-
Notifications
You must be signed in to change notification settings - Fork 6
/
draft-hirano-websocket-over-http2.xml
399 lines (374 loc) · 21 KB
/
draft-hirano-websocket-over-http2.xml
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
<?xml version="1.0" encoding="UTF-8" ?>
<?rfc notedraftinprogress="yes" ?>
<?rfc rfcprocack="yes" ?>
<?rfc symrefs="yes" ?>
<?rfc toc="yes" ?>
<rfc
category="std"
docName="draft-hirano-httpbis-websocket-over-http2-01"
ipr="trust200902">
<front>
<title>WebSocket over HTTP/2</title>
<author
initials="Y.H."
surname="Hirano"
fullname="Yutaka Hirano">
<organization>Google, Inc.</organization>
<address>
<email>[email protected]</email>
</address>
</author>
<date month="August" year="2014"/>
<area>Applications</area>
<workgroup>HTTPbis Working Group</workgroup>
<abstract>
<t>
The WebSocket protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code.
It requires one TCP connection for every WebSocket connection, but WebSocket connections often live for long time and are idle for most of the time.
By multiplexing WebSocket traffic between the same client-server pair onto one TCP connection, we can reduce resource spent for TCP socket while keeping WebSockets useful.
On the other hand, HTTP/2 specifies a fast, secure, multiplexed framing protocol.
This document provides bi-directional multiplexed communication by layering WebSocket on top of HTTP/2.
</t>
<t>
Please send feedback to the [email protected] mailing list.
</t>
</abstract>
</front>
<middle>
<section title="Introduction">
<t>
The WebSocket protocol was standardized to enable efficient bidirectional messaging mainly for browsers.
However, the core spec in RFC 6455 left one problem about scalability unaddressed.
That is that one WebSocket connection uses one TCP connection.
Use of multiple WebSocket connections provides flexibility for web apps, while using more TCP connections leads to more load to the end hosts and also to network intermediaries.
</t>
<t>
For the HTTP/1.1, there has been effort to multiplex HTTP traffic into one TCP connection called HTTP/2.
The HTTP/2 defines a general multiplexed transport on which not only HTTP but other messaging application protocol may be layered onto.
We can address the scalability issue of WebSocket by using HTTP/2 framing's multiplexing functionality.
</t>
<t>
In this document, we describe how to layer WebSocket semantics onto HTTP/2 semantics by defining detailed mapping, replacement of operations and events defined in RFC 6455.
</t>
<section title="Document Organization">
<t>
WebSocket over HTTP/2 is a protocol that layers the WebSocket protocol over an HTTP/2 stream rather than a TCP connection.
This document introduces some abstractions and overrides some definitions in <xref target="RFC6455"/>.
Definitions in <xref target="RFC6455"/> not overridden by this document such as Error Handling or Extensions are still valid.
</t>
<t>
<xref target="protocol_negotiation"/> describes how to choose the protocol to use between native WebSocket and WebSocket over HTTP/2 for each server.
Each of <xref target="opening_handshake"/>, <xref target="framing"/> and <xref target="closing_connection"/> overrides definitions and rules in its counterpart in <xref target="RFC6455"/>.
</t>
</section>
</section>
<section title="Conformance Requirements and Terminology">
<t>
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in <xref target="RFC2119" />.
</t>
<t>
Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("MUST", "SHOULD", "MAY", etc.) used in introducing the algorithm.
</t>
<t>
Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent.
In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant.
</t>
<t>
Native WebSocket means the WebSocket specified in <xref target="RFC6455" />.
</t>
<t>
"Frame" has two meanings, WebSocket frame and HTTP/2 frame.
When it is obvious "WebSocket" and "HTTP/2" can be omitted.
For example, "DATA frame" means "HTTP/2 DATA frame" and "Close frame" means "WebSocket Close frame".
</t>
</section>
<section title="Cross Protocol Negotiation" anchor="protocol_negotiation">
<section title="Overview">
<t><spanx style="emph">This section is non-normative.</spanx>.</t>
<t>
To establish a WebSocket connection, a client needs to decide the protocol to use.
Roughly speaking, if a client knows the server's preference the client will connect to the server with the protocol.
Otherwise, the client tries to connect to the server with the native WebSocket.
</t>
</section>
<section title="server preference">
<t>
The server can tell its preference between the WebSocket over HTTP/2 and the native WebSocket by the following means.
<list style="symbols">
<t>Sending <xref target="ALT-SVC"/> information to the client</t>
<t>Selecting an ALPN protocol</t>
</list>
</t>
</section>
<section title="WebSocket over HTTP/2 capability">
<t>
When two endpoints and all intermediaries between them understand WebSocket over HTTP/2, we say the communication path consisting of these nodes is capable of WebSocket over HTTP/2.
</t>
<t>
The client MUST send a SETTINGS frame containing SETTINGS_WEBSOCKET_CAPABLE before it starts the first WebSocket opening handshake on a HTTP/2 connection.
</t>
<t>
The client knows if the communication path towards the server is capable of WebSocket over HTTP/2 when the handshake response is received.
<list style="symbols">
<t>If status code of the response is other than 501 (Not Implemented), the communication path is capable of WebSocket over HTTP/2.</t>
<t>If status code of the response is 501 (Not Implemented), the communication path is not capable of WebSocket over HTTP/2.</t>
</list>
</t>
<t>
When the server receives a handshake from a client, the server MUST send the server's opening handshake.
</t>
<t>
If the server has never received a SETTINGS frame that contains SETTINGS_WEBSOCKET_CAPABLE on the HTTP/2 connection, the server MUST send a 501 (Not Implemented) status code.
</t>
<t>
Otherwise, the server MUST NOT send a 501 (Not Implemented) status code.
</t>
<t>
The client MAY start an opening handshake with WebSocket over HTTP/2 without knowing if the communication path is capable of WebSocket over HTTP/2.
When the status code of the opening handshake handshake from the server is 501 (Not Implemented), the client MAY start another opening handshake with the native WebSocket. If it comes to that, the connection failure MUST not be reported to the upper layer.
</t>
<t>
NOTE: The server may reset the stream. In such a case, the client doesn't know if the communication path is capable of WebSocket over HTTP/2.
</t>
<t>
The client MUST not start an opening handshake with WebSocket over HTTP/2 when it knows that the communication path is not capable of WebSocket over HTTP/2.
</t>
</section>
<section title="secure connection">
<t>
If the client knows that the server prefers WebSocket over HTTP/2 more than the native WebSocket and there is an existing HTTP/2 connection, the client create an HTTP/2 stream on the HTTP/2 connection.
</t>
<t>
Otherwise, the client sets up a TLS connection.
The client SHOULD send one or two of the following application protocols as ProtocolNameList as specified in <xref target="ALPN"/> in any order.
<list style="symbols">
<t>"http/1.1" for the native WebSocket over TLS</t>
<t>"h2ws" for secure WebSocket over HTTP/2.</t>
</list>
If the server selects the "h2ws" protocol, the client SHOULD connect to the server with WebSocket over HTTP/2 on the TLS connection.
If the server selects the "http/1.1" protocol or the server does not support ALPN, the client SHOULD connect to the server with the native WebSocket on the TLS connection.
If the server returns "no_application_protocol" alert, the client MUST <spanx style="emph">Fail the WebSocket connection</spanx>.
</t>
</section>
<section title="the server's preference">
<t>
The client SHOULD keep track of the <xref target="ALT-SVC" /> information provided by the server and use it as the server's preference.
</t>
<t>
Note that though a client uses the ALPN protocol when it sets up a TLS connection, it SHOULD not use the information after that.
</t>
</section>
</section>
<section title="Opening Handshake" anchor="opening_handshake">
<section title="Handshake Request">
<t>
The client initiates an opening handshake by sending a HEADERS frame.
The frame MUST NOT set the END_STREAM flag because WebSocket intends to establish a bi-directional communication port and to send arbitrary data after success in opening handshake.
The HEADERS Name/Value section will contain all of the following headers which are associated with the WebSocket protocol <xref target="RFC6455" /> opening handshake.
Upgrade, Connection, Sec-WebSocket-Key, and Sec-WebSocket-Version headers MUST NOT be included because we do not have to take care of protocol upgrading or verification over HTTP.
The following name/value pairs MUST be present in every request:
<list style="empty">
<t>
“:path”: /resource name/ as used in the “Client Requirements” section of the WebSocket protocol specification. (See <xref target="RFC6455" />)
</t>
<t>
“:authority”: /host:port/ (e.g. “www.example.com:1234”) as used in the “Client Requirements” section of the WebSocket protocol specification. (See <xref target="RFC6455" />)
</t>
<t>
“websocket-version”: the WebSocket protocol version of this request. MUST be “WebSocket/13”.
</t>
<t>
“:scheme”: the scheme portion of the URI. MUST be “ws” or “wss”. (See also /secure/ flag in <xref target="RFC6455" />)
</t>
<t>
“websocket-origin”: /origin/ as used in the “Client Requirements” section of the WebSocket protocol specification. (See <xref target="RFC6455" />)
</t>
</list>
In addition, the following OPTIONAL name/value pairs MAY be present:
<list style="empty">
<t>
“sec-websocket-protocol” - the Sec-WebSocket-Protocol header (See <xref target="RFC6455" />)
</t>
<t>
“sec-websocket-extensions” - the Sec-WebSocket-Extensions header (See <xref target="RFC6455" />)
</t>
</list>
Also, other HTTP compatible header name/value pairs MAY be present.
</t>
</section>
<section title="Handshake Response">
<t>
The server responds to a client request with a HEADERS frame.
If the server intends to allow the client connection, the HEADERS frame MUST NOT set the END_STREAM flag and MUST have “:status” containing “101”.
Any status code other than 101 indicates that the WebSocket handshake has not completed and that the semantics of HTTP still apply.
The client MAY send some data to the server before receiving the successful response.
The server MUST ignore this data when opening handshake fails. After sending successful response, the server can send arbitrary data frames at any time.
The response status line is unfolded into name/value pairs like other WebSocket handshake headers and MUST be present: “:status” - The WebSocket or fallback HTTP response status code (e.g. “101” or “101 Switching Protocols”. See <xref target="RFC6455" />).
In addition, the following OPTIONAL name/value pairs MAY be present:
<list style="empty">
<t>
“sec-websocket-protocol” - the Sec-WebSocket-Protocol header (See <xref target="RFC6455" />)
</t>
<t>
“sec-websocket-extensions” - the Sec-WebSocket-Extensions header (See <xref target="RFC6455" />)
</t>
</list>
Also, other HTTP compatible header name/value pairs MAY be present.
All header names MUST be lowercase. The successful server response MUST have “:status” containing “101”.
</t>
<section title="The Alt-Svc header">
<t>
When the Alt-Svc header field is contained in the handshake response, the client SHOULD use the advertised service if possible.
Note that the Alt-Svc header field takes effect even for the handshake response whose status code is not 101.
</t>
<t>
If the client receives an opening handshake response having the Alt-Svc header field and the client is able to work with the advertised service, the client SHOULD send a Close frame with code 1006 and reason like "Alternate Service: h2ws" and then close the WebSocket connection as soon as possible.
These transactions MUST be hidden and MUST NOT be notified to upper layers like the JavaScript event queue.
Then, the client SHOULD connect to the advertised server with the advertised protocol.
</t>
</section>
</section>
</section>
<section title="Data Framing" anchor="framing">
<t>
TO BE WRITTEN
</t>
</section>
<section title="Closing the Connection" anchor="closing_connection">
<t>
Some definitions in <xref target="RFC6455"/> are overridden in this section.
</t>
<section title='Definitions'>
<section title="Close the WebSocket Connection" anchor="close_wsc">
<t>
To <spanx style="emph">Close the WebSocket Connection</spanx>, an endpoint closes the underlying HTTP/2 stream.
If the stream is already closed, the endpoint MUST do nothing.
Otherwise, the endpoint MUST send an RST_STREAM frame with an appropriate error code.
</t>
</section>
<section title="Start the WebSocket Closing Handshake" anchor="start_closing">
<t>
To <spanx style="emph">Start the WebSocket Closing Handshake</spanx> with a status code (<xref target='status_codes'/>) /code/ and an optional close reason (<xref target='close_reason'/>) /reason/, an endpoint MUST send a Close control frame, as described in <xref target="RFC6455"/> whose status code is set to /code/ and whose close reason is set to /reason/.
The last HTTP/2 frame of the WebSocket Close control frame MUST turn END_STREAM flag on.
</t>
</section>
<section title="The WebSocket Closing Handshake is Started">
<t>Same as Section 7.1.3 in <xref target="RFC6455"/>.</t>
</section>
<section title='The WebSocket Connection is Closed' anchor='is_closed'>
<t>
When the underlying HTTP stream is closed, it is said that <spanx style='emph'>The WebSocket Connection is Closed</spanx> and that the WebSocket connection is in the CLOSED state.
If the stream was closed after the WebSocket closing handshake was completed, the WebSocket connection is said to have been closed <spanx style='emph'>cleanly</spanx>.
</t>
<t>
If the WebSocket connection could not be established, it is also said that <spanx style='emph'>The WebSocket Connection is Closed</spanx>, but not cleanly.
</t>
</section>
<section title='The WebSocket Connection Close Code' anchor='closecode'>
<t>Same as Section 7.1.5 in <xref target="RFC6455"/>.</t>
</section>
<section title='The WebSocket Connection Close Reason' anchor='close_reason'>
<t>Same as Section 7.1.6 in <xref target="RFC6455"/>.</t>
</section>
<section title='Fail the WebSocket Connection' anchor='fail_ws'>
<t>Same as Section 7.1.7 in <xref target="RFC6455"/>.</t>
</section>
</section>
<section title='Abnormal Closures'>
<section title='Client-Initiated Closure'>
<t>
If at any point the underlying HTTP/2 stream is unexpectedly terminated, the client MUST <spanx style="emph">Fail the WebSocket Connection</spanx>.
</t>
<t>
Except as indicated above or as specified by the application layer
(e.g. a script using the WebSocket API), clients SHOULD NOT
close the connection.
</t>
</section>
<section title='Server-initiated closure'>
<t>Same as Section 7.2.2 in <xref target="RFC6455"/>.</t>
</section>
<section title='Recovering from Abnormal Closure'>
<t>Same as Section 7.2.3 in <xref target="RFC6455"/>.</t>
</section>
</section>
<section title='Normal Closure of Connections'>
<t>Same as Section 7.3 in <xref target="RFC6455"/>.</t>
</section>
<section title='Status Codes' anchor='status_codes'>
<t>Same as Section 7.4 in <xref target="RFC6455"/>.</t>
</section>
</section>
<section title="Security Considerations">
<t>
<xref target="RFC6455"/> frame has the masking mechanism for two purposes.
<list style="symbols">
<t>
To prevent a misbehavior of transparent proxies.
</t>
<t>
To prevent TLS side-channel attacks such as <xref target="BEAST"/>.
</t>
</list>
These should be addressed at the HTTP/2 framing layer and WebSocket over HTTP/2 has no masking mechanism.
</t>
</section>
<section title="IANA Considerations">
<section title='Registration of New SETTINGS parameter'>
<t>
This section describes a new SETTINGS parameter.
</t>
<t>
SETTINGS_WEBSOCKET_CAPABLE(0xxx):
The Client uses this parameter to declare that it wants to use WebSocket over HTTP/2.
This parameter must be sent before creating any WebSocket over HTTP/2 stream in an HTTP/2 connection.
</t>
</section>
</section>
</middle>
<back>
<references title="Normative References">
<?rfc include="reference.RFC.6455" ?>
<?rfc include="reference.RFC.2119" ?>
<reference anchor="HTTP-2">
<front>
<title>Hypertext Transfer Protocol version 2</title>
<author initials="M." surname="Belshe" fullname="Mike Belshe"></author>
<author initials="R." surname="Peon" fullname="Roberto Peon"></author>
<author initials="M." surname="Thomson" fullname="Martin Thomson"></author>
<author initials="A." surname="Melnikov" fullname="Alexey Melnikov"></author>
<date month="August" year="2014" />
</front>
</reference>
<reference anchor="ALPN">
<front>
<title>Transport Layer Security (TLS) Application Layer Protocol Negotiation Extension</title>
<author initials="S." surname="Friedl" fullname="Stephan Friedl"></author>
<author initials="A." surname="Popov" fullname="Andrei Popov"></author>
<author initials="A." surname="Langley" fullname="Adam Langley"></author>
<author initials="E." surname="Stephan" fullname="Emile Stephan"></author>
<date month="March" year="2014" />
</front>
</reference>
<reference anchor="ALT-SVC">
<front>
<title>HTTP Alternative Services</title>
<author initials="M." surname="Nottingham" fullname="Mark Nottingham"></author>
<author initials="P." surname="McManus" fullname="Patrick McManus"></author>
<author initials="J." surname="Reschke" fullname="Julian F. Reschke"></author>
<date month="July" year="2014" />
</front>
</reference>
</references>
<references title="Informative References">
<reference anchor="BEAST">
<front>
<title>The BEAST attack</title>
<author initials="T." surname="Duong" fullname="Thai Duong"></author>
<author initials="J." surname="Rizzo" fullname="Juliano Rizzo"></author>
<date year="2011"/>
</front>
</reference>
</references>
</back>
</rfc>