/
358.txt
470 lines (347 loc) · 26 KB
/
358.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
[114] [DFN[server push]] は、[[クライアント]]から明示的な[[要求]]がなくても、
予め[[サーバー]]から[[応答]]を送信するものです。
* 仕様書
[REFS[
- [78] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-2.2>
- [79] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-4.1>
- [82] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-4.2>
- [83] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-5.1>
- [87] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-5.3.5>
- [29] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.1>
- [1] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.5.2>
- [8] '''[CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.6>'''
- [31] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-7>
- [34] '''[CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-8.2>'''
- [70] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-10.4>
- [76] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-10.5>
]REFS]
* 意味
[35] [[HTTP/2]] [[server push]] は、
[[応答]]とそれに対応する「[RUBYB[約束]@en[promised]]」[[要求]]を、
先に[[クライアント]]が開始した[[要求]]に関連付ける形で[[サーバー]]から予め送信
([[push]]) するものです [SRC[>>34]]。
[36] [[server push]] は、[[クライアント]]が元の[[要求]]に対する[[応答]]を完全に処理するために当該[[応答]]が必要になるであろうとわかっている場合に便利です
[SRC[>>34]]。
[55] [[server push]] は、意味的には[[クライアント]]の[[要求]]に[[サーバー]]が[[応答]]を返す通常の場合と同じですが、
[[要求]]を[[クライアント]]ではなく[[サーバー]]が ([[クライアント]]へと)
[CODE[[[PUSH_PROMISE]]]] [[フレーム]]により送信します [SRC[>>34]]。
[52] [[クライアント]]は、 [[push]] できません [SRC[>>34]]。
* 約束要求
[44] [[サーバー]]から[[クライアント]]へと送信する[[要求]]を、
[DFN[[RUBYB[[[約束要求]]]@en[promised request]]]]といいます。
[39] [[約束要求]]は、[[要求本体]]を含んでは[['''なりません''']] [SRC[>>34]]。
[56] [CODE[[[PUSH_PROMISE]]]] [[フレーム]] (と [CODE[[[CONTINUATION]]]]
[[フレーム]]) が、[[要求]]の [[header block]] を含みます。
[[要求]]の[[ヘッダー]]を[[妥当]]かつ完全に含まなければ[['''なりません''']]。 [SRC[>>34]]
[49] [[サーバー]]は、当該[[サーバー]]が権限を有する ([[authoritative]])
[CODE(HTTP)@en[[[:authority]]]] [[疑似ヘッダー]]値を含めなければ[['''なりません''']]
[SRC[>>34]]。
;; [[HTTP接続]]も参照。
[37] [[約束要求]]は、[[キャッシュ可能]]でなければ[['''なりません''']] [SRC[>>34]]。
[38] [[約束要求]]は、[[安全]]でなければ[['''なりません''']] [SRC[>>34]]。
[58] [[サーバー]]は、 [CODE(HTTP)@en[[[:method]]]] [[疑似ヘッダー]]に[[安全]]で[[キャッシュ可能]]な[[要求メソッド]]を指定しなければ[['''なりません''']] [SRC[>>34]]。
[61] [[サーバー]]は、約束された[[応答]]を参照する[[フレーム]]を送信する前に、
[CODE(HTTP)@en[[[PUSH_PROMISE]]]] [[フレーム]]を送信する[['''べきです''']]。
これにより[[クライアント]]が [CODE[[[PUSH_PROMISE]]]] [[フレーム]]を送信する前に別途[[要求]]を発行することを防ぐことができます。 [SRC[>>34]]
[EG[
[62] 例えば [CODE(HTTP)@en[[[DATA]]]] [[フレーム]]に[[画像]]を埋め込むリンクが含まれているなら、
それよりも前に当該[[画像]]の [CODE[[[PUSH_PROMISE]]]] [[フレーム]]を送信することにできます。 [SRC[>>34]]
]EG]
[71] 複数の[[著者]]の[[資源]]を提供する[[サーバー]]は、
他の[[著者]]の管轄下のはずの[[資源]]を[[プッシュ]]できてしまわないようにしなければ[['''なりません''']] [SRC[>>70]]。
;; [72] [[レンタルサーバー]]や[[クラウド]]サービスの[[逆串]]などで注意が必要です。
* プッシュ応答
[48] [[約束要求]]に続いて[[サーバー]]から[[クライアント]]へと送信する[[応答]]を、
[DFN[[RUBYB[プッシュ応答]@en[pushed response]]]]といいます。
[65] [[サーバー]]は [CODE[[[PUSH_PROMISE]]]] [[フレーム]]
(と [CODE[[[CONTINUATION]]]] [[フレーム]]) に続けて
(同じ[[ストリーム]]で) [[プッシュ応答]]を配送開始できます [SRC[>>34]]。
* 処理
[60] [[クライアント]]は、[[約束要求]]に完全で妥当な[[ヘッダー]]の集合が含まれていなければ、
[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>34]]。
[40] [[クライアント]]は、[[キャッシュ可能]]でない[[約束要求]]を受信したら、
[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>34]]。
[41] [[クライアント]]は、[[安全]]でない[[約束要求]]を受信したら、
[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>34]]。
[59] [[クライアント]]は、 [CODE(HTTP)@en[[[:method]]]] [[疑似ヘッダー]]に[[安全]]でない[[要求メソッド]]が指定されていれば、
[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>34]]。
;; [43] [[クライアント]]が新しい[[要求メソッド]]が[[安全]]と知っていなければ、
エラーになります [SRC[>>34]]。
[42] [[クライアント]]は、[[要求本体]]の存在を示した[[約束要求]]を受信したら、
[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>34]]。
[50] [[クライアント]]は、[[サーバー]]が権限を有する ([[authoritative]])
か[[プロキシ]]であって対応する[[要求]]に関する[[プッシュ応答]]を提供するよう設定されていることを検証しなければ[['''なりません''']]。
それ以外の値の [CODE(HTTP)@en[[[:authority]]]] [[疑似ヘッダー]]が含まれていたら、
[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>34]]。
[EG[
[69] [[DNS-ID]] または[[共通名]]として [CODE[[[example.com]]]]
が指定された[[証明書]]を使っている[[サーバー]]の場合、
[CODE[https://www.example.org/doc]] の[[プッシュ応答]]を提供してはなりません。 [SRC[>>34]]
]EG]
;; [[HTTP接続]]も参照。
[45] [[プッシュ応答]]は、[[キャッシュ可能]]なら、
[[クライアント]]の [[HTTPキャッシュ]]に[[蓄積]]できます [SRC[>>34]]。
[46] [[プッシュ応答]]は、[[ストリーム]]が [[open]]
である間、[[起源サーバー]]で成功裏に[[検証]]されたものとみなします [SRC[>>34]]。
[47] [[プッシュ応答]]は、[[キャッシュ可能]]でなければ、
[[HTTPキャッシュ]]に[[蓄積]]しては[['''なりません''']]。
別途[[応用]]に提供しても構いません。 [SRC[>>34]]
[51] [[中間器]]は、[[サーバー]]からの [[push]] を[[クライアント]]へと[[転送]]しないことにしても構いません。
また[[サーバー]]から送られてこなくても独自に[[クライアント]]に [[push]]
しても構いません。 [SRC[>>34]]
[66] [[クライアント]]は、 [CODE[[[PUSH_PROMISE]]]] [[フレーム]]を受信し、
[[プッシュ応答]]を受け入れることにしたら、
その[[ストリーム]]が閉じられるまでの間、
その[[応答]]に対する[[要求]]を発行する[['''べきではありません''']] [SRC[>>34]]。
[67] [[クライアント]]は、何らかの理由で[[プッシュ応答]]を受信したくない時や、
[[サーバー]]が[[プッシュ応答]]を送信し始めるまでの時間がかかりすぎている時は、
[CODE[[[RST_STREAM]]]] [[フレーム]]に[[誤り符号]] [CODE[[[CANCEL]]]] や
[CODE[[[REFUSED_STREAM]]]] を指定し、当該[[ストリーム識別子]]を指定して送信できます [SRC[>>34]]。
[73] [[サーバー]]が [[authoritative]] でない[[応答]]を[[キャッシュ]]したり、
使ったりしては[['''なりません''']] [SRC[>>70]]。
;; [74] [[authoritative]] かどうかの判定については、 [[HTTP接続]]の再利用の項を参照。
[EG[
[75] 例えば [CODE[[[example.com]]]] の[[サーバー証明書]]を持つ [[TLS接続]]上で
[CODE[https://example.net/]] の[[応答]]が[[プッシュ]]されても、
使ってはなりません。
]EG]
[30] [[Firefox]] も [[Chrome]] も、異なる[[起源]]の[[約束要求]]を受信した時、
[[ストリームエラー]] [CODE[[[REFUSED_STREAM]]]] とするようです。
[TIME[2015-10-12T10:01:05.800Z]]
[106] [[Firefox]] も [[Chrome]] も、この検査を ([CODE[[[PUSH_PROMISE]]]]
の受信時でも [[fetch]] 時でもなく) 応答の受信時に行うようです。
[TIME[2015-10-12T14:33:56.00Z]]
[111] 同じ [CODE[[[:path]]]] の[[約束要求]]を受信したら、
[[Chrome]] は[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]]、
[[Firefox]] は[[ストリームエラー]] [CODE[[[INTERNAL_ERROR]]]]
とします。この検査は [CODE[[[PUSH_PROMISE]]]] 受信時点で行い、
[[約束ストリーム]]に対して送信します。 [TIME[2015-10-13T02:26:10.300Z]]
[77] [[クライアント]]は、 [[reserved (remote)]] 状態にある[[ストリーム]]の数を制限する[['''べきです''']]。
超過したら[[ストリームエラー]] [CODE[[[ENHANCE_YOUR_CALM]]]]
とできます。 [SRC[>>76]]
* [CODE(HTTP)@en[PUSH_PROMISE]] フレーム
** 意味
[9] [CODE[[[PUSH_PROMISE]]]] [[フレーム]] ([[フレーム型]] [CODE[[[0x5]]]]) は、
[[peer]] に対して[[ストリーム]]を開始することを予め通知するものです [SRC[>>8]]。
[23] [CODE[[[PUSH_PROMISE]]]] によって予約する順序は、その[[ストリーム]]を利用する順序と一致していなくても構いません [SRC[>>8]]。
** 構文
[57] [[ストリーム識別子]]は、[[要求]]が属する[[ストリーム]]を表します [SRC[>>34]]。
0x0 を指定することはできません。
[16] 次の[[フラグ]]があります。
[FIG(list members)[
:[17] [CODE[[[END_HEADERS]]]] ([CODE[[[0x4]]]] = 第2ビット):
設定されていれば、[[header block]] 全体が含まれており、 [CODE[[[CONTINUATION]]]]
[[フレーム]]が続かないことを表します [SRC[>>8]]。
[18] 設定されていなければ、同じ[[ストリーム]]で [CODE[[[CONTINUATION]]]]
[[フレーム]]が続かなければ[['''なりません''']] [SRC[>>8]]。
:[20] [CODE[[[PADDED]]]] ([CODE[[[0x8]]]] = 第3ビット):
設定されていれば、詰め長欄と詰めが存在することを示します [SRC[>>8]]。
]FIG]
[80] 他の[[フラグ]]は、0 でなければ[['''なりません''']]。
[[受信者]]は、無視しなければ[['''なりません''']]。 [SRC[>>79]]
[FIG(packet)[
:width:8
= 1 0
= 1 0
= 1 [CODE[[[END_HEADERS]]]]
= 1 [CODE[[[PADDED]]]]
= 1 0
= 1 0
= 1 0
= 1 0
]FIG]
[11] [[payload]] は、次の欄で構成されます。
[FIG(list members)[
:[12] [RUBYB[[[詰め長]]]@en[Pad Length]]:
[[フレーム]]の詰めの長さを[[バイト]]単位で指定する
8ビットの欄です [SRC[>>8]]。
[CODE[[[PADDED]]]] [[フラグ]]が設定されている場合のみ存在します [SRC[>>8]]。
値は0でも構いません。値が実際の[[詰め]]の長さを超えることは禁止されていませんが、
当然正しく処理できませんし、可能な長さを超えるなら[[接続エラー]]となります。
:[13] [[R]]:
予約されている1ビットです [SRC[>>8]]。
:[10] [DFN[[RUBYB[[[約束ストリームID]]]@en[Promised Stream ID]]]]:
[[送信者]]がで予約する[[ストリーム]]の[[符号無し]]31ビット[[ストリーム識別子]]を示します [SRC[>>8]] ([[ネットワークバイト順]] [SRC[>>78]])。
[[送信者]]が作成する次の[[ストリーム]]の識別子として妥当なものでなければ[['''なりません''']]
[SRC[>>8]]。 [[idle]] 状態でなければなりません [SRC[>>8]]。
これは[RUBYB[関連付けられた]@en[associated]][[ストリーム]]を表します [SRC[>>8]]。
選択方法は[[ストリーム識別子]]を参照。
:[14] [RUBYB[[[ヘッダーブロック素片]]]@en[[[Header Block Fragment]]]]:
[[要求ヘッダー]]を含んだ[[ヘッダーブロック素片]]です [SRC[>>8]]。
:[15] [RUBYB[[[詰め]]]@en[Padding]]:
[[メッセージ]]の長さを隠すための[[セキュリティー]]機能です。
[[送信者]]は、すべて 0 の[[オクテット]]にしなければ[['''なりません''']]。 [SRC[>>29]]
詰め長の長さより、詰めの最大長は、255バイトです。
]FIG]
[FIG(packet)[
:width:32
= 8 詰め長
= 1 R
= 31 ストリーム識別子
= 88... header block fragment
= 32... 詰め
]FIG]
** 文脈
[64] [CODE[[[PUSH_PROMISE]]]] [[フレーム]]は、
任意の[[クライアント]]が開始した[[ストリーム]]に対して、
[[サーバー]]が送信することができます [SRC[>>34]]。
[21] [[peer]] が開始した[[ストリーム]]で状態が [[open]] か [[half-closed (remote)]]
である場合にしか送信しては[['''なりません''']] [SRC[>>8, >>34]]。
[86] 送信すると、指定した約束ストリームIDの[[ストリーム]]の状態は、
[[idle]] から [[reserved (local)]] へと遷移します [SRC[>>83]]。
[3] [[設定]] [CODE[[[SETTINGS_ENABLE_PUSH]]]] が 0 に設定されていれば、
[CODE[[[PUSH_PROMISE]]]] [[フレーム]]を送信しては[['''なりません''']] [SRC[>>1, >>8]]。
[63] [[クライアント]]は、 [CODE[[[PUSH_PROMISE]]]] [[フレーム]]を送信しては[['''なりません''']]
[SRC[>>34]]。
** 処理
[81] [[受信者]]は、[[payload]] が短すぎるか、[[設定]] [CODE[[[SETTINGS_MAX_FRAME_SIZE]]]]
より長いなら、[[接続エラー]] [CODE[[[FRAME_SIZE_ERROR]]]] としなければ[['''なりません''']]
[SRC[>>82]]。
[4] [[設定]] [CODE[[[SETTINGS_ENABLE_PUSH]]]] を 0 に設定し、
[[acknowledge]] された[[エンドポイント]]は、
[CODE[[[PUSH_PROMISE]]]] [[フレーム]]を受信したら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>1, >>8]]。
[22] [[ストリーム識別子]]が [CODE[[[0x0]]]] なら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>8]]。
[108] 未使用の[[ストリーム識別子]]の [CODE[[[PUSH_STREAM]]]]
を受信すると、[[約束ストリーム識別子]]の[[ストリーム]]の側で
[[Firefox]] は[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]]、
[[Chrome]] は[[ストリームエラー]] [CODE[[[STREAM_CLOSED]]]]
とするようです。ただし[[約束ストリーム識別子]]が 0
なら、[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] とするようです。
[TIME[2015-10-12T15:43:49.800Z]]
;; 仕様上は[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]]。[[ストリーム]]の状態遷移参照。
[109] [[要求]]送信済みで [CODE[[[HEADERS]]]]
受信前の[[ストリーム]] ([CODE[[[PUSH_PROMISE]]]] で作成された[[ストリーム]]含む。)
の[[ストリーム識別子]]で [CODE[[[PUSH_PROMISE]]]]
を受信したら、 [[Firefox]] も [[Chrome]] もエラーとはしません。
[TIME[2015-10-12T15:56:40.700Z]]
[110] [CODE[[[END_STREAM]]]] 受信済みの[[ストリーム]]で [CODE[[[PUSH_PROMISE]]]]
を受信したら、 [[Firefox]] は[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]]、
[[Chrome]] は[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]] とします。[TIME[2015-10-13T02:07:42.400Z]]
[28] [[約束ストリーム識別子]]が [[idle]] 状態でないなら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>8]]。
[93] 明記されていませんが、[[送信者]]が開始できない[[ストリーム識別子]]や
0の場合も同様に扱うべきと思われます。[[Chrome]] や [[Firefox]]
はそのようにしています。 [TIME[2015-10-12T15:29:02.100Z]]
[26] [[受信者]]は、[[ストリーム]]の状態が [[open]] でも [[half-closed (local)]]
でもなければ、[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']]
[SRC[>>8]]。
[27] ただし、[CODE[[[RST_STREAM]]]] を送信した後 (の [[closed]] 状態) には、
受信した [CODE[[[PUSH_PROMISE]]]] を処理しなければ[['''なりません''']] [SRC[>>8, >>83]]。
;; が十分な時間の経過後はエラーとしても構いません [SRC[>>83]]。
[[ストリーム]]の状態遷移の項を参照。
[32] [[受信者]]は、[[詰め]]に 0 以外があれば[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]]
としても構いません。 [SRC[>>29]]
[33] [[受信者]]は、詰め長が可能な長さより長ければ、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>29]]。
[24] [[受信者]]は、約束された[[ストリーム識別子]]を参照する
[CODE[[[RST_STREAM]]]] [[フレーム]]を返送することで、
約束[[ストリーム]]を拒絶することができます [SRC[>>8]]。
[84] [CODE(HTTP)@en[[[PUSH_PROMISE]]]] [[フレーム]]を受信すると、
その約束ストリームIDの[[ストリーム]]は、[[idle]] 状態から
[[reserved (remote)]] 状態へ遷移します。 [SRC[>>83]]
;; [85] 実際には約束ストリームIDで指定された[[ストリーム]]は存在していないはずですから、
作成して初期状態の [[idle]] 状態となり、直ちに [[reserved (remote)]]
状態に遷移します。
[88] [[約束ストリームID]]の[[ストリーム]]は、[[ストリーム識別子]]の[[ストリーム]]に
([[重み]]は既定値で) [[依存性]]を持つ状態となります [SRC[>>87]]。
;; [[依存性木]]を参照。
[25] [[ストリーム]]の状態遷移の項、[[ヘッダーリスト]]の項も参照。
[19] [CODE[[[END_HEADERS]]]] フラグが設定されていない場合、
次の[[フレーム]]が [CODE[[[CONTINUATION]]]] で無いか、
違う[[ストリーム]]なら、[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]]
としなければ[['''なりません''']] [SRC[>>8]]。
[53] [[サーバー]]は、[CODE(HTTP)@en[[[PUSH_PROMISE]]]] [[フレーム]]を受信したら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>34]]。
[107] [CODE[[[PUSH_PROMISE]]]] の[[ヘッダー]]が[[奇形]]な場合、
[[Chrome]] はエラーの種別に応じて[[接続エラー]] [CODE[[[COMPRESSION_ERROR]]]]
または[[約束ストリーム]]の[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]]、
[[Firefox]] は[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] とするようです。
[TIME[2015-10-12T14:38:24.100Z]]
* 設定
[2] [DFN[[CODE[[[SETTINGS_ENABLE_PUSH]]]]]] ([CODE[[[0x2]]]]) は、
[[server push]] を無効化するために使うことができます。 [SRC[>>1]]
[5] 値 1 は、 [[server push]] を認めることを表します。これは初期値です。 [SRC[>>1]]
[6] 値 0 は、 [[server push]] を認めないことを表します [SRC[>>34]]。
[7] [CODE[[[1]]]] と [CODE[[[0]]]] 以外の値は、[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]]
としなければ[['''なりません''']] [SRC[>>1]]。
[54] [[クライアント]]は、 [CODE(HTTP)[[[SETTINGS_ENABLE_PUSH]]]]
が [CODE[[[0]]]] 以外の値に設定されようとしたら、
拒絶して[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']]
[SRC[>>34]]。
;; [101] 1 が初期値なので、クライアントは最初エラーになるべき値が設定されていることになりますが、 [[RFC]] ではこの点に特に説明はありません。。。
[102] 実際には [[Chrome]] も [[Firefox]] も、値の検査をしていないようです。
[TIME[2015-10-12T03:20:51.100Z]]
[68] [[クライアント]]は、[[設定]] [CODE[[[SETTINGS_MAX_CONCURRENT_STREAMS]]]]
によって[[サーバー]]が[[並行]]してプッシュできる[[応答]]の数を制限できます。
0 を設定することで、[[server push]] のための[[ストリーム]]の作成を抑制できます。
ただし [CODE[[[PUSH_PROMISE]]]] [[フレーム]]の送信を禁止するものではありません。 [SRC[>>34]]
* fetch と server push
[92] [[Chrome]] や [[Firefox]] は、 [[fetch]] に当たり [CODE[[[PUSH_PROMISE]]]]
を受け取っていれば、新たに[[要求]]を送信せずにその[[応答]]を待つようです。
しかし [[fetch]] の呼び出し方法 (やタイミング?) によって別途[[要求]]を送信することもあります。
[TIME[2015-10-12T10:15:29.700Z]]
* メモ
[89] [CITE@ja[IIS 10.0 と ASP.NET 4.6 で HTTP/2 のサーバープッシュが使えるようになっていたので試した - しばやん雑記]]
([TIME[2015-06-06 17:34:09 +09:00]] 版)
<http://blog.shibayan.jp/entry/20150506/1430846908>
[90] [CITE@en[HTTP/2 server push support · Issue #51 · whatwg/fetch]]
([TIME[2015-06-12 12:15:20 +09:00]] 版)
<https://github.com/whatwg/fetch/issues/51>
[91] [CITE[HTTP/2 Push + browser cache - Google ドキュメント]]
([TIME[2015-08-28 20:02:16 +09:00]] 版)
<https://docs.google.com/document/d/1v3rjj0DMDTocUtZSjOwdwt8D-yhCw6R5SVaax4MPgMc/edit?pli=1>
[94] [CITE[Issue 135485 - chromium - SPDY - Pushed stream - crash accessing https://jetty.intalio.com:10111/spdy - An open-source project to help move the web forward. - Google Project Hosting]]
([TIME[2015-10-05 20:45:55 +09:00]] 版)
<https://code.google.com/p/chromium/issues/detail?id=135485>
[95] [CITE[Issue 377538 - chromium - Robust support for HTTP/2 server-push - An open-source project to help move the web forward. - Google Project Hosting]]
([TIME[2015-10-05 20:48:35 +09:00]] 版)
<https://code.google.com/p/chromium/issues/detail?id=377538>
[96] [CITE[Issue 328167 - chromium - Server-push for proactive cache management - An open-source project to help move the web forward. - Google Project Hosting]]
([TIME[2015-10-05 20:49:28 +09:00]] 版)
<https://code.google.com/p/chromium/issues/detail?id=328167>
[97] [CITE@en[958712 – HTTP/2 push continuations not completely implemented]]
([TIME[2015-10-05 20:51:56 +09:00]] 版)
<https://bugzilla.mozilla.org/show_bug.cgi?id=958712>
[98] [CITE@en[draft-thomson-webpush-http2-02 - Generic Event Delivery Using HTTP Push]]
([TIME[2015-07-19 16:43:54 +09:00]] 版)
<http://tools.ietf.org/html/draft-thomson-webpush-http2-02>
[99] [CITE@en[1072478 – loading never stops due to slow SPDY push]]
([TIME[2015-10-05 20:54:26 +09:00]] 版)
<https://bugzilla.mozilla.org/show_bug.cgi?id=1072478>
[100] [CITE@en[1167851 – HTTP/2 pushes and WINDOW_UPDATA frame]]
([TIME[2015-10-05 20:54:45 +09:00]] 版)
<https://bugzilla.mozilla.org/show_bug.cgi?id=1167851>
[103] [CITE@en[1127618 – PUSH_PROMISE is immediately rejected with a RST_STREAM]]
([TIME[2015-10-12 18:31:29 +09:00]] 版)
<https://bugzilla.mozilla.org/show_bug.cgi?id=1127618>
[104] [CITE[Issue 331663007: Implement PUSH_PROMISE handling in spdy_session - Code Review]]
([TIME[2015-10-12 18:32:45 +09:00]] 版)
<https://codereview.chromium.org/331663007>
[105] [CITE[Issue 331663007: Implement PUSH_PROMISE handling in spdy_session - Code Review]]
([TIME[2015-10-12 18:32:45 +09:00]] 版)
<https://codereview.chromium.org/331663007>
[112] [CITE@en[Preload]]
([TIME[2016-01-30 08:50:22 +09:00]] 版)
<https://w3c.github.io/preload/#server-push-http-2>
[FIG(quote)[
[FIGCAPTION[
[113] [CITE[Announcing Support for HTTP/2 Server Push]]
([TIME[2016-05-01 12:12:30 +09:00]] 版)
<https://blog.cloudflare.com/announcing-support-for-http-2-server-push-2/>
]FIGCAPTION]
> So, if you want to push assets for a given request, you simply add a specially formatted Link header to the response:
> Link: </asset/to/push.js>; rel=preload;
]FIG]
[115] [CITE@en[RFC 8030 - Generic Event Delivery Using HTTP Push]]
([TIME[2016-12-09 04:15:21 +09:00]])
<https://tools.ietf.org/html/rfc8030>
[FIG(quote)[
[FIGCAPTION[
[116] [CITE@en[mod_http2 - Apache HTTP Server Version 2.4]]
( ([TIME[2017-01-15 21:40:17 +09:00]]))
<https://httpd.apache.org/docs/2.4/mod/mod_http2.html#h2push>
]FIGCAPTION]
> Server pushes are detected by inspecting the Link headers of responses (see https://tools.ietf.org/html/rfc5988 for the specification). When a link thus specified has the rel=preload attribute, it is treated as a resource to be pushed.
]FIG]