/
68.txt
1585 lines (1159 loc) · 95 KB
/
68.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
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
[535] [[HTTP]] 通信の直接の当事者間の[[仮想回路]]を、
[DFN[[RUBYB[[[接続]]]@en[connection]]]]といいます。
[564] [[接続]]の両端は[[クライアント]]と[[鯖]]ですが、[[串]]が介在する場合、
一方又は両方が[[串]]となることもあります。
* 仕様書
[REFS[
- [131] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-3.5>
- [515] '''[CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-6>'''
-- [539] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-6.3.1>
-- [548] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-6.4>
-- [553] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-6.5>
- [3] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-3.3.3>
- [512] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-5.6>
- [108] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2015-04-23 00:49:39 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-9.1>
- [577] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-08-07 05:54:02 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#section-6.6.4>
- [63] [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>
-- [45] [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>
-- [47] [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-3>
-- [62] [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.1>
-- [73] [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.4>
-- [60] [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.8>
-- [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-7>
-- [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-8.1.4>
-- [90] [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-9.1>
-- [109] [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.1>
-- [111] [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.2>
-- [115] [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.8>
- [203] [CITE@en-US[Fetch Standard]] ([TIME[2016-04-19 01:53:35 +09:00]] 版) <https://fetch.spec.whatwg.org/#connections>
- [230] [CITE@en[Resource Hints]] ([TIME[2016-05-21 01:13:13 +09:00]]) <https://w3c.github.io/resource-hints/#dfn-initiate-a-preconnect>
- [234] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-4>
- [235] [CITE[RFC Errata Report]] ([TIME[2015-05-16 22:26:12 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=6455>
]REFS]
* 状態
[46] [DFN[[RUBYB[接続]@en[connection]]]]は、2つの[[エンドポイント]]の間の[[トランスポート層]]の[[接続]]です [SRC[>>45]]。
[50] [[接続]]の[[エンドポイント]]は、[[クライアント]]か[[サーバー]]かのいずれかです。
[48] [[HTTP/0.9]] や [[HTTP/1.0]]、[[HTTP/1.1]]、[[HTTP/2]] [SRC[>>47]] の[[接続]]は、
[[TCP接続]]上で動作する[[アプリケーション層プロトコル]][[輸送路]]です。
;; [49] [[TLS]] が間に挟まることもあります。 [[TCP]] の代わりに[[プロキシ]]プロトコルを用いる場合もあります。
(>>516)
[204] [[利用者エージェント][利用者エージェント (Web)]]は、
[F[接続プール]]として[[接続][HTTP接続]]群を保持します [SRC[>>203]]。
[205] [[接続][HTTP接続]]は、[F[起源]]と[F[credentials]]の組で識別されます [SRC[>>203]]。
[119] [[エンドポイント]]は、[[接続]]ごとに次の状態を持ちます。
[FIG(list members)[
: [F[起源]] : [[起源]]オブジェクト [SRC[>>203]]。
: [F[credentials]] : [[真偽値]] [SRC[>>203]]。
:下位層の情報:自身と [[peer]] の[[ホスト名]]や[[IPアドレス]]、[[ポート番号]]、
[[TLSセッション]]、[[RTT]] など。
:プロトコルの版:[[HTTP/0.9]]、[[HTTP/1.0]]、[[HTTP/1.1]]、[[HTTP/2]] のいずれか。
:自身の[[HTTP設定]]群:自身が値を決定した [[HTTP/2]] [[設定]]の各[[引数]]の値です。
:[[peer]] の [[HTTP設定]]群:[[peer]] から値を受信した [[HTTP/2]] [[設定]]の各[[引数]]の値です。
:[[HTTPストリーム]]群:[[HTTP/2接続]]内にある0個[[以上]]の[[HTTPストリーム]]の情報です。
初期状態では、空です (が [CODE(HTTP)@en[[[Upgrade: h2c]]]] でははじめに[[ストリーム]]が作られます)。
:[[HPACK]] 符号化用[[動的表]]:[[HTTP/2]] [[ヘッダーブロック]]の生成に使う[[動的表]]です。
:[[HPACK]] 復号用[[動的表]]:[[HTTP/2]] [[ヘッダーブロック]]の解釈に使う[[動的表]]です。
:[[依存性木]]:[[HTTP/2]] [[ストリーム]]の[[優先度]]を表す[[木]]です。
:[CODE(HTTP)@en[[[GOAWAY]]]] 送信[[最大ストリームID]]:[CODE(HTTP)@en[[[GOAWAY]]]]
を送信した場合その[[最大ストリームID]]。それより大きな[[ストリーム]]は以後処理しない。
:[CODE(HTTP)@en[[[GOAWAY]]]] 受信[[最大ストリームID]]:[CODE(HTTP)@en[[[GOAWAY]]]]
を受信した場合その[[最大ストリームID]]。
:タイムスタンプ:タイムアウトによる切断のために必要な情報。開始時刻、最後の送受信時刻など。
:[CODE(HTTP)@en[[[SETTINGS]]]] タイムスタンプ:
自身が最後に送信し、まだ [[ACK]] を受信していない [CODE(HTTP)@en[[[SETTINGS]]]]
[[フレーム]]の送信時刻です。一定時間経過後、タイムアウトによるエラーとなります。
:[CODE(HTTP)@en[[[GOAWAY]]]] 送信時刻:[CODE(HTTP)@en[[[GOAWAY]]]]
を送信した場合そのタイムスタンプ。
:[[接続フロー制御窓]]:
:[[HTTP/1.1]] 以下の状態:[[HTTP接続の処理]]を参照。
]FIG]
[217] [[WebSocket接続]]は、更に [[WebSocket]] 固有の状態を持ちます。
;; [[WebSocket接続]]の項を参照。
* HTTP の版
[566] [[接続]]がどのように処理されるかは、[[HTTPの版]]によって異なっています。
[[HTTPの版]]は、 [[HTTP/1.1]] [[以下]]と [[HTTP/2]] のいずれであるかは
[[TLS]] の [[ALPN]] により示され、更に [[HTTP/1.1]] [[以下]]の場合には[[接続]]上を流れる[[HTTPメッセージ]]の[[先頭行]]でそのいずれであるかが示されます。
[FIG(switch)[
:[[ALPN]] で [CODE[[[h2]]]]: [[HTTP/2]]
:[[ALPN]] で [CODE[http/1.1]] または [[ALPN]] なし:
[FIG(switch)[
:[[先頭行]]が [CODE[[[HTTP/1.1]]]]: [[HTTP/1.1]]
:それ以外で[[先頭行]]に[[プロトコルの版]]: [[HTTP/1.0]]
:それ以外: [[HTTP/0.9]]
]FIG]
: それ以外 : 非 [[HTTP]]
]FIG]
[10] [[HTTP/1.1]] [[以下]]の場合、理論上は[[要求]]ごと、
あるいは[[応答]]ごとに異なる[[プロトコルの版]]を記述することもできますが、
普通はそのようなことはありません。
そのような状況で[[受信者]]がどう処理するべきかは不明です。
[136] 実際の [[Webブラウザー]]は、 [[HTTP/1.1]] と [[HTTP/1.0]] と [[HTTP/0.9]]
が同じ[[接続]]内に混在しても、それぞれの動作に従い処理します。
[CODE(HTTP)[[[1xx]]]] と[[最後の応答]]で[[プロトコルの版]]が異なっていても構いません。
;; [137] [[HTTPの構文解析]]、[[状態行]]、[[HTTP/0.9]]、[CODE(HTTP)[[[1xx]]]]
を参照。なお、一部ブラウザーで例外的にエラーとなることがあります (各項参照)。
[11] [[鯖]]がおかしな[[メッセージ]]を返したことによって [[HTTP/1.1]] や [[HTTP/1.0]]
の[[接続]]の途中で [[HTTP/0.9]] [[メッセージ]]が出現したと判断し、おかしな動作をする
[[Webブラウザー]]もありました。セキュリティー上の問題となる可能性もありますから、
注意が必要です。
;; [[HTTP/0.9]>>7]参照。
;; [118] 途中で版が変わる場合にはエラー[[応答]]を返したり、[[接続]]を切断したりするべきなのかもしれません。
なお[[プロキシ]]は受信したメッセージをそのまま[[転送]]するのではなく、
自身の対応する適切な版を選択して適宜書き換えて[[転送]]することが期待されていますから、
[[プロキシ]]との通信であっても途中で版が変わることはないはずです。
[54] [[HTTPの版]]の決定方法については、[[プロトコルの版]]を参照してください。
[78] [[HTTP/2]] から [[HTTP/1.1]] への切り替えもあります (>>79)。
* 接続を得る
[206] [[利用者エージェント]][VAR[クライアント]]が[[起源]][VAR[起源]]、
[[boolean]] [VAR[credentials]]、
[[boolean]] [VAR[事前]] (既定値は[[偽]])
について[DFN[[RUBYB[接続を得る]@en[obtain a connection]]]]には、
次のようにします [SRC[>>203]]。
[FIG(steps)[
= [207] [VAR[クライアント]]の[F[接続プール]]に、
[F[起源]]が[VAR[起源]]で[F[credentials]]が[VAR[credentials]]の[[接続][HTTP接続]]があれば、
== [208] それを返し、ここで停止します。
= [209] [VAR[接続]]を、[VAR[起源]]への [[HTTP接続]]を確立した結果に設定します。
[VAR[credentials]] が[[偽]]なら、[[TLSクライアント証明書]]を送信しません。
本 [[fetch]] が [[terminate][terminate (fetch)]] されたら、接続を中断します。
= [289] 本 [[fetch]] が [[terminate][terminate (fetch)]] されている場合、
== [290] [VAR[接続]]が [CODE[null]] 以外の場合、
=== [291] [VAR[接続]]を閉じます。
=== [292] [[失敗]]を返し、ここで停止します。
= [210] [VAR[接続]]が[[失敗]]なら、
== [211] [[失敗]]を返し、ここで停止します。
= [212] [VAR[接続]]の[F[起源]]を、[VAR[起源]]に設定します。
= [213] [VAR[接続]]の[F[credentials]]を、[VAR[credentials]]に設定します。
= [214] [VAR[接続]]を、[VAR[クライアント]]の[F[接続プール]]に追加します。
= [215] [VAR[接続]]を返します。
]FIG]
[231] [VAR[事前]]が[[真]]の場合、[[HTTP接続]]の確立 (>>209)
はできれば完全に行う[SHOULD[べき]]ですが、
[[資源]]制約その他の理由で叶わなければ、
一部または全部を省略して構いません [SRC[>>230]]。
[EG[
[232] 例えば [[DNS]] の[[名前解決]]のみとしたり、 [[TCP]] までで [[TLS]]
は行わなかったりしても構いません。 [SRC[>>230]]
]EG]
;; [233] もちろん、その[[事前接続]]を後から実際に利用するためには、
接続の確立の処理を完了させる必要があります。
[219] 後述の通り、同じ[[サーバー]]に複数の[[接続][HTTP接続]]を同時に確立できます。
[F[接続プール]]には、[F[起源]]と[F[credentials]]の組が同じ[[接続][HTTP接続]]が複数含まれているかもしれません。
何個まで含められるかや、それらからどうやって選ぶか(選ばないか)は、
[VAR[クライアント]]に委ねられています。
([[パフォーマンス]]や利用可能[[資源]]などの[[トレードオフ]]を考慮する必要があります。)
[VAR[事前]]が[[真]]なら、
既に十分な数の接続があれば、新たな接続を確立しないことにするかもしれません。
[VAR[事前]]が[[偽]]なら、接続数が減少するまで[[HTTP接続]]の確立の実処理を遅延させる必要がありそうです。
[216] [[WebSocket接続を得る]]手順は、これとは別に用意されています (詳細はそちらの項を参照)。
通常の[[HTTP接続を得る]]手順とおおむね同趣旨ではあるのですが、
[[WebSocket]] は必ず新しい[[接続][HTTP接続]]を使うので、[F[接続プール]]は参照しません。
(これは[[事前接続]]が利用されないことも意味します。)
[218] これらは、 [[HTTP-network fetch]] から呼び出されます。
[224] [[接続を得る]]は、[[事前接続の開始]]からも呼び出されます。
** 接続先の決定
[531] [[接続]]先の[[鯖]]は、他の[[インターネット]]の[[アプリケーション層プロトコル]]と同じように、
[[URL]] などによって指定された[[ドメイン名]]や [[IPアドレス]]などと[[ポート番号]]とを使って識別されます。
;; [532] [CODE(URI)@en[[[http:]]]] の項も参照してください。
[67] [[URL scheme]] が [CODE(URI)@en[[[http:]]]] なら [[TCP]] を、
[CODE(URI)@en[[[https:]]]] なら [[TLS]] over [[TCP]] を下位層として使います。
;; [68] [[HSTS]] では特定の条件を満たす [CODE(URI)@en[[[http:]]]] [[URL]]
に接続する前に [CODE(URI)@en[[[https:]]]] [[URL]] へと書き換えます。
この処理は [[fetch]] で行われます。 [[HTTP接続]]の確立の段階では、
既に書き換え済みです。
[197] [[クライアント]]が[[代替サービス]]に対応しており、接続先の [[URL scheme]]、
[[ホスト]]、[[ポート]]の組に対して適用可能な[[代替サービス]]を知っている場合、
接続先の[[プロトコル]]、[[ホスト]]、[[ポート]]をその[[代替サービス]]のものとします。
;; 詳細は[[代替サービス]]参照。
[EG[
[199] [[Chrome]] は、 [[QUIC]] が利用可能なら、そちらに切り替えます。
]EG]
[EG[
[285] [[Firefox]] は、 [[Opportunistic HTTP/2 Security]] が利用可能なら、
そちらに切り替えます。
]EG]
[533] [[プロキシ]]は、[[利用者エージェント]]の設定などの実装依存の方法で指定されます。
[[串]]が指定されている場合は、[[接続]]先は[[サーバー]]ではなく、[[プロキシ]]となります。
;; [534] 多くの[[Webブラウザー]]は、 [[proxy.pac]] による指定に対応しています。
;; [198] [[代替サービス]]に接続する場合も、必要に応じて[[プロキシ]]を使います。
[19] [[串]]に[[名前解決]]を委ねる場合を除き、通常は[[ホスト]]部の[[名前解決]]を行い、
[[IPアドレス]]を取得し、それを[[接続]]先の[[鯖]]とします。[[名前解決]]は [[DNS]]
によって行うのが基本ですが、 [CODE[[[/etc/hosts]]]] や [[NetBIOS]]
など当該システムが実装している他の[[名前解決]]の仕組みが用いられることもあります。
;; [[名前解決]]を参照。
;; [[インターネット]]の [[DNS]] による[[名前解決]]と [CODE[[[localhost]]]]、
それに [[IPアドレス]]による直接指定を除くと、
システム依存の[[名前解決]]方式に依存した接続先の指定は[[相互運用]]不能です。
;; [120] [[WebSocket接続の確立]]も参照。
** 接続の開始
[530] [[接続]]は、[[クライアント]]が[[鯖]] (または[[串]])
に対して下位層プロトコルの[[接続]]を確立することにより、開始されます。
[[鯖]]は下位層プロトコルと [[OS]] 等の [[API]] ([[ソケット]]など)
の規定に基づき予め[[接続]]を受け付ける状態で待っている必要があります。
;; [69] 下位層プロトコルの章 (>>516) も参照。
[536] [[HTTP/1.1]] [[以下]]では、他の多くの[[アプリケーション層プロトコル]]とは違って、
[[接続]]の初期化のようなプロトコル上の手続きはなく、すぐに[[要求]]を送信できます。
;; [70] [[HTTP認証]]は、[[接続]]レベルではなく、個々の[[要求]]のレベルで行われるのが原則です。
([[HTTP認証]]の項を参照。) 従って、 [[HTTP]] レベルでは[[接続]]の確立の段階で
[[challenge]] や [[credentials]] の送信など[[認証]]操作は行われません。
もちろん、[[サーバー]]は必要なら下位層の接続が確立された (確立しようとする) 時点で
[[IPアドレス]]や[[TLSクライアント証明書]]などを使って [[HTTP]]
よりも前に認証を行うことはできます。
[568] [[接続]]が確立されると、[[クライアント]]は[[鯖]]に[[要求]]を送信します。
その送信のタイミングは特に規定されていませんが、通常は即座に送信します。
後述の通り、[[鯖]]は通常タイムアウトを設定しており、一定時間内に[[要求]]が送信されなければ、
エラーとして扱います。
[20] [[クライアント]]が[[名前解決]]に失敗した場合や下位層プロトコルの[[接続]]の確立に失敗した場合は、
当然ながら [[HTTP接続]]を利用することはできず、[[要求]]を送信できません。
*** cross-protocol attack
[121] [[HTTP/1.1]] 以下は単純なテキストベースのプロトコルなので、
攻撃者の指示により[[クライアント]]が他のプロトコルに接続できる文字列を送ることができる場合があります。
;; [114] [CODE(MIME)@en[[[multipart/form-data]]]] により[[フォームデータ]]を [[HTTP]]
で送信することで、 [[cross-protocol attack]] が試みられることがあります。
;; [122] [[HTTPヘッダー]]など他のプロトコルで解釈できない部分を未知の命令などとして無視するプロトコルを攻撃できます。
[113] [[Webブラウザー]]は [[port blocking]] により他の[[プロトコル]]が使うことが多い[[ポート]]へのアクセスを拒み、
[[cross-protocol attack]] を難しくしています。
[110] [[HTTP/2]] over [[TLS]] は [[ALPN]] によりプロトコルを明示でき、
また[[暗号化]]のため [[TCP]] 上のバイト列を制御することが難しいため、
[[cross-protocol attack]] は困難です [SRC[>>111]]。
[123] [[HTTP/1.1]] [[以下]] over [[TLS]] は[[暗号化]]のため、[[平文]]プロトコルを攻撃することは困難です。
しかし [[ALPN]] を使わなくて良いため、 [[TLS]] 上の非 [[HTTP]]
[[プロトコル]]は攻撃できるかもしれません。
[112] [[HTTP/2]] over [[TCP]] は[[接続序文]]により [[HTTP/1.1]] [[以下]]の実装の誤動作を防ごうとしていますが、
非 [[HTTP]] [[プロトコル]]に対する [[cross-protocol attack]] を防ぐものではありません [SRC[>>111]]。
** 接続の並行性
[87] [[HTTP/1.1]] [[以下]]では、1つの[[接続]]で同時に送受信できる[[応答]]は1つだけです。
1つの[[文書]]に埋め込まれた複数の[[画像]]が存在する場合など、
[[クライアント]]側の処理性能の向上のためには複数の[[接続]]を[[並列]]に確立する必要があります。
[88] [[HTTP/1.0]] の [[keep-alive]] や [[HTTP/1.1]] の[[持続的接続]]や[[パイプライン]]化を用いると
1つの[[接続]]を再利用して次の[[応答]]を受信することができ、 [[TCP接続]]の再[[確立]]や次の[[要求]]の送受信の時間を節約できますが、
前の[[応答]]が完了するまで次の[[応答]]は送信できませんから、
すぐに[[レンダリング]]開始したいなら、やはり複数の[[接続]]が必要となります。
[89] しかし[[接続]]数が多すぎると[[サーバー]]や[[ネットワーク]]に過剰な負荷を与えてしまう虞があるため、
[[クライアント]]は適当な上限を設けるべきです。
[550] 旧仕様の [[RFC 2616]] までは、ある[[クライアント]]からある[[鯖]] (や[[串]])
への同時接続数は2[[以下]]とするべきだとされていました [SRC[>>549]]。
[551] [[RFC 7230]] は、[[応用]]によっては非現実的なので、特定の上限は設けないが、
[[クライアント]]は[[接続]]を開くのには保守的であるようにと求めています [SRC[>>548]]。
[552] 多くの [[Webブラウザー]]は、00年代前半までは [[RFC]] の上限を既定値とし、
設定によっては更に増やすこともできるようになっていました。
しかしその後 [[Ajax]] の普及などに伴い徐々に制限が緩和されています。
[REFS[
- [549] [CITE@en[RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1]] ([TIME[2014-06-07 01:51:52 +09:00]] 版) <http://tools.ietf.org/html/rfc2616#page-47>
- [243] [CITE@en[Network.http.max-connections - MozillaZine Knowledge Base]] ([TIME[2015-11-24 06:40:48 +09:00]]) <http://kb.mozillazine.org/Network.http.max-connections>
- [244] [CITE@en[Network.http.max-connections-per-server - MozillaZine Knowledge Base]] ([TIME[2008-03-20 12:13:05 +09:00]]) <http://kb.mozillazine.org/Network.http.max-connections-per-server>
- [245] [CITE@en[Network.http.max-persistent-connections-per-proxy - MozillaZine Knowledge Base]] ([TIME[2008-03-20 12:16:57 +09:00]]) <http://kb.mozillazine.org/Network.http.max-persistent-connections-per-proxy>
- [246] [CITE@en[Network.http.max-persistent-connections-per-server - MozillaZine Knowledge Base]] ([TIME[2015-11-24 06:46:13 +09:00]]) <http://kb.mozillazine.org/Network.http.max-persistent-connections-per-server>
- [251] [CITE@en[33259 – So, should we make a number of http connections configurable]] ([TIME[2016-06-17 10:47:33 +09:00]]) <https://bugzilla.mozilla.org/show_bug.cgi?id=33259>
- [247] [CITE@en[83526 – http should use fewer connections per server per page]] ([TIME[2016-06-17 10:33:47 +09:00]]) <https://bugzilla.mozilla.org/show_bug.cgi?id=83526>
- [250] [CITE@en[103070 – No new connections issued when waiting for timeout]] ([TIME[2016-06-17 10:42:51 +09:00]]) <https://bugzilla.mozilla.org/show_bug.cgi?id=103070>
- [248] [CITE@en[423377 – (wedidntstartthefire) Change max-persistent-connections-per-server to 6.]] ([TIME[2016-06-17 10:38:45 +09:00]]) <https://bugzilla.mozilla.org/show_bug.cgi?id=423377>
- [252] [CITE@en[648570 – increase total idle pconn tool to 256 (matches chrome)]] ([TIME[2016-06-17 10:48:31 +09:00]]) <https://bugzilla.mozilla.org/show_bug.cgi?id=648570>
- [253] [CITE@en[692260 – Increase in network.http.max-connections appears to cause hang, requires browser restart]] ([TIME[2016-06-17 10:53:06 +09:00]]) <https://bugzilla.mozilla.org/show_bug.cgi?id=692260>
- [254] [CITE@en[Issue 12066 - chromium - Match Firefox's per-host connection limit of 15 - Monorail]] ([TIME[2016-06-17 10:59:20 +09:00]]) <https://bugs.chromium.org/p/chromium/issues/detail?id=12066>
- [255] [CITE@en[Issue 19052 - chromium - Option to configure max-persistent-connections-per-proxy - Monorail]] ([TIME[2016-06-17 11:00:09 +09:00]]) <https://bugs.chromium.org/p/chromium/issues/detail?id=19052>
- [259] [CITE@en[Issue 44501 - chromium - Consider changing connections per proxy server limit - Monorail]] ([TIME[2016-06-17 11:04:52 +09:00]]) <https://bugs.chromium.org/p/chromium/issues/detail?id=44501>
- [256] [CITE@en[Issue 63658 - chromium - Policy: Add policy to manage max number of concurrent connections per proxy server - Monorail]] ([TIME[2016-06-17 11:01:13 +09:00]]) <https://bugs.chromium.org/p/chromium/issues/detail?id=63658>
- [258] [CITE@en[Issue 85323 - chromium - Configurable connections-per-host - Monorail]] ([TIME[2016-06-17 11:03:42 +09:00]]) <https://bugs.chromium.org/p/chromium/issues/detail?id=85323>
- [257] [CITE@en[Issue 87381 - chromium - Allow configuring of max connections and max connections per proxy - Monorail]] ([TIME[2016-06-17 11:02:04 +09:00]]) <https://bugs.chromium.org/p/chromium/issues/detail?id=87381>
- [6] [CITE[AnyEvent::HTTP - search.cpan.org]] ([TIME[2014-10-22 08:11:41 +09:00]] 版) <http://search.cpan.org/dist/AnyEvent-HTTP/HTTP.pm#%24AnyEvent%3A%3AHTTP%3A%3AMAX_PER_HOST>
]REFS]
[91] [[HTTP/2]] では[[持続的接続]]が基本動作となっており、
[[クライアント]]は必要が無いと判断するまで[[接続]]を閉じずにいることが期待されています
[SRC[>>90]]。[[クライアント]]は 1つの[[接続]]で複数の[[ストリーム]]を使って[[並行]]して[[応答]]を受信できます。
[[クライアント]]は、[[プロキシ]]を含む[[サーバー]]への[[接続]]を、
[[ホスト]]と[[ポート]]の組に対して複数開く[['''べきではありません''']] [SRC[>>90]]。
;; [116] これは[[サーバー]]が[[利用者]]の動作を追跡しやすくすることになり、
注意が必要です。 [SRC[>>115]]
[93] [[HTTP/2]] [[クライアント]]は、異なる値を [[SNI]] に指定する場合や異なる [[TLS]]
[[クライアント証明書]]を指定する場合は、同じ [[IPアドレス]]と [[TCPポート]]に対して複数の[[接続]]を開いて構いません。
しかし同じ指定で複数の[[接続]]を開くことは避ける[['''べきです''']]。 [SRC[>>90]]
;; [103] 逆に複数の[[ホスト]]が同じ[[接続]]を共有する場合 (>>96) があります。
[92] [[HTTP/2]] [[クライアント]]は、既存の[[接続]]が[[ストリーム識別子]]空間を使い果たしつつある場合や、
[[TLSセッション]]の鍵の更新のため必要な場合、
[[エラー]]を検出した場合には、代替となる[[接続]]を新たに開くことができます [SRC[>>90]]。
*** 他の接続を待つ
[237] [[WebSocket]] に関しては、他の接続が閉じられるのを待つ処理が明文化されています。
[236] [DFN[他の接続を待つ]]場合は、次のようにしなければ[MUST[なりません]] [SRC[>>234]]。
[FIG(steps)[
= [[ホスト]]から、 [[IPアドレス]]を得ます ([[名前解決]])。
= [[ホスト]]から[[IPアドレス]]を得られない場合 (例えば[[名前解決]]を[[プロキシ]]に委ねている場合)、
== [VAR[host]] を、[[ホスト]]に設定します。
== [VAR[n]] を、十分小さな値とする[SHOULD[べきです]]。例えば開いている[[タブ]]数を考慮して決めます。
= それ以外の場合、
== [VAR[host]] を、[[IPアドレス]]に設定します。
== [VAR[n]] を、1 に設定します。
= 同じ [VAR[host]] と[[ポート]]への状態が [CODE[[[CONNECTING]]]]
である[[WebSocket接続]]があるか調べます。
= その数が [VAR[n]] [[未満]]となるまで、待ちます。
]FIG]
[238] この制限は、[[著者]]が多数の [[WebSocket接続]]を開いて [[DoS攻撃]]することを難しくするためのものです
[SRC[>>234]]。
;; [239] [[ホスト]]のみで制限する実装と[[ホスト]]と[[ポート]]の組で制限する実装があります
[SRC[>>235]]。
;; [240] これをうまく使うとある[[ホスト]]とある[[ホスト]]が同じ [[IPアドレス]]かどうかをある程度の精度で推測できるかもしれませんが、
それによって何か問題になることはあまり無さそうです。
[241] [[HTTP/1]] (非 [[WebSocket]]) と [[HTTP/2]] に関しては明文規定はありませんが、
[VAR[n]] 以外は同様に処理するべきものと思われます。
([[プロキシ]]への接続と[[起源サーバー]]への接続とでも [VAR[n]] は違いそうです。)
** 接続の再利用
[94] [[HTTP/1.0]] [[keep-alive]]、[[HTTP/1.1]] [[持続的接続]]、[[HTTP/2]]
では、同じ[[接続]]を複数の[[要求]]と[[応答]]の組の送受信に再利用できます。
[95] [[HTTP/1.0]] と [[HTTP/1.1]] でどのような場合に[[接続]]を再利用できるのかは、
明確な規定がありません。
[96] [[HTTP/2]] の[[起源サーバー]]への接続は、直接のものであれ [CODE(HTTP)@en[[[CONNECT]]]]
[[トンネル]]経由であれ、 [[authority]] が異なっていても当該[[起源サーバー]]が
[[authoritative]] である限り、再利用できます。 [SRC[>>90]]
[97] 具体的には、 [[TLS]] 無しの [[TCP]] では、[[ホスト]]が同じ [[IPアドレス]]に[[解決]]されることをいいます。 [SRC[>>90, >>108, >>109]]
(もちろん[[ポート番号]]も一致する必要があります。)
[98] [CODE(URI)@en[[[https]]]] では、 [[TCP]] のみの場合の条件に加え、
[[サーバー証明書]]が新しい [[TLS接続]]の場合と同様の検査を満足しなければ[['''なりません''']]。
[SRC[>>90, >>108, >>109]]
;; [99] [[SAN]] や[[ワイルドカード証明書]]を使うと、同じ[[証明書]]で複数の
[[authority]] に対応できます。
;; [102] 複数の[[ホスト]]へ同じ[[接続]]を利用できる本規定と、
同時接続の禁止 (>>91) がどう関係するのかは不明です。
;; [117] [[起源]]を超えて[[サーバー]]が[[利用者]]の行動を追跡しやすくなりますから、
注意が必要です [SRC[>>115]]。
[104] [[サーバー]]の構成によっては、 [[SNI]] で指定された[[ホスト]]によって[[中間器]]が異なる[[起源サーバー]]を選択する場合など、
[[クライアント]]が (機密かもしれない) [[要求]]を誤った[[サーバー]]に送ってしまう可能性もあります。
[[サーバー]]は、[[クライアント]]に[[接続]]を再利用してほしくない場合、
[[authoritative]] でないことを [CODE(HTTP)[[[421]]]]
[[応答]]によって表明できます。 [SRC[>>90]]
;; [105] [[クライアント]]は事前に判定できないので、[[要求]]が他者に漏洩してしまう可能性があるわけですが、
良いのでしょうか... [[クラウド]]サービスの共通の[[逆串]]などで[[証明書]]まで共有していても異なる[[起源サーバー]]に接続されることはあるでしょうから、その場合[[クラウド]]サービス提供者は確実に
[CODE(HTTP)[[[421]]]] [[応答]]を返すよう注意が必要です。
[106] [[HTTP/2]] [[プロキシ]]を使う[[クライアント]]は、
すべての[[要求]]を同じ[[接続][HTTP接続]]に送信します [SRC[>>90]]。
;; [185] [[要求URL]]も参照。
[283] [[代替サービス]]に関してはまた別の要件があります。
* 接続上を流れるもの
[401] 通常の [[HTTP]] の通信では、[[HTTPメッセージ]]が[[接続]]上を送受信されます。
[523] [[HTTPメッセージ]]は、[[要求メッセージ]]または[[応答メッセージ]]です。
現在の [[HTTP]] では[[クライアント]]から[[鯖]]へと送信されるのが[[要求]]、
[[鯖]]から[[クライアント]]へ送信されるのが[[応答]]と決まっています。
[52] テキスト形式プロトコルである [[HTTP/1.1]] [[以下]]では、
[[メッセージ]]は [[RFC 822]] 風のテキスト形式で表現され、
[[接続]]上を直接送受信されます。
[53] バイナリー形式プロトコルである [[HTTP/2]] では、
[[メッセージ]]は複数の[[フレーム]]の列で表現され、
[[接続]]内の[[ストリーム]]上のバイト列として送受信されます。
** HTTP/1.1 以下
[55] [[要求]]を[[クライアント]]から[[サーバー]]へと送信し、
それに対して[[応答]]を[[サーバー]]から[[クライアント]]へと送信するのが基本的な動作です。
[[接続]]を開き、送受信を行ってから、[[接続]]を閉じます。
[FIG(sequence)[
:C:[[クライアント]]
:S:[[鯖]]
:C ## S:[[接続の確立]]
:C -> S:[[要求]]
:S -> C:[[応答]]
:C ## S:[[接続]]を閉じる
]FIG]
[522] [[持続的接続]]機能を使うと、1つの[[接続]]で複数の[[要求]]と[[応答]]の組をやりとりすることができます。
;; [9] [[持続的接続]]は [[HTTP/1.1]] では標準機能となっています。
([[HTTP/1.0]] では [[Keep-Alive]] は実験的に追加された機能でした。)
詳しくは[[持続的接続]]を参照。
[513] [[要求]]と[[応答]]の対応関係は、明示されません。
[[要求]]が送信されたのと同じ順に[[応答]]が送信されます。 [SRC[>>512]]
;; [524] ですから、下位層プロトコルは順序を保証するものである必要があります。
[525] [[応答]]は、必ず[[要求]]に対する反応として送信されます。
[[要求]]がないのに[[応答]]が送信されることは、原則としてありません。
;; [526] 例外的に、[[接続]]をはじめてから何も送られないままタイムアウトした場合など、
特別に[[応答]]が送信され、ただちに[[接続]]が閉じられるケースがあります。
[528] [[メッセージ]]の境界は、[[メッセージ]]自体によって、または[[接続]]が閉じられることにより識別されます。下位層プロトコルは[[オクテット列]]の送受信のみが要求されています。
;; [529] 詳しくは[[メッセージ]]と[[メッセージ本体]]の項を参照してください。
[132] [[鯖]]は、少なくても1つは[[要求行]]の前の [[CRLF]] を無視する[['''べきです''']]
[SRC[>>131]]。 実際には他の[[改行]]と同じく、省略可能な [[CR]] とその後の [[LF]]
が無視されるようです。
[133] [[Apache]] も [[nginx]] も、[[要求]]の前の任意の個数の[[改行]]を無視するようです。
[TIME[2015-06-15T12:58:39.600Z]]
;; [134] すべての実装がそのように動作するなら、 [[ping]] の代用とできるかもしれません。
実際どうなのかは定かではありません。
[546] [[パイプライン]]化により、[[要求]]に対する[[応答]]の到着を待たずに次の[[要求]]を送ることもできます。
;; 詳しくは[[HTTPパイプライン]]の項を参照してください。
[402] [CODE(HTTP)@en[[[CONNECT]]]] [[メソッド]]に対して [CODE(HTTP)[[[2xx]]]]
[[応答]]が返された場合、[[メッセージ]]はそこで終端され、
以後は[[トンネル]]となります。詳しくは [CODE(HTTP)@en[[[CONNECT]]]]
の項を参照してください。
[562] [CODE(HTTP)@en[[[Upgrade:]]]] によって[[プロトコル]]が切り替えられる場合、
[[鯖]]によって [CODE(HTTP)[[[101]]]] が返され、それよりも後は新しい[[プロトコル]]に切り替わります。
詳しくは [CODE(HTTP)@en[[[Upgrade:]]]] や [[WebSocket接続の確立]]、
[[WebSocket接続]]の項を参照してください。
;; [38] [[パイプライン化]]と [CODE(HTTP)@en[[[CONNECT]]]] や [CODE(HTTP)@en[[[Upgrade:]]]]
の組み合わせは思わぬ副作用を生むかもしれません。例えば別のプロトコルに切り替わる前に[[クライアント]]がデータを送信していると、
[[鯖]]がそれをどう解釈するかが曖昧となり、[[セキュリティー]]や[[相互運用性]]の問題を引き起こすことがあります。
[[RFC 7472]] や [[HTTPS]] の歴史の項も参照。
;; [43] [[クライアント]]が対応していない [CODE(HTTP)[[[101]]]]
[[応答]]を受信した場合の[[クライアント]]の処理は、[CODE(HTTP)[[[101]]]]
を参照してください。
*** 応答間のデータ
[167] 前の[[応答]]を受信し終えてから次の[[要求]]の送信を始めるまでの間に受信したデータは、
どのブラウザーも捨てるようです。 [TIME[2015-09-12T14:34:03.900Z]]
[168] それに対して [[HTTP]] ではどのブラウザーも最初の[[要求]]の送信前に受信した
(であろう) データは最初の[[要求]]への[[応答]]とみなすようです。 [TIME[2015-09-12T14:35:47.200Z]]
[169] [[HTTPS]] では [[Chrome]] と [[IE]] は ([[TLS handshake]] 後に送られた)
最初の[[要求]]の送信前にデータを受信したら、最初の[[要求]]を[[ネットワークエラー]]とするようです。 [TIME[2015-09-12T14:37:41.400Z]]
[171] [[Firefox]] は [[HTTPS]] で最初の[[要求]]の前に受信しても最初の[[応答]]とみなすように見えます。
しかし[[応答]]後に受信したデータがあると次の[[要求]]にその[[接続]]を使わないように見えます。
([[Chrome]] では [[HTTP]] と同じく[[応答]]後のデータは無視するように見えます。)
[TIME[2015-09-12T14:49:57.500Z]]
[265] [[nginx]] や [[Apache]] は最初の[[要求]]の前に LF または CRLF があれば、これを無視します。
それ以外の CR と LF の列があると、 [[nginx]] はおかしな状態になり、
[[Apache]] は[[要求行]]として解釈しようとしてエラーを返します。 [TIME[2016-09-09T07:57:44.000Z]]
[266] [[nginx]] は最初の[[要求]]と次の[[要求]]の間で任意の CR と LF
の列を無視します。 [[Apache]] は LF または CRLF の任意個の繰り返しを無視します。 [TIME[2016-09-09T07:58:13.600Z]]
;; [170] いずれの場合についても[[ネットワーク]]や [[TCP/IPスタック]]の状況によって[[アプリケーション]]に到達するタイミングが左右される上、
[[接続]]の確立から最初の[[要求]]を送信するまでの時間はごくわずかなので、
動作は不確かです。
** HTTP/2
[80] [[ストリーム]]の処理については、[[ストリーム]]や[[フレーム]]を参照。
[81] [[メッセージ]]の送受信については、[[HTTPメッセージ]]、
[[HTTP要求]]、[[HTTP応答]]、[[サーバープッシュ]]を参照。
[51] 両[[エンドポイント]]は、[[メッセージ]]を構成する[[フレーム]]の他、
適宜 [CODE[[[PING]]]] [[フレーム]]、
[[フロー制御]]のための [CODE[[[WINDOW_UPDATE]]]] [[フレーム]]、
[[設定]]変更のための [CODE[[[SETTINGS]]]] [[フレーム]]などを送受信することになります。
;; [57] [[HTTP/2]] [CODE(HTTP)@en[[[CONNECT]]]] [[要求メソッド]]は、
[[ストリーム]]内のデータの送受信を[[トンネル]]として使います。 [[HTTP/1.1]]
とは違って[[接続]]全体が切り替わるのではないので、他の[[ストリーム]]により
(または同じ[[ストリーム]]の [CODE[[[DATA]]]] 以外の[[フレーム型]]により)
[[HTTP]] データの送受信は継続できます。
;; [58] [[HTTP/2]] では [CODE(HTTP)@en[[[Upgrade:]]]] は使えません。
** 最初の要求と応答
[284] [[Opportunistic Security for HTTP/2]] では、
実際の[[要求]]と[[応答]]の送受信の前に、
[CODE[/.well-known/http-opportunistic]] の送受信が発生します。
ただし、[[HTTPキャッシュ]]により省略される場合もあります。
;; [CODE[/.well-known/http-opportunistic]] 参照。
** 要求の時機
[225] 基本的には、[[接続][HTTP接続]]が確立されたら、すぐに最初の[[要求]]が送信されます。
[226] [[事前接続]]を用いる場合は、[[接続][HTTP接続]]の確立から最初の[[要求]]の送信までに若干の時間があるかもしれません。
[228] 同じ[[接続][HTTP接続]]を再利用 (>>94) して次の[[要求]]を送信する場合もあります。
これも前の[[要求]]と[[応答]]の後すぐに送信される場合もあれば、時間を置く場合もあります。
;; [229] [[HTTP/1]] では理論上 [[HTTPパイプライン]]により前の[[応答]]を待たずに次の[[要求]]を送ることができますが、
実際には不可能です。
[[HTTP/2]] では複数の[[ストリーム][HTTPストリーム]]を同時に用いられるので、
他の[[要求]]・[[応答]]のタイミングに関わらず次の[[要求]]を送信できます。
[227] [[サーバー]]は、一定時間内に[[要求]]が送信されなければ、
[[タイムアウト]] (>>554) で[[接続][HTTP接続]]を閉じるかもしれません。
** 応答の時機
[569] [[応答]]が送信されるタイミングは、特に規定されていません。
[[鯖]]が[[要求]]の末尾まで読み終えるよりも先に送信される可能性もありますし、
[[要求]]がすべて読み終わってからしばらく経ってようやく送信される可能性もあります。
[[要求]]が送信され始めるより前に[[応答]]が返されることもあるかもしれません。
[[long poll]] では、[[応答]]の送信開始や送信完了までの待機時間が長いかもしれません。
[579] [[要求]]が[[非妥当]]である場合や、[[要求]]の[[要求行]]や[[ヘッダー]]、
あるいは[[メッセージ本体]]の途中で[[鯖]]が処理できないと判断した場合、
[[鯖]]が[[要求]]をすべて読み終わる前や[[クライアント]]が[[要求]]を送信し終わる前に[[鯖]]がエラー
([CODE(HTTP)[[[400]]]] や [CODE(HTTP)[[[413]]]] や [CODE(HTTP)[[[505]]]] など) を返したり、
[[接続]]を閉じたりすることがあります。
[44] [[クライアント]]は通常タイムアウトを設定しており、一定時間内に[[応答]]の一部または全部が返されなければ、
通信やサーバーのエラーとみなします。タイムアウトまでの[[時間]]は、[[アプリケーション]]の性質や[[サーバー]]や[[クライアント]]の用途、
想定される[[ネットワーク]]の状態など様々な因子に依存するため、一概には決められません。
[572] [[メッセージ]]を構成するデータの送信速度は、一様でなくても構いません。
例えば、[[鯖]]が [CODE(MIME)@en[[[multipart/x-mixed-replace]]]] [[応答]]を返す場合、
ある程度の時間をあけて複数の[[本体部分]]を送信し続けることになります。
;; もちろん、実装によってはタイムアウトがありますから、
あまりにも長時間データの送信が行われないと、エラーとみなして[[接続]]が閉じられることがあります。
[573] 用途によっては、 [[payload body]] が無限に長いこともあります。
その場合は、相手側によって[[接続]]が閉じられたり、
ネットワークエラーなど外部的な要因で[[接続]]が閉じられたりしない限り、
データの送信が継続されます。
;; [574] ですから、 [[HTTP]] の実装は、[[メッセージ]]が有限の長さを持つことを仮定することはできません。
** [CODE(HTTP)[1xx]] 応答
[514] [CODE(HTTP)[[[1xx]]]] [[応答]]が最終[[応答]]より前に送信される場合には、
1つの[[要求]]に複数の[[応答]]が対応することとなります。 [SRC[>>512]]
[FIG(sequence)[
:C:[[クライアント]]
:S:[[鯖]]
:C -> S:[[要求]]
:S -> C:[CODE(HTTP)[[[1xx]]]] [[応答]]
:S -> C:[CODE(HTTP)[[[1xx]]]] [[応答]]
:S -> C:[[最後の応答]]
]FIG]
;; [527] [[要求]]送信後に[[接続]]が閉じられた場合など例外的なケースを除けば、
[[要求]]には必ず[[応答]]が送られます。
[56] [CODE(HTTP)[[[1xx]]]] [[応答]]は、 [[HTTP/1.1]] [[以上]]の場合に、
[[最後の応答]]の前に0個[[以上]]使うことができます。
[FIG(railroad)[
= *
== [CODE(HTTP)[[[1xx]]]] [[応答]]
= [[最後の応答]]
]FIG]
;; [162] [CODE(HTTP)[[[101]]]] の後 [[WebSocket]] に切り替わる場合は、
[[最後の応答]]はありません。
[570] [[要求]]に [CODE(HTTP)[[[100-continue]]]] が指定されている場合には、
[[要求]]の[[ヘッダー部]]を読み終えた時点で[[鯖]]が [CODE(HTTP)[[[100]]]]
[[応答]]を返し、その後[[要求]]の[[メッセージ本体]]を処理してから最終的な[[応答]]を返すことが期待されています。
(詳しくは [CODE(HTTP)[[[100-continue]]]] を参照してください。)
** サーバープッシュ
[65] [[HTTP/2]] では、[[クライアント]]が[[要求]]するかわりに[[サーバー]]が[[要求]]を[[クライアント]]へ送信し、
その後[[サーバー]]から[[クライアント]]へ[[応答]]を送信できます。
[66] 構文上は[[サーバー]]は任意の [[URL]] の[[応答]]を送信できます。
実際には当該[[サーバー]]が [[authoritative]] であることなどいくつかの制限があります。
;; 詳細は[[サーバープッシュ]]および >>96 を参照。
* 接続を閉じる
[558] [[クライアント]]、[[鯖]]、[[串]]はいずれも任意の時点で[[接続]]を閉じて構いません
[SRC[>>553, >>73]]。
[61] [[HTTP/2]] では、まず [CODE(HTTP)@en[[[GOAWAY]]]] [[フレーム]]を送信する[['''べきです''']]
[SRC[>>60, >>90, >>73]]。
しかし送信しない実装もあります。 [CODE(HTTP)[[[GOAWAY]]]] を参照。
[184] [[Firefox]] は、相手が [CODE(HTTP)@en[[[GOAWAY]]]] なしで接続を閉じた場合でも、
(他に問題がなければ) [[誤り符号]] [CODE[[[NO_ERROR]]]] の [CODE[[[GOAWAY]]]]
を送信してから、接続を閉じます。 [[Chrome]] はすぐに接続を閉じます。
[TIME[2015-10-12T04:44:18.00Z]]
[576] [[鯖]]は過負荷時に [WEAK[([CODE(HTTP)[[[503]]]] を返すか、または)]]
直ちに[[接続]]を閉じても構いません [SRC[>>577]]。
[540] [[接続]]はいつでも予告なく閉じられることがあります [SRC[>>539]]
から、[[実装]]は、[[接続]]の終了に対して[[頑強]]でなければなりません。
[567] [[HTTP/0.9]] や [[HTTP/1.0]] では、 [CODE(HTTP)@en[[[Keep-Alive]]]] が有効な場合を除き、
[[メッセージ]]の終わりで[[接続]]も閉じなければなりません。
[537] [[持続的接続]]の終了は、 [CODE(HTTP)@en[[[Connection:]] [[close]]]]
によって表します。
;; 詳しくは [CODE(HTTP)@en[[[close]]]] や[[持続的接続]]の項を参照してください。
[4] [[HTTP/1.1]] [[以下]]では、[[メッセージ本体]]の終了を[[接続]]を閉じることによって通知することがあります。
;; [[メッセージ本体]]の項を参照してください。
[561] [[鯖]]は、下位層プロトコルの特性により[[メッセージ]]の一部又は全部が失われないように注意して[[接続]]を閉じる必要があります。
詳しくは[[TCPリセット問題]]を参照してください。
;; [571] [CODE(HTTP)@en[[[CONNECT]]]] の項も参照してください。
[165] [[サーバー]]によっては [CODE[[[FIN]]]] を受け取った時点で[[応答]]の残りの転送を取りやめるようなので、
[[クライアント]]は[[応答]]の受信が終わるまで、[[要求]]の送信が終わったとしても[[接続]]を閉じてはいけません。
[64] [[HTTP/2]] では、[[ストリーム識別子]]が枯渇するとそれ以上[[メッセージ]]を送受信できなくなってしまいます。
[[クライアント]]は、新しい[[接続]]を確立して新しい[[ストリーム]]を作成できます
[SRC[>>62]]。[[サーバー]]は、 [CODE(HTTP)@en[[[GOAWAY]]]] [[フレーム]]を送信して[[クライアント]]に新しい[[接続]]を開くように求められます [SRC[>>62]]。
[135] [[Chrome]] と [[Firefox]] は、 [[abort a document]] による [[fetch]]
の中止の際は、正常に ([CODE[[[FIN]]]] で) [[接続]]を閉じるようです。
[[IE]] は [CODE[[[RST]]]] を使うようです。 [TIME[2015-08-01T15:17:36.000Z]]
** エラーによる接続の終了
[5] [[メッセージ本体]]が存在し、 [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
[[ヘッダー]]の最後の[[転送符号化]]が [CODE(HTTP)@en[[[chunked]]]]
以外である[[要求メッセージ]]を受け取った時は、 [CODE(HTTP)[[[400]]]]
[[応答]]を返して[[接続]]を閉じなければ[['''なりません''']] [SRC[>>3]]。
[510] [CODE(HTTP)[[[Content-Length:]]]] が無視されない場合で、
複数あったり[[非妥当]]だったりする場合は、
[[接続]]を閉じなければ[['''なりません''']] [SRC[>>3]]。
[511] [CODE(HTTP)[[[Content-Length:]]]] が無視されない場合で、
その長さの[[メッセージ本体]]を受け取らずに[[接続]]が閉じられたり、
[[タイムアウト]]したりした時には、[[接続]]を閉じなければ[['''なりません''']] [SRC[>>3]]。
[538] 下位ネットワークの障害や[[接続]]の当事者のシステム上の障害などによって、
[[メッセージ]]の途中で[[接続]]が中断されたり、
何の送受信も発生しないまま長時間経過したりすることがあります。
こうした場合の処理については、[[メッセージ]]や[[メッセージ本体]]の項を参照してください。
[547] [[パイプライン化]]している場合で途中で[[接続]]が閉じられたときの処理は、
[[HTTPパイプライン]]の項を参照してください。
[40] [[サーバー]]の[[死活監視]]を行うソフトウェアの中には、 [[TCP]]
レベルでの検査を行うものもあります。これは [[TCP接続]]が[[確立]]できることを確認すると、
すぐに切断するものです。この場合 [[HTTPメッセージ]]を送受信することなく[[接続]]が終了しますから、
[[サーバー]]はそのような場合も適切に処理できる必要があります。
[559] [[鯖]]は、[[クライアント]]が再試行すると期待して[[接続]]を閉じるよりは、
できれば[[持続的接続]]を維持して、一時的な過負荷は[[トランスポート層]]の[[フロー制御]]に任せる[['''べきです''']]
(閉じて再試行させる方が[[輻輳]]を悪化させるかもしれません) [SRC[>>553]]。
[560] [[クライアント]]は[[メッセージ本体]]の送信中に[[接続]]を監視して、
[[鯖]]が受信を望まず[[接続]]を閉じようとしていることがわかれば、
すぐに転送をやめて[[接続]]を閉じる[['''べきです''']] [SRC[>>553]]。
;; [580] [CODE(HTTP)[[[100]]]] や [CODE(HTTP)[[[413]]]] も参照してください。
[578] [[串]]は[[上流]]から[[非妥当]]な[[応答]]を受け取った時、
[[転送]]するかわりに [CODE(HTTP)[[[502]]]] [[応答]]を返すことができます。
[CODE(HTTP)@en[[[Content-Length:]]]] が[[非妥当]]な場合は更に[[接続]]を閉じなければならないこともあります。
詳しくは [CODE(HTTP)[[[502]]]] を参照してください。
[74] [[HTTP/2]] [[接続エラー]]の場合、 ([CODE(HTTP)@en[[[GOAWAY]]]] の後)
[[TCP接続]]を閉じなければ[['''なりません''']] [SRC[>>73]]。
;; [[接続エラー]]を参照。
[77] [[誤り符号]] [DFN[[CODE[[[ENHANCE_YOUR_CALM]]]]]] ([CODE[[[0xb]]]])
は、 [[過負荷]]を引き起こしかねない動作を [[peer]] が示したことを表します [SRC[>>76]]。
** タイムアウト
[554] [[鯖]]は普通は[[タイムアウト]]を設定しており、
活性状態でない[[接続]]をそれ以上維持しません。 [SRC[>>553]]
[555] [[串]]は、[[クライアント]]が同じ[[串]]により多く[[接続]]して来るであろうことから、
[[タイムアウト]]を大きめにするかもしれません。 [SRC[>>553]]
[556] [[クライアント]]も[[タイムアウト]]を設定して、
必要のない[[接続]]をそれ以上維持しないかもしれません。
[557] [[タイムアウト]]したい[[クライアント]]や[[鯖]]は、
当該[[接続]]を [[graceful close]] する[['''べきです''']] [SRC[>>553]]。
[[実装]]は定期的に[[接続]]を閉じる信号を監視して、
適宜応答する[['''べきです''']] [SRC[>>553]]。
[12] [[鯖]]によっては、[[HTTP/1.0]] [[応答]]を送り終えた後もしばらく[[接続]]を閉じないものがあるといわれています。
[71] [[nginx]] は、接続後何も送信しないでいると、タイムアウトにより何も返さずに[[接続]]を閉じるようです。
[TIME[2015-06-14T09:24:37.200Z]]
[264] [[nginx]] は標準状態では60s何も受信しないと、タイムアウトとするようです [SRC[>>263]]。
[REFS[
- [263] [CITE[Module ngx_http_core_module]] ([TIME[2016-08-29 21:17:12 +09:00]]) <https://nginx.org/en/docs/http/ngx_http_core_module.html>
]REFS]
[154] [[応答]]の受信後に次の[[要求]]を送信するため保持した状態の[[接続]]について、
[[Chrome]] は約300s、 [[Firefox]] は115s [SRC[>>159]] 未使用なら、閉じるようです。
[[IE]] は60s未使用なら、 [CODE[[[RST]]]] するようです [SRC[>>141]]。
[155] [[IE]] は、[[要求]]の送信があった後 3600s [[サーバー]]から送信がなければ、
[CODE[[[RST]]]] するようです。 (どこから起算しているかは未調査。最後の受信?)
[TIME[2015-08-16T05:11:42.000Z]]
[156] [[Firefox]] は [[TCP keep alive]] (>>153) が無効に設定されている時は、
300s 間[[サーバー]]から送信がなければ、タイムアウトとして接続を閉じます [SRC[>>142]]。
[160] [[Chrome]] や、[[Firefox]] で [[TCP keep alive]] が有効な場合 (既定の状態)
では、[[要求]]が送信された後[[応答]]を受信するまで ([[応答]]の一部を受信しようがしまいが)
タイムアウトは無いように見えます。 (少なくても20時間以上は切断されません。) [TIME[2015-08-16T08:18:24.200Z]]
;; [161] [[XHR]] の [CODE(DOMa)@en[[[timeout]]]] [[属性]]は、
[[接続]]の状態に関わらず、[[fetch]] の開始からの経過時間により[[fetch]]を中断するものです。
[195] [[クライアントライブラリー]]によっては、
[[要求]]の開始や[[応答]]の受信開始からの経過時間で[[タイムアウト]]を決めるものもあります。
しかし[[応答]]完了まで (正常時でも) 非常に時間がかかる[[サーバー]]もありますから、
相当に大きな値とする必要があります。それでは逆に異常時に[[タイムアウト]]エラーとなるまでかなり時間がかかってしまいますから、
あまりよい実装戦略ではなさそうです。
[196] [[サーバー]]によっては、無限に長い[[応答]]を送ることがあります。
従って[[対話的]]でない[[クライアント]]は、正常な受信中であっても、
一定時間経過後に受信を打ち切るようにする必要がありそうです。
** 接続枠解放
[260] [[持続的接続]]等で現時点で未使用の[[接続][HTTP接続]]を後で利用する(可能性がある)ため保持している場合で、
実装全体での、あるいは特定[[サーバー]]宛ての接続数上限に達した場合、
その未使用[[接続][HTTP接続]]を閉じて接続枠を開ける必要があるかもしれません。
;; [[接続プール]]参照。
* 要求の再試行
[541] [[実装]]は、[[接続]]が閉じられた時に回復しないといけないかもしれないことを想定しておく[RUBYB[べき]@en[ought to]]です
[SRC[>>539]]。
[542] [[クライアント]]は、[[内向き]]の[[接続]]が意図せず閉じられたとき、
中断された[[要求]]群がすべて[[冪等]]なメソッドだった場合には、
新しい[[接続]]を開いてその[[要求]]を自動的に再転送して構いません。 [SRC[>>539]]
[544] [[利用者エージェント]]は、何らかの手段で[[要求]]が本当は[[冪等]]であると分かっている場合や元の[[要求]]が適用されなかったと分かっている場合を除き、
[[冪等]]でない[[メソッド]]の[[要求]]を自動的に再試行しては[['''なりません''']]。
[SRC[>>539]]
[545] [[クライアント]]は、失敗した自動再試行を自動的に再試行する[['''べきではありません''']]
[SRC[>>539]]。
[543] [[串]]は、[[冪等]]でない[[要求]]を自動的に再試行しては[['''なりません''']]
[SRC[>>539]]。
;; [565] [CODE(HTTP)@en[[[Expect:]] [[100-continue]]]] についても、
自動的な再試行に関する規定があります。
[75] [[HTTP/2]] の [[TCP接続]]が閉じられたり [[RST]] されたりした時に [[open]]
や [[half-closed]] の[[状態]]だった[[ストリーム]]は、
自動的に再試行することはできません [SRC[>>73]]。
[83] [[HTTP/2]] では、次の場合、[[クライアント]]は[[要求]]が処理されていないことが保証されます [SRC[>>82]]。
[FIG(list)[
- [84] [CODE(HTTP)@en[[[GOAWAY]]]] [[フレーム]]で示された最大[[ストリーム識別子]]よりも大きな[[ストリーム識別子]]の[[ストリーム]]の[[要求]]は、
処理されていません。
- [85] [CODE(HTTP)@en[[[RST_STREAM]]]] [[フレーム]]で[[誤り符号]]
[CODE(HTTP)@en[[[REFUSED_STREAM]]]] が指定されていれば、その[[ストリーム]]の[[要求]]は処理されていません。
]FIG]
[86] これらの処理されていない[[要求]]は、失敗ではなく、
[[クライアント]]は[[冪等]]か否かに関わらず自動的に再試行して構いません [SRC[>>82]]。
[107] [CODE(HTTP)[[[421]]]] [[応答]]を受信した[[クライアント]]は、
[[冪等]]か否かに関わらず自動的に再試行して構いません [SRC[>>90]]。
[[代替サービス]]から受信した場合は、当該[[代替サービス]]情報は削除しなければ[MUST[ならず]]、
他の[[代替サービス]]や[[起源サーバー]]に再試行して構いません。
;; [CODE(HTTP)[421]] 参照。
[138] [[Chrome]] も [[Firefox]] も [[IE]] も、 ([CODE(HTTP)@en[[[GET]]]] でも
[CODE(HTTP)@en[[[POST]]]] でも) [[持続的接続]]の2つ目の[[要求]]に対して[[応答]]を受信せず[[接続]]が切断された場合、
他の[[接続]]で改めて[[要求]]を送信するようです。 [TIME[2015-08-12T10:25:17.300Z]]
* 版の切り替え
[79] [[誤り符号]] [DFN[[CODE[[[HTTP_1_1_REQUIRED]]]]]] ([CODE[[[0xd]]]])
は、 [[HTTP/2]] ではなく [[HTTP/1.1]] が必要であることを示します [SRC[>>76]]。
[179] その詳細な処理方法はどこでも規定されていません。いつこれを送れるのかも明確ではありません。
[183] [[HTTP/2]] では[[再折衝]]が禁止されているため、[[クライアント認証]]が必要な時は
[CODE[[[HTTP_1_1_REQUIRED]]]] を送信するべきだとされています。
[174] [[Chrome]] も [[Firefox]] も、 [CODE[[[HEADERS]]]] より前に
[CODE[[[RST_STREAM]]]] や [CODE[[[GOAWAY]]]] で [CODE[[[HTTP_1_1_REQUIRED]]]]
を受信すると、 [[HTTP/1.1]] で接続し直すようです。
[TIME[2015-10-11T15:03:47.200Z]]
;; [175] 既に [[HTTP/1.1]] の接続があれば、再利用するかもしれません (未検証)。
[176] [[Chrome]] は [CODE[[[HEADERS]]]] より後だと、 ([CODE[[[RST_STREAM]]]] であっても)
接続を閉じて、[[ネットワークエラー]]とするようです。 [TIME[2015-10-11T15:04:59.500Z]]
[177] [[Firefox]] は [CODE[[[HEADERS]]]] より後だと、
[[ネットワークエラー]]とするようです。 [TIME[2015-10-11T15:05:21.500Z]]
[178] [[Chrome]] も [[Firefox]] も、再接続時には [[ALPN]] で [CODE[[[http/1.1]]]]
だけを指定します。 [TIME[2015-10-11T15:06:38.200Z]]
[180] (にも関わらず) [[サーバー]]が [[ALPN]] で [CODE[[[h2]]]] を指定すると、
[[Chrome]] も [[Firefox]] も [[HTTP/2]] を使います。更に [CODE[[[HTTP_1_1_REQUIRED]]]]
を返すと、 [[Firefox]] は何度か試して諦めますが、 [[Chrome]] は無限に(?)試し続けます。
[TIME[2015-10-11T15:07:56.500Z]]
[201] 理論上は [CODE(HTTP)@en[Upgrade: h2c]] によって [[HTTP/1]] から
[[HTTP/2]] への切り替えを指示できます (が実装されていません)。
[200] [[Chrome]] は、 [CODE(HTTP)@en[Alt-Svc:]] [[ヘッダー]]によって
[[QUIC]] が利用可能なことを認識できます。
;; [CODE(HTTP)@en[Alt-Svc:]] 参照。
* ヘッダー
[521] [CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]は、[[接続]]の取り扱いを指定するものです。
[21] [CODE(HTTP)@en[[[Expect:]] [[100-continue]]]] はデータの送信のタイミングについて指示するものです。
;; [CODE(HTTP)@en[[[100-continue]]]] 参照。
* 下位層プロトコル
[516] [[HTTP]] の[[メッセージ]]は下位の ([[トランスポート層]]や[[セッション層]]の)
[[プロトコル]]に依存しておらず、[[信頼できる]]輸送路であって、
[[要求]]の順序を保存した配送と[[応答]]の順序を保存した配送のみを要求しています [SRC[>>515]]。
[2] 実際には [[HTTP]] は、下位層プロトコルとして、
[FIG(list short)[
- [517] [[TCP]]
- [518] [[TLS]]
- [[Unix domain socket]]
- [[HTTP]] [CODE(HTTP)@en[[[CONNECT]]]]
- [[SOCKS]]
]FIG]
... のいずれかを用います。
;; [7] [[UPnP]] では [[UDP]] が使われます ([[SSDP]])。
;; [37] [[HTTP over SCTP]] も提案されましたが、関心を集められませんでした。
[519] [[HTTP]] の[[要求]]や[[応答]]の構造と下位層プロトコルのデータ単位との対応関係は、
[[HTTP]] の仕様書の[[適用範囲]]外とされています [SRC[>>515]]。
;; [520] それ、[[アプリケーション層プロトコル]]の重要なところじゃないのでしょうか。。。
[59] [[HTTP/2]] では [[HTTP/1.1]] よりは詳しく規定があります (が完全ではありません)。
** TCP
[192] [[HTTP]] over [[TCP]] は、従来標準的に用いられていました。
現在は安全ではないと考えられているため、徐々に [[HTTPS]] に置き換えられてきています。
[193] [[HTTP]] over [[TCP]] を [[HTTPS]] と区別するため、
[DFN[素のHTTP]]と呼ぶことがあります。
[41] [[HTTP]] over [[TCP]] は、 [CODE(URI)@en[[[http:]]]] [[URL]] によって表されます。
[17] [[three-way handshake]] を経て [[TCP]] [[接続]]が確立された後に [[TCP]]
によって伝送される[[オクテット列]]が [[HTTP接続]]の[[オクテット列]]です。
なお [[TCP]] [[セグメント]]の境界は [[HTTP接続]]に反映されません。
[[TCP]] [[セグメント]]の境界と [[HTTP接続]]上の[[メッセージ]]境界と一致しているとは限りません。
-*-*-
[33] [[TCP]] [CODE[[[PSH]]]] フラグの取り扱いについて [[HTTP]] 特有の規定は特に無いと思われます。
(例えば[[HTTPメッセージ]]の最後で [CODE[[[PSH]]]] フラグを立てなければならないというようなことは特にありません。)
[16] [[TCP]] [[緊急データ]]と [[HTTP]] の関係は明文化されていません。
[125] [[応答]]の受信中に[[緊急データ]]が含まれていた場合、次のように動作するようです
(いずれも [[Windows]])。 [TIME[2015-06-15T03:40:23.400Z]]
[FIG(list)[
- [126] [[IE]] はレンダリングを[[非文書表示]]に切り替えます。 [[Firefox]] と [[Chrome]]
は通常通りです。
- [127] [[IE]] と [[Firefox]] は [CODE[[[RST]]]] を送信します。
- [128] [[Firefox]] も [[Chrome]] も、[[緊急ポインター]]が指す1バイトを無視し、その前後のバイト列のみが送られたものとして処理します。
]FIG]
-*-*-
[18] [[HTTP接続]]を閉じる、あるいは閉じられるとは、 [[TCP]] [[接続]]を閉じる、あるいは閉じられることを意味します。
[[HTTP接続]]を閉じると [CODE[[[FIN]]]] [[セグメント]]が送信されることになります。
[CODE[[[FIN]]]] [[セグメント]]を受信すると [[HTTP接続]]が相手に閉じられたことを表します。
その他に [CODE[[[RST]]]] や[[タイムアウト]]など [[TCP]] プロトコル上の規定や実装によって正常でない形で接続が閉じられることもあります。
[72] [[応答]]の受信中に [CODE[[[RST]]]] を受信した場合、次のように動作するようです
(いずれも [[Windows]])。
[TIME[2015-06-14T14:27:40.700Z]]
[FIG(list)[
- (前提として) [[Firefox]] はできるだけすぐに[[レンダリング]]を開始するようです。
[[IE]] と [[Chrome]] はある程度のデータを受信しないと処理開始しないようです。
- [[Firefox]] と [[IE]] は、レンダリング開始後であっても、 [CODE[[[RST]]]]
を受信したら [CODE[[[RST]]]] を受信した旨の[[非文書表示]]に切り替えます。
[[Chrome]] はレンダリング開始前ならそうしますが、開始後なら何も表示しません
([[開発者ツール]]にはエラーが表示されます)。
- ただし [[Firefox]] は場合によっては切り替わらない、あるいは自動的に再試行しようとするようです (詳細不明)。
]FIG]
;; [124] [[TCP]] が [CODE[[[RST]]]] を受信した時点でまだ[[アプリケーション]]に渡されていないデータの扱いは、
[[TCP]] の実装によって異なるようです。エラーとして扱う以外に[[相互運用可能]]な方法はなさそうです。