【发布时间】:2018-03-20 10:25:10
【问题描述】:
我一直在尝试通过 HTTP2 为原生 ES 模块提供服务的方法。几乎所有东西都运行良好(在支持的情况下),但有一个我无法理解的怪癖。
给定 / 文档的请求,我推送直接或间接已知为该文档依赖项的资源。在这种情况下,最终会成为通过推送捎带的三个额外资源:
- /index.css(依赖于
<link href ...>) - /index.js(通过
<script type="module" src ...> - /routes.js(间接依赖,由
index.js导入)
所有三个资源似乎都从服务器端成功推送。然而,Chrome 对“/index.js”提出了第二个请求,尽管第一个请求是推送的。其他两种资源均未请求;这些推送的响应似乎得到了正确的确认。
起初我认为这是 Chrome 的一个怪癖,只是新功能的一个粗略的边缘。但是当启用模块支持标志时,在 Firefox 中也会出现相同的行为,这让我怀疑这是不是出于某种原因故意的。
从后端对应上述请求的日志记录:
RECEIVED REQUEST: GET /
...PUSHING /index.css
...PUSHING /index.js
...PUSHING /routes.js
RECEIVED REQUEST: GET /index.js
...PUSHING /routes.js
按照@sbordet 的说明进行操作:以下是两个请求的记录(很高兴知道这些内容可以在 Chrome 中进行自省!):
第一个请求 (/)
3067: HTTP2_SESSION
death.tips:443 (DIRECT)
Start Time: 2017-10-09 10:49:24.597
t=304289 [st= 0] +HTTP2_SESSION [dt=?]
--> host = "death.tips:443"
--> proxy = "DIRECT"
t=304289 [st= 0] HTTP2_SESSION_INITIALIZED
--> protocol = "h2"
--> source_dependency = 3064 (SOCKET)
t=304289 [st= 0] HTTP2_SESSION_SEND_SETTINGS
--> settings = ["[id:1 (SETTINGS_HEADER_TABLE_SIZE) value:65536]","[id:3 (SETTINGS_MAX_CONCURRENT_STREAMS) value:1000]","[id:4 (SETTINGS_INITIAL_WINDOW_SIZE) value:6291456]"]
t=304289 [st= 0] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = 15663105
--> window_size = 15728640
t=304289 [st= 0] HTTP2_SESSION_SEND_WINDOW_UPDATE
--> delta = 15663105
--> stream_id = 0
t=304289 [st= 0] HTTP2_SESSION_SEND_HEADERS
--> exclusive = true
--> fin = true
--> has_priority = true
--> :method: GET
:authority: death.tips
:scheme: https
:path: /
pragma: no-cache
cache-control: no-cache
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3236.0 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
--> parent_stream_id = 0
--> source_dependency = 3060 (HTTP_STREAM_JOB)
--> stream_id = 1
--> weight = 256
t=304310 [st=21] HTTP2_SESSION_RECV_SETTINGS
t=304310 [st=21] HTTP2_SESSION_SEND_SETTINGS_ACK
t=304313 [st=24] HTTP2_SESSION_RECV_SETTINGS_ACK
t=304336 [st=47] HTTP2_SESSION_RECV_PUSH_PROMISE
--> :scheme: https
:authority: death.tips
:path: /index.css
:method: GET
--> id = 1
--> promised_stream_id = 2
t=304336 [st=47] HTTP2_STREAM_SEND_PRIORITY
--> exclusive = true
--> parent_stream_id = 1
--> stream_id = 2
--> weight = 110
t=304336 [st=47] HTTP2_SESSION_RECV_PUSH_PROMISE
--> :scheme: https
:authority: death.tips
:path: /index.js
:method: GET
--> id = 1
--> promised_stream_id = 4
t=304336 [st=47] HTTP2_STREAM_SEND_PRIORITY
--> exclusive = true
--> parent_stream_id = 2
--> stream_id = 4
--> weight = 110
t=304336 [st=47] HTTP2_SESSION_RECV_PUSH_PROMISE
--> :scheme: https
:authority: death.tips
:path: /routes.js
:method: GET
--> id = 1
--> promised_stream_id = 6
t=304336 [st=47] HTTP2_STREAM_SEND_PRIORITY
--> exclusive = true
--> parent_stream_id = 4
--> stream_id = 6
--> weight = 110
t=304336 [st=47] HTTP2_SESSION_RECV_HEADERS
--> fin = false
--> :status: 200
cache-control: public, max-age=0
content-encoding: deflate
content-length: 388
content-type: text/html; charset=utf-8
date: Mon, 09 Oct 2017 14:49:24 GMT
etag: "c3QDLn1lTsAqsErFvMgM3bEsUsY="
last-modified: Mon, 09 Oct 2017 14:43:24 GMT
--> stream_id = 1
t=304336 [st=47] HTTP2_SESSION_RECV_HEADERS
--> fin = false
--> :status: 200
cache-control: public, max-age=0
content-encoding: deflate
content-length: 88
content-type: text/css
date: Mon, 09 Oct 2017 14:49:24 GMT
etag: "/qkigeCvJgEE+0+5YhHLgByhKL0="
last-modified: Mon, 09 Oct 2017 14:43:24 GMT
--> stream_id = 2
t=304336 [st=47] HTTP2_SESSION_RECV_HEADERS
--> fin = false
--> :status: 200
cache-control: public, max-age=0
content-encoding: deflate
content-length: 60
content-type: text/javascript
date: Mon, 09 Oct 2017 14:49:24 GMT
etag: "/+cUWoFWkafsB6vSI5wBuB7v4Tk="
last-modified: Mon, 09 Oct 2017 14:43:24 GMT
--> stream_id = 4
t=304336 [st=47] HTTP2_SESSION_RECV_HEADERS
--> fin = false
--> :status: 200
cache-control: public, max-age=0
content-encoding: deflate
content-length: 64
content-type: text/javascript
date: Mon, 09 Oct 2017 14:49:24 GMT
etag: "2ZM3pEXqn9z1d5tkBr2x5kdHsGk="
last-modified: Mon, 09 Oct 2017 14:43:24 GMT
--> stream_id = 6
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = false
--> size = 388
--> stream_id = 1
t=304336 [st=47] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = -388
--> window_size = 15728252
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = true
--> size = 0
--> stream_id = 1
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = false
--> size = 88
--> stream_id = 2
t=304336 [st=47] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = -88
--> window_size = 15728164
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = true
--> size = 0
--> stream_id = 2
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = false
--> size = 60
--> stream_id = 4
t=304336 [st=47] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = -60
--> window_size = 15728104
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = true
--> size = 0
--> stream_id = 4
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = false
--> size = 64
--> stream_id = 6
t=304336 [st=47] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = -64
--> window_size = 15728040
t=304336 [st=47] HTTP2_SESSION_RECV_DATA
--> fin = true
--> size = 0
--> stream_id = 6
t=304337 [st=48] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = 388
--> window_size = 15728428
t=304342 [st=53] HTTP2_STREAM_ADOPTED_PUSH_STREAM
--> stream_id = 2
--> url = "https://death.tips/index.css"
t=304343 [st=54] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = 88
--> window_size = 15728516
第二个请求 (/index.js)
3085: HTTP2_SESSION
death.tips:443 (DIRECT)
Start Time: 2017-10-09 10:49:24.694
t=304386 [st= 0] +HTTP2_SESSION [dt=?]
--> host = "death.tips:443"
--> proxy = "DIRECT"
t=304386 [st= 0] HTTP2_SESSION_INITIALIZED
--> protocol = "h2"
--> source_dependency = 3084 (SOCKET)
t=304386 [st= 0] HTTP2_SESSION_SEND_SETTINGS
--> settings = ["[id:1 (SETTINGS_HEADER_TABLE_SIZE) value:65536]","[id:3 (SETTINGS_MAX_CONCURRENT_STREAMS) value:1000]","[id:4 (SETTINGS_INITIAL_WINDOW_SIZE) value:6291456]"]
t=304386 [st= 0] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = 15663105
--> window_size = 15728640
t=304386 [st= 0] HTTP2_SESSION_SEND_WINDOW_UPDATE
--> delta = 15663105
--> stream_id = 0
t=304386 [st= 0] HTTP2_SESSION_SEND_HEADERS
--> exclusive = true
--> fin = true
--> has_priority = true
--> :method: GET
:authority: death.tips
:scheme: https
:path: /index.js
pragma: no-cache
cache-control: no-cache
origin: https://death.tips
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3236.0 Safari/537.36
accept: */*
referer: https://death.tips/
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
--> parent_stream_id = 0
--> source_dependency = 3080 (HTTP_STREAM_JOB)
--> stream_id = 1
--> weight = 220
t=304405 [st=19] HTTP2_SESSION_RECV_SETTINGS
t=304405 [st=19] HTTP2_SESSION_SEND_SETTINGS_ACK
t=304409 [st=23] HTTP2_SESSION_RECV_SETTINGS_ACK
t=304409 [st=23] HTTP2_SESSION_RECV_PUSH_PROMISE
--> :scheme: https
:authority: death.tips
:path: /routes.js
:method: GET
--> id = 1
--> promised_stream_id = 2
t=304409 [st=23] HTTP2_STREAM_SEND_PRIORITY
--> exclusive = true
--> parent_stream_id = 1
--> stream_id = 2
--> weight = 110
t=304409 [st=23] HTTP2_SESSION_RECV_HEADERS
--> fin = false
--> :status: 200
cache-control: public, max-age=0
content-encoding: deflate
content-length: 60
content-type: text/javascript
date: Mon, 09 Oct 2017 14:49:24 GMT
etag: "/+cUWoFWkafsB6vSI5wBuB7v4Tk="
last-modified: Mon, 09 Oct 2017 14:43:24 GMT
--> stream_id = 1
t=304409 [st=23] HTTP2_SESSION_RECV_HEADERS
--> fin = false
--> :status: 200
cache-control: public, max-age=0
content-encoding: deflate
content-length: 64
content-type: text/javascript
date: Mon, 09 Oct 2017 14:49:24 GMT
etag: "2ZM3pEXqn9z1d5tkBr2x5kdHsGk="
last-modified: Mon, 09 Oct 2017 14:43:24 GMT
--> stream_id = 2
t=304409 [st=23] HTTP2_SESSION_RECV_DATA
--> fin = false
--> size = 60
--> stream_id = 1
t=304409 [st=23] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = -60
--> window_size = 15728580
t=304409 [st=23] HTTP2_SESSION_RECV_DATA
--> fin = true
--> size = 0
--> stream_id = 1
t=304409 [st=23] HTTP2_SESSION_RECV_DATA
--> fin = false
--> size = 64
--> stream_id = 2
t=304409 [st=23] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = -64
--> window_size = 15728516
t=304409 [st=23] HTTP2_SESSION_RECV_DATA
--> fin = true
--> size = 0
--> stream_id = 2
t=304410 [st=24] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = 60
--> window_size = 15728576
t=304412 [st=26] HTTP2_STREAM_ADOPTED_PUSH_STREAM
--> stream_id = 2
--> url = "https://death.tips/routes.js"
t=304413 [st=27] HTTP2_SESSION_UPDATE_RECV_WINDOW
--> delta = 64
--> window_size = 15728640
【问题讨论】:
-
如果它是相关的:后端是节点,我使用 userland http2/SPDY 包和新的 node-core http2 模块观察到这种行为。
-
截图中没有显示
index.js被浏览器先推送再请求。推送index.js可能会出现一些问题,以便 Chrome 将其丢弃。您能否使用 Chrome 重试,然后:转到 chrome://net-internals,然后在左侧面板中选择“HTTP/2”,在中间面板中选择与您的服务器的连接。在右侧面板上,您应该会看到 HTTP/2 流量的详细转储,包括推送。在此处报告以供进一步分析。 -
谢谢 sbordet,我没有意识到有内置的工具。已添加交流的 Chrome 记录以回答。
标签: http2 es6-modules