【问题标题】:HTTP/2 requests and headers starting with colon以冒号开头的 HTTP/2 请求和标头
【发布时间】:2019-08-13 19:45:17
【问题描述】:

亲爱的 SO 社区你好。

我有一个问题折磨了我好几个月都没有解决。

我正在尝试在 HTTP/2 端点发出请求,该端点使用一些以冒号开头的标头。示例:

:method: "POST"

我尝试过使用 python(hyper, requests)、php(guzzle) 和 js(fetch)。 据推测,我已经使用 js 实现了所需的结果,但 CORS 策略返回给我一个“不透明”的结果。

任何帮助都会很棒!

JS 结果大概是正确的“不透明”

fetch("https://www.example.com/users/sign_in", 
        {
          "credentials":"include",
          "headers":{
            "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
            "accept-language":"en-US,en;q=0.9,el;q=0.8",
            "cache-control":"max-age=0",
            "content-type":"application/x-www-form-urlencoded",
            "accept-encoding": "gzip, deflate, br",
            "content-length": 614,
            "origin": "https://www.example.com",
            "sec-fetch-mode": "navigate",
            "sec-fetch-site": "same-origin",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36",
          },
          "referrer":"https://www.example.com/users/sign_in",
          "referrerPolicy":"no-referrer-when-downgrade",
          "redirect": "follow",
          "body":"..."
          "method":"POST",
          "mode":"no-cors",
          ":authority": "www.example.com",
          ":method": "POST",
          ":path": "/users/sign_in",
          ":scheme": "https"
        })

Python 结果 500 或 404

 context = tls.init_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE
    with HTTP20Connection('www.example.com', port=443, ssl_context=context) as c:
        headers = {
            ":authority": "www.example.com",
            ":method": "GET",
            ":path": "/users/sign_in",
            ":scheme": "https",
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
            "accept-encoding": "gzip, deflate, br",
            "accept-language": "en-US,en;q=0.9,el;q=0.8",
            "sec-fetch-mode": "navigate",
            "sec-fetch-site": "none",
            "sec-fetch-user": "?1",
            "upgrade-insecure-requests": "1",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
        }

        c.request('GET', 'www.example.com/users/sign_in', headers=headers)

PHP 结果 500 或 curl 错误 55

$jar = new CookieJar;
    $client = new Client([
        // Base URI is used with relative requests
        'cookies' => $jar,
        'version' => 2.0,
        'debug' => fopen('php://stderr', 'w'),
    ]);

    $client->request('GET', 'https://www.example.com/users/sign_in');

    $response = $client->request('POST', 'https://www.example.com/users/sign_in', [
        'headers' => [
            ":authority"=> "www.example.com",
            ":method"=> "POST",
            ":path"=> "/users/sign_in",
            ":scheme"=> "https",
            "accept"=> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
            "accept-encoding"=> "gzip, deflate, br",
            "accept-language"=> "en-US,en;q=0.9,el;q=0.8",
            "cache-control"=> "max-age=0",
            "content-length"=> "616",
            "content-type"=> "application/x-www-form-urlencoded",
            "origin"=> "https://www.example.com",
            "referer"=> "https://www.example.com/users/sign_in",
            "sec-fetch-mode"=> "navigate",
            "sec-fetch-site"=> "same-origin",
            "sec-fetch-user"=> "?1",
            "upgrade-insecure-requests"=> "1",
            "user-agent"=> "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
        ],
        'form_params' => [ ... ],
        'version' => 2.0,
        'allow_redirects' => true
    ]);

【问题讨论】:

  • 我认为标题字段不能以: 开头。这是标头名称和值之间的分隔符。
  • 看起来您尝试使用的标头只是 URL 中的重复字段。是什么让您认为这是必要的?
  • 感谢两位的回复。正如您在此处imgur.com/MKuSvar devtools 的屏幕截图中看到的那样,标头包含在请求中。如果没有标头,请求将返回 404 或 500 响应。
  • 那些不是真正的标头,它只是开发人员工具显示 HTTP 请求行详细信息的方式。开头的冒号是表示它们不是真实的方式。
  • @Barmar 那么为什么使用 JS 脚本,当它们不存在时我得到 500 响应,而当存在请求时,请求就正常了?

标签: javascript php python request


【解决方案1】:

这些是 HTTP/2 伪标头,适用于 HTTP/2 流中的请求和响应。 HTTP/2 创建从每个不同的源端点到服务器的单个持久连接。该连接向端点传输多个请求和响应;这些被解析为“帧”并作为“流”传输。 HTTP/2 可以同时交织来自多个请求和响应流的帧,以获得巨大的性能优势。 intro to http/2

伪标头适用于流;一组不同的标头适用于连接本身。为请求定义了四个伪标头::method、:scheme、:authority 和:path。不允许其他人。这 4 个必须包含在每个请求标头块中,并且它们必须位于任何其他标头之前:

"所有伪头域必须出现在头块之前 常规标题字段。任何包含 出现在头块中的伪头字段 标头字段必须被视为格式错误(第 8.1.2.6 节)。" http2 spec

我不熟悉“获取”如何实现标头,但在您上面的代码中,您似乎在标头块之外有伪标头,它们被放置在最后。可能搞砸了。

【讨论】:

    猜你喜欢
    • 2020-02-12
    • 2017-10-07
    • 2015-07-13
    • 1970-01-01
    • 2016-06-29
    • 2017-01-03
    • 2019-01-08
    • 1970-01-01
    • 2012-01-06
    相关资源
    最近更新 更多