我正在为Docker编写API客户端。我从文档中了解到API是Restful / HTTP,但是如果连接到本地守护程序,则必须通过公开的 unix socket 来完成。
这一切似乎都有效,我打开一个套接字,发送一个HTTP请求(尊重specification),我收到预期的响应,,但也会立即响应400 BAD REQUEST
。
以下是请求:
GET /info HTTP/1.1
Host: localhost
Accept: application/json
这就是我得到的:
HTTP/1.1 200 OK
Api-Version: 1.30
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/17.06.1-ce (linux)
Date: Thu, 01 Feb 2018 18:53:18 GMT
Transfer-Encoding: chunked
892
{"ID":"6MGE:35TO:BI..." ...}
0
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request
首先,我认为我身边有一个错误而且我以某种方式发送了2个请求,但是我enabled debugging并且跟踪了sudo journalctl -fu docker.service
的日志,并且只收到了一个请求...记录至少一个GET /info
。我还调试了代码并发送了1个单一请求。
非常感谢任何提示!
编辑:这是客户的代码:
final StringBuilder hdrs = new StringBuilder();
for(final Map.Entry<String, String> header : headers) {
hdrs.append(header.getKey() + ": " + header.getValue())
.append("\r\n");
}
final String request = String.format(
this.template(), method, home, hdrs, this.readContent(content)
);
final UnixSocketChannel channel = UnixSocketChannel.open(
new UnixSocketAddress(this.path)
);
final PrintWriter writer = new PrintWriter(
Channels.newOutputStream(channel)
);
writer.print(request);
writer.flush();
final InputStreamReader reader = new InputStreamReader(
Channels.newInputStream(channel)
);
CharBuffer result = CharBuffer.allocate(1024);
reader.read(result);
result.flip();
System.out.println("read from server: " + result.toString());
答案 0 :(得分:1)
看起来你在标题和正文之间有一个额外的CRLF。
private String template() {
final StringBuilder message = new StringBuilder();
message
.append("%s %s HTTP/1.1\r\n")
.append("Host: localhost").append("\r\n")
.append("%s")
.append("\r\n").append("\r\n") //one of these is superfluous, as each header line ends with "\r\n" itself
.append("%s");
return message.toString();
}
在标题后删除一个append("\r\n")
,看看会发生什么。
答案 1 :(得分:-1)
固定。最初,我认为问题出在行结尾(它们应该是\ n而不是\ r \ n)。事实证明,400 BAD REQUEST发生了,因为Connection: close
标题丢失了,而Request收到响应后立即关闭了。
更多详情here。