Description
I was trying to use cpp-httplib to communicate with my local docker daemon using sock file. There is a possibility to do that according to this
After testing my connection with curl I was pretty sure that it will be easy to do however problem (IMO) is caused by the fact that docker engine is expecting to receive request on endpoint http://localhost/v1.39/images/json
and not /v1.39/images/json
. I can not see how to do that using httplib::Client
object because its only argument is a path to sock file.
Also curl is working with that socket curl --unix-socket /run/docker.sock /v1.39/images/json
I am attaching a short example comparing httplib and raw socket usage
#if defined(HTTP_LIB)
#include <httplib.h>
#include <iostream>
#include <sys/socket.h>
#else
#include <iostream>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <cstring>
#endif
int main(){
std::string dockerSocket("/run/docker.sock");
std::string endpoint("http://localhost/v1.39/images/json");
#if defined(HTTP_LIB)
httplib::Client cli(dockerSocket);
cli.set_address_family(AF_UNIX);
auto res = cli.Get(endpoint);
if (res && res->status == 200) {
std::cout << "Response from Docker Engine: "<< res->body << std::endl;
} else {
if (res) {
std::cout << "HTTP Error: " << res->status << std::endl;
} else {
std::cout << "Connection failed: " << httplib::to_string(res.error()) << std::endl;
}
}
#else
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
try{
const char* data = "GET http://localhost/v1.39/images/json HTTP/1.1\r\n"
"Host: localhost\r\n"
"Connection: close\r\n\r\n";
if (sockfd < 0) {
throw std::runtime_error("Failed to create socket");
}
sockaddr_un addr{};
addr.sun_family = AF_UNIX;
std::strncpy(addr.sun_path, dockerSocket.c_str(), sizeof(addr.sun_path) - 1);
if (connect(sockfd, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) < 0) {
throw std::runtime_error("Failed to connect to the socket");
}
if (send(sockfd, data, strlen(data), 0) < 0) {
throw std::runtime_error("Failed to send data");
}
char buffer[4096] = {};
while(true)
{
ssize_t bytesReceived = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
if (bytesReceived <= 0) {
break;
}
buffer[bytesReceived] = '\0';
std::cout << buffer << std::endl;
}
}
catch(const std::exception &ex){
std::cout << "Error: " << ex.what() << std::endl;
}
if (sockfd >= 0){
close(sockfd);
}
#endif
return 0;
}
g++ example.cpp && ./a.out
HTTP/1.1 200 OK
Api-Version: 1.46
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/27.1.2 (linux)
Date: Tue, 14 Jan 2025 17:08:12 GMT
Connection: close
Transfer-Encoding: chunked
f6b
g++ example.cpp -DHTTP_LIB && ./a.out
HTTP Error: 400
I am using httplib 0.18.3 from vcpkg, but I also tried with trunk version. My GCC is 14.2.1 and Docker 27.1.2