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
9{
10  // Http2ServerRequest should have header helpers
11
12  const server = h2.createServer();
13  server.listen(0, common.mustCall(function() {
14    const port = server.address().port;
15    server.once('request', common.mustCall(function(request, response) {
16      const expected = {
17        ':path': '/foobar',
18        ':method': 'GET',
19        ':scheme': 'http',
20        ':authority': `localhost:${port}`,
21        'foo-bar': 'abc123'
22      };
23
24      assert.strictEqual(request.path, undefined);
25      assert.strictEqual(request.method, expected[':method']);
26      assert.strictEqual(request.scheme, expected[':scheme']);
27      assert.strictEqual(request.url, expected[':path']);
28      assert.strictEqual(request.authority, expected[':authority']);
29
30      const headers = request.headers;
31      for (const [name, value] of Object.entries(expected)) {
32        assert.strictEqual(headers[name], value);
33      }
34
35      const rawHeaders = request.rawHeaders;
36      for (const [name, value] of Object.entries(expected)) {
37        const position = rawHeaders.indexOf(name);
38        assert.notStrictEqual(position, -1);
39        assert.strictEqual(rawHeaders[position + 1], value);
40      }
41
42      request.url = '/one';
43      assert.strictEqual(request.url, '/one');
44
45      // Third-party plugins for packages like express use query params to
46      // change the request method
47      request.method = 'POST';
48      assert.strictEqual(request.method, 'POST');
49      assert.throws(
50        () => request.method = '   ',
51        {
52          code: 'ERR_INVALID_ARG_VALUE',
53          name: 'TypeError',
54          message: "The argument 'method' is invalid. Received '   '"
55        }
56      );
57      assert.throws(
58        () => request.method = true,
59        {
60          code: 'ERR_INVALID_ARG_TYPE',
61          name: 'TypeError',
62          message: 'The "method" argument must be of type string. ' +
63                  'Received type boolean (true)'
64        }
65      );
66
67      response.on('finish', common.mustCall(function() {
68        server.close();
69      }));
70      response.end();
71    }));
72
73    const url = `http://localhost:${port}`;
74    const client = h2.connect(url, common.mustCall(function() {
75      const headers = {
76        ':path': '/foobar',
77        ':method': 'GET',
78        ':scheme': 'http',
79        ':authority': `localhost:${port}`,
80        'foo-bar': 'abc123'
81      };
82      const request = client.request(headers);
83      request.on('end', common.mustCall(function() {
84        client.close();
85      }));
86      request.end();
87      request.resume();
88    }));
89  }));
90}
91
92{
93  // Http2ServerRequest should keep pseudo-headers order and after them,
94  // in the same order, the others headers
95
96  const server = h2.createServer();
97  server.listen(0, common.mustCall(function() {
98    const port = server.address().port;
99    server.once('request', common.mustCall(function(request, response) {
100      const expected = {
101        ':path': '/foobar',
102        ':method': 'GET',
103        ':scheme': 'http',
104        ':authority': `localhost:${port}`,
105        'foo1': 'abc1',
106        'foo2': 'abc2'
107      };
108
109      assert.strictEqual(request.path, undefined);
110      assert.strictEqual(request.method, expected[':method']);
111      assert.strictEqual(request.scheme, expected[':scheme']);
112      assert.strictEqual(request.url, expected[':path']);
113      assert.strictEqual(request.authority, expected[':authority']);
114
115      const headers = request.headers;
116      for (const [name, value] of Object.entries(expected)) {
117        assert.strictEqual(headers[name], value);
118      }
119
120      const rawHeaders = request.rawHeaders;
121      let expectedPosition = 0;
122      for (const [name, value] of Object.entries(expected)) {
123        const position = rawHeaders.indexOf(name);
124        assert.strictEqual(position / 2, expectedPosition);
125        assert.strictEqual(rawHeaders[position + 1], value);
126        expectedPosition++;
127      }
128
129      response.on('finish', common.mustCall(function() {
130        server.close();
131      }));
132      response.end();
133    }));
134
135    const url = `http://localhost:${port}`;
136    const client = h2.connect(url, common.mustCall(function() {
137      const headers = {
138        ':path': '/foobar',
139        ':method': 'GET',
140        'foo1': 'abc1',
141        ':scheme': 'http',
142        'foo2': 'abc2',
143        ':authority': `localhost:${port}`
144      };
145      const request = client.request(headers);
146      request.on('end', common.mustCall(function() {
147        client.close();
148      }));
149      request.end();
150      request.resume();
151    }));
152  }));
153}
154