HttpURLConnection 属性顺序

HttpURLConnection properties order

我需要申请特定的 headers 订单。 所以我按要求的顺序为每个 属性 调用 setRequestProperty:

        URL url = new URL(urlString);
        HttpURLConnection request = (HttpURLConnection) url.openConnection();
        request.setRequestMethod("GET");
        request.setRequestProperty("Host", "myhostname.com");
        request.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0");
        request.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
        request.setRequestProperty("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3");
        request.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
        request.setRequestProperty("Connection", "keep-alive");
        request.setRequestProperty("Cookie", cookies);
        request.setRequestProperty("Upgrade-Insecure-Requests", "1");
        request.setRequestProperty("Cache-Control", "max-age=0");

但实际(嗅探)请求看起来像:

    GET /api/apitest&code=1 HTTP/1.1\r\n
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0\r\n
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n
    Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\r\n
    Accept-Encoding: gzip, deflate, br\r\n
    Cookie: <cookie>\r\n
    Upgrade-Insecure-Requests: 1\r\n
    Cache-Control: max-age=0\r\n
    Host: myhostname.com\r\n
    Connection: keep-alive\r\n

有没有办法保持headers顺序不变?

所以我使用 RawHttp 解决了它:

RawHttp http = new RawHttp();
RawHttpRequest httpRequest = http.parseRequest("GET /api/apitest&code="+code+" HTTP/1.1\r\n" +
                "Host:myhostname.com\r\n" +
                "User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0\r\n" +
                "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n" +
                "Accept-Language:ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\r\n" +
                "Accept-Encoding:gzip, deflate, br\r\n" +
                "Connection:keep-alive\r\n" +
                "Cookie:" + cookies + "\r\n" +
                "Upgrade-Insecure-Requests:1\r\n" +
                "Cache-Control:max-age=0");

        URL url = new URL(api_url);
        Socket httpsSocket = HttpsURLConnection.getDefaultSSLSocketFactory().createSocket(api_url.getHost(),  443);

        httpRequest.writeTo(httpsSocket.getOutputStream());
        RawHttpResponse httpResponse = http.parseResponse(httpsSocket.getInputStream());

        BodyReader body = httpResponse.getBody().get();
        String response = body.decodeBodyToString(StandardCharsets.UTF_8);

Body 可以使用

检查是否存在
httpResponse.getBody().isPresent()

现在 header 的顺序没有改变,这个 non-RFC 兼容的服务器正确回答。

为了显示结果,我已将端口更改为 80,但其他一切都相同:

Frame 6099: 680 bytes on wire (5440 bits), 680 bytes captured (5440 bits) on interface \Device\NPF_{28393799-9889-4CF5-B65C-ED851CC47ECC}, id 0
Ethernet II, Src: ASUSTekC_<MAC>, Dst: D-Link_<MAC>
Internet Protocol Version 4, Src: 192.168.1.3, Dst: <IP>
Transmission Control Protocol, Src Port: 58530, Dst Port: 80, Seq: 4, Ack: 1, Len: 626
[2 Reassembled TCP Segments (629 bytes): #6096(3), #6099(626)]
Hypertext Transfer Protocol
    GET /api/apitest&code=1 HTTP/1.1\r\n
    Host: myhostname.com\r\n
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0\r\n
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n
    Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\r\n
    Accept-Encoding: gzip, deflate, br\r\n
    Connection: keep-alive\r\n
    Cookie: <cookie>\r\n
    Upgrade-Insecure-Requests: 1\r\n
    Cache-Control: max-age=0\r\n
    \r\n
    [Full request URI: http://myhostname.com/api/apitest&code=1]
    [HTTP request 1/1]
    [Response in frame: 6101]

然后我移动了主机 header 并相应地更改了捕获的数据包:

Frame 78: 680 bytes on wire (5440 bits), 680 bytes captured (5440 bits) on interface \Device\NPF_{28393799-9889-4CF5-B65C-ED851CC47ECC}, id 0
Ethernet II, Src: ASUSTekC_<MAC>, Dst: D-Link_<MAC>
Internet Protocol Version 4, Src: 192.168.1.3, Dst: <IP>
Transmission Control Protocol, Src Port: 58619, Dst Port: 80, Seq: 4, Ack: 1, Len: 626
[2 Reassembled TCP Segments (629 bytes): #76(3), #78(626)]
Hypertext Transfer Protocol
    GET /api/apitest&code=1 HTTP/1.1\r\n
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0\r\n
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n
    Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\r\n
    Accept-Encoding: gzip, deflate, br\r\n
    Connection: keep-alive\r\n
    Cookie: <cookie>\r\n
    Host: myhostname.com\r\n
    Upgrade-Insecure-Requests: 1\r\n
    Cache-Control: max-age=0\r\n
    \r\n
    [Full request URI: http://myhostname.com/api/apitest&code=1]
    [HTTP request 1/1]
    [Response in frame: 80]