Я пытаюсь связаться с Docker Daemon, используя ядро dotnet.Я использовал это руководство, которое работает, как ожидалось.
Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь отправить данные POST в конечную точку, чтобы изменить сервис докера (в основном я хотел бы иметь возможность масштабировать сервисы увеличения / уменьшения в этом случае), я 'используя тот же метод для отправки данных в сокет, но изменив содержимое:
Это метод GET для получения запущенных служб, который работает:
public string GetAllServices()
{
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
var unixEndpoint = new UnixEndPoint("/var/run/docker.sock"); // this address is where the socket exists
socket.Connect(unixEndpoint); // connect to the socket
// create a request like this in HTTP spec format
var request = $"GET /v1.24/services "
+ "HTTP/1.1\r\n"
+ "Host: unix\r\n"
+ "Content-Length: 0\r\n"
+ "accept-encoding: gzip\r\n"
+ "Connection: keep-alive\r\n"
+ "Accept: */*\r\n"
+ "\r\n";
// convert the request into byte data
byte[] requestBytes = Encoding.ASCII.GetBytes(request);
// send the request to the socket
socket.Send(requestBytes);
// get the header
while (true)
{
var headerLine = ReceiveUntilCRLF(socket);
if (headerLine == "\r\n")
{
break;
}
if (headerLine == "HTTP/1.1 400 Bad Request\r\n")
{
break;
}
}
// get the payload
var payload = "";
byte[] chunkLengthBytes = new byte[512];
var chunkLength = 0;
while (true)
{
// get the length of the next chunk
var temp = ReceiveUntilCRLF(socket);
// get the chunk
byte[] chunkBytes = new byte[chunkLength];
payload += ReceiveUntilCRLF(socket);
// append chunk to payload string
if (payload.EndsWith("\r\n"))
{
break;
}
}
// in the end, disconnect and close the socket to cleanup
socket.Disconnect(false);
socket.Close();
return payload;
}
Затем для обновления службы:
public void UpdateService(Services currentServiceState)
{
bool badRequest = false;
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
var unixEndpoint = new UnixEndPoint("/var/run/docker.sock"); // this address is where the socket exists
socket.Connect(unixEndpoint); // connect to the socket
var body = JsonConvert.SerializeObject(currentServiceState, Formatting.Indented);
string request = CreateRequestString($"/v1.24/services/{currentServiceState.Spec.Name}/update?version={currentServiceState.Version.Index}", body);
// convert the request into byte data
byte[] requestBytes = Encoding.ASCII.GetBytes(request);
// send the request to the socket
socket.Send(requestBytes);
// get the header
while (true)
{
var headerLine = ReceiveUntilCRLF(socket);
if (headerLine == "\r\n")
{
break;
}
if (headerLine == "HTTP/1.1 400 Bad Request\r\n")
{
badRequest = true;
string errorResponse = headerLine;
while (true)
{
var newLine = ReceiveUntilCRLF(socket);
errorResponse += newLine;
if (newLine == "\r\n")
{
Console.WriteLine($"{errorResponse}");
break;
}
}
break;
}
}
if(!badRequest)
{
// get the payload
var payload = "";
byte[] chunkLengthBytes = new byte[512];
var chunkLength = 0;
while (true)
{
// get the length of the next chunk
var temp = ReceiveUntilCRLF(socket);
// get the chunk
byte[] chunkBytes = new byte[chunkLength];
payload += ReceiveUntilCRLF(socket);
// append chunk to payload string
Console.Write(payload);
if (payload.EndsWith("\r\n"))
{
break;
}
}
}
// in the end, disconnect and close the socket to cleanup
socket.Disconnect(false);
socket.Close();
}
и CreateRequestString () выглядит следующим образом:
public string CreateRequestString(string endpoint, string content)
{
int contentLength = 0;
if (content.Length > 0)
{
contentLength = Encoding.UTF8.GetBytes(content).Length;
}
var requestString = $"POST {endpoint} "
+ "HTTP/1.1\r\n"
+ "Host: unix\r\n"
+ "accept-encoding: gzip\r\n"
+ "Connection: keep-alive\r\n"
+ $"content-length: {contentLength}\r\n"
+ "Accept: */*\r\n"
+ "\r\n";
if (content.Length > 0)
{
requestString += $"{JsonConvert.DeserializeObject(content)}";
}
return requestString;
}
, который возвращает неверный запрос 400.
Мне интересно, если либо: 1. AmЯ правильно рассчитал длину контента?2. Я правильно строю строку запроса?3. Есть что-то еще, что я пропустил?
Спасибо