HTTP和Java - 用gzip编码修改的头文件

时间:2016-10-15 12:43:57

标签: java http

我的http通讯遇到了奇怪的问题。我写了非常简单的http服务器和客户端。

Http服务器:

public class SimpleHttpServer {

    public void run() throws IOException {
        final ServerSocket serverSocket = new ServerSocket(8080);

        while(true)
        {
            final Socket connectionSocket = serverSocket.accept();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        try(BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
                            DataOutputStream out = new DataOutputStream(connectionSocket.getOutputStream())){

                            System.out.println(in.readLine());

                            String line = null;
                            while((line = in.readLine()) != null && !line.trim().isEmpty()){
                                System.out.println(line);
                            }

                            byte[] message = loadFile(); //load some gzipped jpg image from disk

                            out.write(ascii("HTTP/1.1 200 OK\n"));
                            out.write(ascii("Content-Type: image/jpg\n"));
                            out.write(ascii(String.format("Content-Length: %s\n", message.length)));
                            out.write(ascii("content-encoding: gzip\n"));
                            out.write(ascii("\n"));
                            out.write(message);

                        }
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

Http客户端:

public class SimpleHttpClient {

    public void run() throws IOException {
        String host = "localhost";
        int port = 8080;

        Socket socket = new Socket(host, port);
        try (OutputStream out = socket.getOutputStream()) {
            out.write(ascii("GET / HTTP/1.1\n"));
            out.write(ascii("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36\n"));
            out.write(ascii("Accept-Encoding: gzip, deflate, sdch\n"));
            out.write(ascii("Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4\n"));
            out.write(ascii("\n"));


            try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                String line = null;

                while ((line = in.readLine()) != null && !line.trim().isEmpty()) {
                    System.out.println(line);
                }
            }
        }
    }
}

所以,当我删除带有用户代理标题的行时,我会得到我期望的结果:

HTTP/1.1 200 OK 
Content-Type: image/jpg 
Content-Length: 378632
content-encoding: gzip

这很清楚也很明显。

但是当这个标题出现时,答案是不同的:

HTTP/1.1 200 OK
Content-Type: image/jpg
Transfer-Encoding: chunked

我在服务器端没有改变任何东西。在每个请求中,我发送相同的响应。用户代理是从chrome浏览器复制的。

两个实现都是普通的java套接字,而不是第三方libriares。 所以我的问题是:它是如何发生的?有什么东西被缓存了吗?但在哪里?

请不要查看代码质量。这只是一个例子。我不想在生产中使用它:)

编辑1:

private byte[] ascii(String value) throws UnsupportedEncodingException {
    return value.getBytes(StandardCharsets.US_ASCII);
}

编辑2:

我做过一些研究。当用户代理包含" AppleWebKit",协议名称为HTTP且端口为80或8080时,就会发生这种情况。 此外,它发生在Windows 10上(我在两台不同的计算机上查看)。在Linux(Ubuntu 16.04和Debian 8)上,一切都很好。

也许我应该改变问题的标题?但是如何用一个简短的句子来解释这个问题?

0 个答案:

没有答案