Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http2: near full http1 compatibility, add tests #15702

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,12 @@ SETTINGS. By default, a maximum number of un-acknowledged `SETTINGS` frame may
be sent at any given time. This error code is used when that limit has been
reached.

<a id="ERR_HTTP2_NO_SOCKET_MANIPULATION"></a>
### ERR_HTTP2_NO_SOCKET_MANIPULATION

Used when attempting to read, write, pause, and/or resume a socket attached to
an `Http2Session`.

<a id="ERR_HTTP2_OUT_OF_STREAMS"></a>
### ERR_HTTP2_OUT_OF_STREAMS

Expand Down
97 changes: 63 additions & 34 deletions doc/api/http2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2046,7 +2046,7 @@ console.log(request.headers);

See [Headers Object][].

### request.httpVersion
#### request.httpVersion
<!-- YAML
added: v8.4.0
-->
Expand Down Expand Up @@ -2117,7 +2117,14 @@ added: v8.4.0
* `msecs` {number}
* `callback` {Function}

Calls `request.connection.setTimeout(msecs, callback)`.
Sets the [`Http2Stream`]()'s timeout value to `msecs`. If a callback is
provided, then it is added as a listener on the `'timeout'` event on
the response object.

If no `'timeout'` listener is added to the request, the response, or
the server, then [`Http2Stream`]()s are destroyed when they time out. If a
handler is assigned to the request, the response, or the server's `'timeout'`
events, timed out sockets must be handled explicitly.

Returns `request`.

Expand All @@ -2128,13 +2135,24 @@ added: v8.4.0

* {net.Socket}

The [`net.Socket`][] object associated with the connection.
Returns a Proxy object that acts as a `net.Socket` but applies getters,
setters and methods based on HTTP/2 logic.

`destroyed`, `readable`, and `writable` properties will be retrieved from and
set on `request.stream`.

With TLS support, use [`request.socket.getPeerCertificate()`][] to obtain the
client's authentication details.
`destroy`, `emit`, `end`, `on` and `once` methods will be called on
`request.stream`.

*Note*: do not use this socket object to send or receive any data. All
data transfers are managed by HTTP/2 and data might be lost.
`setTimeout` method will be called on `request.stream.session`.

`pause`, `read`, `resume`, and `write` will throw an error with code
`ERR_HTTP2_NO_SOCKET_MANIPULATION`. See [`Http2Session and Sockets`][] for
more information.

All other interactions will be routed directly to the socket. With TLS support,
use [`request.socket.getPeerCertificate()`][] to obtain the client's
authentication details.

#### request.stream
<!-- YAML
Expand Down Expand Up @@ -2232,15 +2250,15 @@ passed as the second parameter to the [`'request'`][] event.
The response implements, but does not inherit from, the [Writable Stream][]
interface. This is an [`EventEmitter`][] with the following events:

### Event: 'close'
#### Event: 'close'
<!-- YAML
added: v8.4.0
-->

Indicates that the underlying [`Http2Stream`]() was terminated before
[`response.end()`][] was called or able to flush.

### Event: 'finish'
#### Event: 'finish'
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2252,7 +2270,7 @@ does not imply that the client has received anything yet.

After this event, no more events will be emitted on the response object.

### response.addTrailers(headers)
#### response.addTrailers(headers)
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2265,7 +2283,7 @@ message) to the response.
Attempting to set a header field name or value that contains invalid characters
will result in a [`TypeError`][] being thrown.

### response.connection
#### response.connection
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2274,7 +2292,7 @@ added: v8.4.0

See [`response.socket`][].

### response.end([data][, encoding][, callback])
#### response.end([data][, encoding][, callback])
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2293,7 +2311,7 @@ If `data` is specified, it is equivalent to calling
If `callback` is specified, it will be called when the response stream
is finished.

### response.finished
#### response.finished
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2303,7 +2321,7 @@ added: v8.4.0
Boolean value that indicates whether the response has completed. Starts
as `false`. After [`response.end()`][] executes, the value will be `true`.

### response.getHeader(name)
#### response.getHeader(name)
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2320,7 +2338,7 @@ Example:
const contentType = response.getHeader('content-type');
```

### response.getHeaderNames()
#### response.getHeaderNames()
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2340,7 +2358,7 @@ const headerNames = response.getHeaderNames();
// headerNames === ['foo', 'set-cookie']
```

