1'use strict';
2
3const common = require('../common');
4if (!common.hasCrypto)
5  common.skip('missing crypto');
6const assert = require('assert');
7const h2 = require('http2');
8
9const server = h2.createServer();
10
11// We use the lower-level API here
12server.on('stream', common.mustCall(onStream));
13
14const status101regex =
15  /^HTTP status code 101 \(Switching Protocols\) is forbidden in HTTP\/2$/;
16const afterRespondregex =
17  /^Cannot specify additional headers after response initiated$/;
18
19function onStream(stream, headers, flags) {
20
21  assert.throws(() => stream.additionalHeaders({ ':status': 201 }),
22                {
23                  code: 'ERR_HTTP2_INVALID_INFO_STATUS',
24                  name: 'RangeError',
25                  message: /^Invalid informational status code: 201$/
26                });
27
28  assert.throws(() => stream.additionalHeaders({ ':status': 101 }),
29                {
30                  code: 'ERR_HTTP2_STATUS_101',
31                  name: 'Error',
32                  message: status101regex
33                });
34
35  assert.throws(
36    () => stream.additionalHeaders({ ':method': 'POST' }),
37    {
38      code: 'ERR_HTTP2_INVALID_PSEUDOHEADER',
39      name: 'TypeError',
40      message: '":method" is an invalid pseudoheader or is used incorrectly'
41    }
42  );
43
44  // Can send more than one
45  stream.additionalHeaders({ ':status': 100 });
46  stream.additionalHeaders({ ':status': 100 });
47
48  stream.respond({
49    'content-type': 'text/html',
50    ':status': 200
51  });
52
53  assert.throws(() => stream.additionalHeaders({ abc: 123 }),
54                {
55                  code: 'ERR_HTTP2_HEADERS_AFTER_RESPOND',
56                  name: 'Error',
57                  message: afterRespondregex
58                });
59
60  stream.end('hello world');
61}
62
63server.listen(0);
64
65server.on('listening', common.mustCall(() => {
66
67  const client = h2.connect(`http://localhost:${server.address().port}`);
68
69  const req = client.request({ ':path': '/' });
70
71  // The additionalHeaders method does not exist on client stream
72  assert.strictEqual(req.additionalHeaders, undefined);
73
74  // Additional informational headers
75  req.on('headers', common.mustCall((headers) => {
76    assert.notStrictEqual(headers, undefined);
77    assert.strictEqual(headers[':status'], 100);
78  }, 2));
79
80  // Response headers
81  req.on('response', common.mustCall((headers) => {
82    assert.notStrictEqual(headers, undefined);
83    assert.strictEqual(headers[':status'], 200);
84    assert.strictEqual(headers['content-type'], 'text/html');
85  }));
86
87  req.resume();
88
89  req.on('end', common.mustCall(() => {
90    server.close();
91    client.close();
92  }));
93  req.end();
94
95}));
96