11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciif (!common.hasCrypto)
51cb0ef41Sopenharmony_ci  common.skip('missing crypto');
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ciconst h2 = require('http2');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst server = h2.createServer();
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci// We use the lower-level API here
121cb0ef41Sopenharmony_ciserver.on('stream', common.mustCall(onStream));
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst status101regex =
151cb0ef41Sopenharmony_ci  /^HTTP status code 101 \(Switching Protocols\) is forbidden in HTTP\/2$/;
161cb0ef41Sopenharmony_ciconst afterRespondregex =
171cb0ef41Sopenharmony_ci  /^Cannot specify additional headers after response initiated$/;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cifunction onStream(stream, headers, flags) {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  assert.throws(() => stream.additionalHeaders({ ':status': 201 }),
221cb0ef41Sopenharmony_ci                {
231cb0ef41Sopenharmony_ci                  code: 'ERR_HTTP2_INVALID_INFO_STATUS',
241cb0ef41Sopenharmony_ci                  name: 'RangeError',
251cb0ef41Sopenharmony_ci                  message: /^Invalid informational status code: 201$/
261cb0ef41Sopenharmony_ci                });
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  assert.throws(() => stream.additionalHeaders({ ':status': 101 }),
291cb0ef41Sopenharmony_ci                {
301cb0ef41Sopenharmony_ci                  code: 'ERR_HTTP2_STATUS_101',
311cb0ef41Sopenharmony_ci                  name: 'Error',
321cb0ef41Sopenharmony_ci                  message: status101regex
331cb0ef41Sopenharmony_ci                });
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  assert.throws(
361cb0ef41Sopenharmony_ci    () => stream.additionalHeaders({ ':method': 'POST' }),
371cb0ef41Sopenharmony_ci    {
381cb0ef41Sopenharmony_ci      code: 'ERR_HTTP2_INVALID_PSEUDOHEADER',
391cb0ef41Sopenharmony_ci      name: 'TypeError',
401cb0ef41Sopenharmony_ci      message: '":method" is an invalid pseudoheader or is used incorrectly'
411cb0ef41Sopenharmony_ci    }
421cb0ef41Sopenharmony_ci  );
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  // Can send more than one
451cb0ef41Sopenharmony_ci  stream.additionalHeaders({ ':status': 100 });
461cb0ef41Sopenharmony_ci  stream.additionalHeaders({ ':status': 100 });
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  stream.respond({
491cb0ef41Sopenharmony_ci    'content-type': 'text/html',
501cb0ef41Sopenharmony_ci    ':status': 200
511cb0ef41Sopenharmony_ci  });
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  assert.throws(() => stream.additionalHeaders({ abc: 123 }),
541cb0ef41Sopenharmony_ci                {
551cb0ef41Sopenharmony_ci                  code: 'ERR_HTTP2_HEADERS_AFTER_RESPOND',
561cb0ef41Sopenharmony_ci                  name: 'Error',
571cb0ef41Sopenharmony_ci                  message: afterRespondregex
581cb0ef41Sopenharmony_ci                });
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  stream.end('hello world');
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciserver.listen(0);
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ciserver.on('listening', common.mustCall(() => {
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  const client = h2.connect(`http://localhost:${server.address().port}`);
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  const req = client.request({ ':path': '/' });
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  // The additionalHeaders method does not exist on client stream
721cb0ef41Sopenharmony_ci  assert.strictEqual(req.additionalHeaders, undefined);
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  // Additional informational headers
751cb0ef41Sopenharmony_ci  req.on('headers', common.mustCall((headers) => {
761cb0ef41Sopenharmony_ci    assert.notStrictEqual(headers, undefined);
771cb0ef41Sopenharmony_ci    assert.strictEqual(headers[':status'], 100);
781cb0ef41Sopenharmony_ci  }, 2));
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  // Response headers
811cb0ef41Sopenharmony_ci  req.on('response', common.mustCall((headers) => {
821cb0ef41Sopenharmony_ci    assert.notStrictEqual(headers, undefined);
831cb0ef41Sopenharmony_ci    assert.strictEqual(headers[':status'], 200);
841cb0ef41Sopenharmony_ci    assert.strictEqual(headers['content-type'], 'text/html');
851cb0ef41Sopenharmony_ci  }));
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  req.resume();
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  req.on('end', common.mustCall(() => {
901cb0ef41Sopenharmony_ci    server.close();
911cb0ef41Sopenharmony_ci    client.close();
921cb0ef41Sopenharmony_ci  }));
931cb0ef41Sopenharmony_ci  req.end();
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci}));
96