### response.getHeaders()
#### response.getHeaders()
<!-- YAML
added: v8.4.0
-->
Expand Down Expand Up @@ -2368,7 +2386,7 @@ const headers = response.getHeaders();
// headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] }
```

### response.hasHeader(name)
#### response.hasHeader(name)
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2385,7 +2403,7 @@ Example:
const hasContentType = response.hasHeader('content-type');
```

### response.headersSent
#### response.headersSent
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2394,7 +2412,7 @@ added: v8.4.0

Boolean (read-only). True if headers were sent, false otherwise.

### response.removeHeader(name)
#### response.removeHeader(name)
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2409,7 +2427,7 @@ Example:
response.removeHeader('Content-Encoding');
```

### response.sendDate
#### response.sendDate
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2422,7 +2440,7 @@ the response if it is not already present in the headers. Defaults to true.
This should only be disabled for testing; HTTP requires the Date header
in responses.

### response.setHeader(name, value)
#### response.setHeader(name, value)
<!-- YAML
added: v8.4.0
-->
Expand Down Expand Up @@ -2463,7 +2481,7 @@ const server = http2.createServer((req, res) => {
});
```

### response.setTimeout(msecs[, callback])
#### response.setTimeout(msecs[, callback])
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2482,18 +2500,29 @@ events, timed out sockets must be handled explicitly.

Returns `response`.

### response.socket
#### response.socket
<!-- YAML
added: v8.4.0
-->

* {net.Socket}

Reference to the underlying socket. Usually users will not want to access
this property. In particular, the socket will not emit `'readable'` events
because of how the protocol parser attaches to the socket. After
`response.end()`, the property is nulled. The `socket` may also be accessed
via `response.connection`.
Returns a Proxy object that acts as a `net.Socket` but applies getters,
setters and methods based on HTTP/2 logic.

`destroyed`, `readable`, and `writable` properties will be retrieved from and
set on `response.stream`.

`destroy`, `emit`, `end`, `on` and `once` methods will be called on
`response.stream`.

`setTimeout` method will be called on `response.stream.session`.

`pause`, `read`, `resume`, and `write` will throw an error with code
`ERR_HTTP2_NO_SOCKET_MANIPULATION`. See [`Http2Session and Sockets`][] for
more information.

All other interactions will be routed directly to the socket.

Example:

Expand All @@ -2506,7 +2535,7 @@ const server = http2.createServer((req, res) => {
}).listen(3000);
```

### response.statusCode
#### response.statusCode
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2526,7 +2555,7 @@ response.statusCode = 404;
After response header was sent to the client, this property indicates the
status code which was sent out.

### response.statusMessage
#### response.statusMessage
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2545,7 +2574,7 @@ added: v8.4.0

The [`Http2Stream`][] object backing the response.

### response.write(chunk[, encoding][, callback])
#### response.write(chunk[, encoding][, callback])
<!-- YAML
added: v8.4.0
-->
Expand Down Expand Up @@ -2583,7 +2612,7 @@ Returns `true` if the entire data was flushed successfully to the kernel
buffer. Returns `false` if all or part of the data was queued in user memory.
`'drain'` will be emitted when the buffer is free again.

### response.writeContinue()
#### response.writeContinue()
<!-- YAML
added: v8.4.0
-->
Expand All @@ -2592,7 +2621,7 @@ Sends a status `100 Continue` to the client, indicating that the request body
should be sent. See the [`'checkContinue'`][] event on `Http2Server` and
`Http2SecureServer`.

### response.writeHead(statusCode[, statusMessage][, headers])
#### response.writeHead(statusCode[, statusMessage][, headers])
<!-- YAML
added: v8.4.0
-->
Expand Down Expand Up @@ -2648,7 +2677,7 @@ const server = http2.createServer((req, res) => {
Attempting to set a header field name or value that contains invalid characters
will result in a [`TypeError`][] being thrown.

### response.createPushResponse(headers, callback)
#### response.createPushResponse(headers, callback)
<!-- YAML
added: v8.4.0
-->
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ E('ERR_HTTP2_INVALID_SETTING_VALUE',
E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed');
E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK',
(max) => `Maximum number of pending settings acknowledgements (${max})`);
E('ERR_HTTP2_NO_SOCKET_MANIPULATION',
'HTTP/2 sockets should not be directly read from, written to, ' +
'paused and/or resumed.');
E('ERR_HTTP2_OUT_OF_STREAMS',
'No stream ID is available because maximum stream ID has been reached');
E('ERR_HTTP2_PAYLOAD_FORBIDDEN',
Expand Down
Loading