summaryrefslogtreecommitdiff
path: root/test/parallel/test-http2-compat-serverresponse-end.js
diff options
context:
space:
mode:
authorAnatoli Papirovski <apapirovski@mac.com>2017-10-02 21:56:53 -0400
committerMatteo Collina <hello@matteocollina.com>2017-10-06 14:04:22 -0700
commit2da7d9b8207d9c35d199734da75fa2bb15f326b6 (patch)
tree9aa1ed51d29bc3d9241539e9ded4d0e4da951970 /test/parallel/test-http2-compat-serverresponse-end.js
parent4f339b54e9cd8a2cb69b41d87832ad8ca3a6b5e2 (diff)
downloadandroid-node-v8-2da7d9b8207d9c35d199734da75fa2bb15f326b6.tar.gz
android-node-v8-2da7d9b8207d9c35d199734da75fa2bb15f326b6.tar.bz2
android-node-v8-2da7d9b8207d9c35d199734da75fa2bb15f326b6.zip
http2: near full http1 compatibility, add tests
Extensive re-work of http1 compatibility layer based on tests in express, on-finished and finalhandler. Fix handling of HEAD method to match http1. Adjust write, end, etc. to call writeHead as in http1 and as expected by user-land modules. Add socket proxy that instead uses the Http2Stream for the vast majority of socket interactions. Add and change tests to closer represent http1 behaviour. Refs: https://github.com/nodejs/node/pull/15633 Refs: https://github.com/expressjs/express/tree/master/test Refs: https://github.com/jshttp/on-finished/blob/master/test/test.js Refs: https://github.com/pillarjs/finalhandler/blob/master/test/test.js PR-URL: https://github.com/nodejs/node/pull/15702 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'test/parallel/test-http2-compat-serverresponse-end.js')
-rw-r--r--test/parallel/test-http2-compat-serverresponse-end.js191
1 files changed, 185 insertions, 6 deletions
diff --git a/test/parallel/test-http2-compat-serverresponse-end.js b/test/parallel/test-http2-compat-serverresponse-end.js
index 76cb692938..fafb3ea76d 100644
--- a/test/parallel/test-http2-compat-serverresponse-end.js
+++ b/test/parallel/test-http2-compat-serverresponse-end.js
@@ -1,6 +1,12 @@
'use strict';
-const { mustCall, mustNotCall, hasCrypto, skip } = require('../common');
+const {
+ mustCall,
+ mustNotCall,
+ hasCrypto,
+ platformTimeout,
+ skip
+} = require('../common');
if (!hasCrypto)
skip('missing crypto');
const { strictEqual } = require('assert');
@@ -18,15 +24,16 @@ const {
// It may be invoked repeatedly without throwing errors
// but callback will only be called once
const server = createServer(mustCall((request, response) => {
- strictEqual(response.closed, false);
response.end('end', 'utf8', mustCall(() => {
- strictEqual(response.closed, true);
response.end(mustNotCall());
process.nextTick(() => {
response.end(mustNotCall());
server.close();
});
}));
+ response.on('finish', mustCall(() => {
+ response.end(mustNotCall());
+ }));
response.end(mustNotCall());
}));
server.listen(0, mustCall(() => {
@@ -111,12 +118,77 @@ const {
}
{
- // Http2ServerResponse.end is not necessary on HEAD requests since the stream
- // is already closed. Headers, however, can still be sent to the client.
+ // Http2ServerResponse.end is necessary on HEAD requests in compat
+ // for http1 compatibility
const server = createServer(mustCall((request, response) => {
strictEqual(response.finished, true);
response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
- response.end(mustNotCall());
+ response.end('data', mustCall());
+ }));
+ server.listen(0, mustCall(() => {
+ const { port } = server.address();
+ const url = `http://localhost:${port}`;
+ const client = connect(url, mustCall(() => {
+ const headers = {
+ ':path': '/',
+ ':method': 'HEAD',
+ ':scheme': 'http',
+ ':authority': `localhost:${port}`
+ };
+ const request = client.request(headers);
+ request.on('response', mustCall((headers, flags) => {
+ strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
+ strictEqual(flags, 5); // the end of stream flag is set
+ strictEqual(headers.foo, 'bar');
+ }));
+ request.on('data', mustNotCall());
+ request.on('end', mustCall(() => {
+ client.destroy();
+ server.close();
+ }));
+ request.end();
+ request.resume();
+ }));
+ }));
+}
+
+{
+ // .end should trigger 'end' event on request if user did not attempt
+ // to read from the request
+ const server = createServer(mustCall((request, response) => {
+ request.on('end', mustCall());
+ response.end();
+ }));
+ server.listen(0, mustCall(() => {
+ const { port } = server.address();
+ const url = `http://localhost:${port}`;
+ const client = connect(url, mustCall(() => {
+ const headers = {
+ ':path': '/',
+ ':method': 'HEAD',
+ ':scheme': 'http',
+ ':authority': `localhost:${port}`
+ };
+ const request = client.request(headers);
+ request.on('data', mustNotCall());
+ request.on('end', mustCall(() => {
+ client.destroy();
+ server.close();
+ }));
+ request.end();
+ request.resume();
+ }));
+ }));
+}
+
+
+{
+ // Should be able to call .end with cb from stream 'streamClosed'
+ const server = createServer(mustCall((request, response) => {
+ response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
+ response.stream.on('streamClosed', mustCall(() => {
+ response.end(mustCall());
+ }));
}));
server.listen(0, mustCall(() => {
const { port } = server.address();
@@ -144,3 +216,110 @@ const {
}));
}));
}
+
+{
+ // Should be able to respond to HEAD request after timeout
+ const server = createServer(mustCall((request, response) => {
+ setTimeout(mustCall(() => {
+ response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
+ response.end('data', mustCall());
+ }), platformTimeout(10));
+ }));
+ server.listen(0, mustCall(() => {
+ const { port } = server.address();
+ const url = `http://localhost:${port}`;
+ const client = connect(url, mustCall(() => {
+ const headers = {
+ ':path': '/',
+ ':method': 'HEAD',
+ ':scheme': 'http',
+ ':authority': `localhost:${port}`
+ };
+ const request = client.request(headers);
+ request.on('response', mustCall((headers, flags) => {
+ strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
+ strictEqual(flags, 5); // the end of stream flag is set
+ strictEqual(headers.foo, 'bar');
+ }));
+ request.on('data', mustNotCall());
+ request.on('end', mustCall(() => {
+ client.destroy();
+ server.close();
+ }));
+ request.end();
+ request.resume();
+ }));
+ }));
+}
+
+{
+ // finish should only trigger after 'end' is called
+ const server = createServer(mustCall((request, response) => {
+ let finished = false;
+ response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
+ response.on('finish', mustCall(() => {
+ finished = false;
+ }));
+ response.end('data', mustCall(() => {
+ strictEqual(finished, false);
+ response.end('data', mustNotCall());
+ }));
+ }));
+ server.listen(0, mustCall(() => {
+ const { port } = server.address();
+ const url = `http://localhost:${port}`;
+ const client = connect(url, mustCall(() => {
+ const headers = {
+ ':path': '/',
+ ':method': 'HEAD',
+ ':scheme': 'http',
+ ':authority': `localhost:${port}`
+ };
+ const request = client.request(headers);
+ request.on('response', mustCall((headers, flags) => {
+ strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
+ strictEqual(flags, 5); // the end of stream flag is set
+ strictEqual(headers.foo, 'bar');
+ }));
+ request.on('data', mustNotCall());
+ request.on('end', mustCall(() => {
+ client.destroy();
+ server.close();
+ }));
+ request.end();
+ request.resume();
+ }));
+ }));
+}
+
+{
+ // Should be able to respond to HEAD with just .end
+ const server = createServer(mustCall((request, response) => {
+ response.end('data', mustCall());
+ response.end(mustNotCall());
+ }));
+ server.listen(0, mustCall(() => {
+ const { port } = server.address();
+ const url = `http://localhost:${port}`;
+ const client = connect(url, mustCall(() => {
+ const headers = {
+ ':path': '/',
+ ':method': 'HEAD',
+ ':scheme': 'http',
+ ':authority': `localhost:${port}`
+ };
+ const request = client.request(headers);
+ request.on('response', mustCall((headers, flags) => {
+ strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
+ strictEqual(flags, 5); // the end of stream flag is set
+ }));
+ request.on('data', mustNotCall());
+ request.on('end', mustCall(() => {
+ client.destroy();
+ server.close();
+ }));
+ request.end();
+ request.resume();
+ }));
+ }));
+}