Docker API返回200 OK然后400 BAD REQUEST

时间:2018-02-01 19:02:04

标签: rest sockets http docker

我正在为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());

2 个答案:

答案 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