11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci'use strict';
231cb0ef41Sopenharmony_ciconst common = require('../common');
241cb0ef41Sopenharmony_ciconst assert = require('assert');
251cb0ef41Sopenharmony_ciconst http = require('http');
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci// Simple test of Node's HTTP Client mutable headers
281cb0ef41Sopenharmony_ci// OutgoingMessage.prototype.setHeader(name, value)
291cb0ef41Sopenharmony_ci// OutgoingMessage.prototype.getHeader(name)
301cb0ef41Sopenharmony_ci// OutgoingMessage.prototype.removeHeader(name, value)
311cb0ef41Sopenharmony_ci// ServerResponse.prototype.statusCode
321cb0ef41Sopenharmony_ci// <ClientRequest>.method
331cb0ef41Sopenharmony_ci// <ClientRequest>.path
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cilet test = 'headers';
361cb0ef41Sopenharmony_ciconst content = 'hello world\n';
371cb0ef41Sopenharmony_ciconst cookies = [
381cb0ef41Sopenharmony_ci  'session_token=; path=/; expires=Sun, 15-Sep-2030 13:48:52 GMT',
391cb0ef41Sopenharmony_ci  'prefers_open_id=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT',
401cb0ef41Sopenharmony_ci];
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ciconst s = http.createServer(common.mustCall((req, res) => {
431cb0ef41Sopenharmony_ci  switch (test) {
441cb0ef41Sopenharmony_ci    case 'headers': {
451cb0ef41Sopenharmony_ci      // Check that header-related functions work before setting any headers
461cb0ef41Sopenharmony_ci      const headers = res.getHeaders();
471cb0ef41Sopenharmony_ci      const exoticObj = Object.create(null);
481cb0ef41Sopenharmony_ci      assert.deepStrictEqual(headers, exoticObj);
491cb0ef41Sopenharmony_ci      assert.deepStrictEqual(res.getHeaderNames(), []);
501cb0ef41Sopenharmony_ci      assert.deepStrictEqual(res.getRawHeaderNames(), []);
511cb0ef41Sopenharmony_ci      assert.strictEqual(res.hasHeader('Connection'), false);
521cb0ef41Sopenharmony_ci      assert.strictEqual(res.getHeader('Connection'), undefined);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci      assert.throws(
551cb0ef41Sopenharmony_ci        () => res.setHeader(),
561cb0ef41Sopenharmony_ci        {
571cb0ef41Sopenharmony_ci          code: 'ERR_INVALID_HTTP_TOKEN',
581cb0ef41Sopenharmony_ci          name: 'TypeError',
591cb0ef41Sopenharmony_ci          message: 'Header name must be a valid HTTP token ["undefined"]'
601cb0ef41Sopenharmony_ci        }
611cb0ef41Sopenharmony_ci      );
621cb0ef41Sopenharmony_ci      assert.throws(
631cb0ef41Sopenharmony_ci        () => res.setHeader('someHeader'),
641cb0ef41Sopenharmony_ci        {
651cb0ef41Sopenharmony_ci          code: 'ERR_HTTP_INVALID_HEADER_VALUE',
661cb0ef41Sopenharmony_ci          name: 'TypeError',
671cb0ef41Sopenharmony_ci          message: 'Invalid value "undefined" for header "someHeader"'
681cb0ef41Sopenharmony_ci        }
691cb0ef41Sopenharmony_ci      );
701cb0ef41Sopenharmony_ci      assert.throws(
711cb0ef41Sopenharmony_ci        () => res.getHeader(),
721cb0ef41Sopenharmony_ci        {
731cb0ef41Sopenharmony_ci          code: 'ERR_INVALID_ARG_TYPE',
741cb0ef41Sopenharmony_ci          name: 'TypeError',
751cb0ef41Sopenharmony_ci          message: 'The "name" argument must be of type string. ' +
761cb0ef41Sopenharmony_ci                   'Received undefined'
771cb0ef41Sopenharmony_ci        }
781cb0ef41Sopenharmony_ci      );
791cb0ef41Sopenharmony_ci      assert.throws(
801cb0ef41Sopenharmony_ci        () => res.removeHeader(),
811cb0ef41Sopenharmony_ci        {
821cb0ef41Sopenharmony_ci          code: 'ERR_INVALID_ARG_TYPE',
831cb0ef41Sopenharmony_ci          name: 'TypeError',
841cb0ef41Sopenharmony_ci          message: 'The "name" argument must be of type string. ' +
851cb0ef41Sopenharmony_ci                   'Received undefined'
861cb0ef41Sopenharmony_ci        }
871cb0ef41Sopenharmony_ci      );
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci      const arrayValues = [1, 2, 3];
901cb0ef41Sopenharmony_ci      res.setHeader('x-test-header', 'testing');
911cb0ef41Sopenharmony_ci      res.setHeader('X-TEST-HEADER2', 'testing');
921cb0ef41Sopenharmony_ci      res.setHeader('set-cookie', cookies);
931cb0ef41Sopenharmony_ci      res.setHeader('x-test-array-header', arrayValues);
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci      assert.strictEqual(res.getHeader('x-test-header'), 'testing');
961cb0ef41Sopenharmony_ci      assert.strictEqual(res.getHeader('x-test-header2'), 'testing');
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci      const headersCopy = res.getHeaders();
991cb0ef41Sopenharmony_ci      const expected = {
1001cb0ef41Sopenharmony_ci        'x-test-header': 'testing',
1011cb0ef41Sopenharmony_ci        'x-test-header2': 'testing',
1021cb0ef41Sopenharmony_ci        'set-cookie': cookies,
1031cb0ef41Sopenharmony_ci        'x-test-array-header': arrayValues
1041cb0ef41Sopenharmony_ci      };
1051cb0ef41Sopenharmony_ci      Object.setPrototypeOf(expected, null);
1061cb0ef41Sopenharmony_ci      assert.deepStrictEqual(headersCopy, expected);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci      assert.deepStrictEqual(res.getHeaderNames(),
1091cb0ef41Sopenharmony_ci                             ['x-test-header', 'x-test-header2',
1101cb0ef41Sopenharmony_ci                              'set-cookie', 'x-test-array-header']);
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci      assert.deepStrictEqual(res.getRawHeaderNames(),
1131cb0ef41Sopenharmony_ci                             ['x-test-header', 'X-TEST-HEADER2',
1141cb0ef41Sopenharmony_ci                              'set-cookie', 'x-test-array-header']);
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci      assert.strictEqual(res.hasHeader('x-test-header2'), true);
1171cb0ef41Sopenharmony_ci      assert.strictEqual(res.hasHeader('X-TEST-HEADER2'), true);
1181cb0ef41Sopenharmony_ci      assert.strictEqual(res.hasHeader('X-Test-Header2'), true);
1191cb0ef41Sopenharmony_ci      [
1201cb0ef41Sopenharmony_ci        undefined,
1211cb0ef41Sopenharmony_ci        null,
1221cb0ef41Sopenharmony_ci        true,
1231cb0ef41Sopenharmony_ci        {},
1241cb0ef41Sopenharmony_ci        { toString: () => 'X-TEST-HEADER2' },
1251cb0ef41Sopenharmony_ci        () => { },
1261cb0ef41Sopenharmony_ci      ].forEach((val) => {
1271cb0ef41Sopenharmony_ci        assert.throws(
1281cb0ef41Sopenharmony_ci          () => res.hasHeader(val),
1291cb0ef41Sopenharmony_ci          {
1301cb0ef41Sopenharmony_ci            code: 'ERR_INVALID_ARG_TYPE',
1311cb0ef41Sopenharmony_ci            name: 'TypeError',
1321cb0ef41Sopenharmony_ci            message: 'The "name" argument must be of type string.' +
1331cb0ef41Sopenharmony_ci                     common.invalidArgTypeHelper(val)
1341cb0ef41Sopenharmony_ci          }
1351cb0ef41Sopenharmony_ci        );
1361cb0ef41Sopenharmony_ci      });
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci      res.removeHeader('x-test-header2');
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci      assert.strictEqual(res.hasHeader('x-test-header2'), false);
1411cb0ef41Sopenharmony_ci      assert.strictEqual(res.hasHeader('X-TEST-HEADER2'), false);
1421cb0ef41Sopenharmony_ci      assert.strictEqual(res.hasHeader('X-Test-Header2'), false);
1431cb0ef41Sopenharmony_ci      break;
1441cb0ef41Sopenharmony_ci    }
1451cb0ef41Sopenharmony_ci    case 'contentLength':
1461cb0ef41Sopenharmony_ci      res.setHeader('content-length', content.length);
1471cb0ef41Sopenharmony_ci      assert.strictEqual(res.getHeader('Content-Length'), content.length);
1481cb0ef41Sopenharmony_ci      break;
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci    case 'transferEncoding':
1511cb0ef41Sopenharmony_ci      res.setHeader('transfer-encoding', 'chunked');
1521cb0ef41Sopenharmony_ci      assert.strictEqual(res.getHeader('Transfer-Encoding'), 'chunked');
1531cb0ef41Sopenharmony_ci      break;
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci    case 'writeHead':
1561cb0ef41Sopenharmony_ci      res.statusCode = 404;
1571cb0ef41Sopenharmony_ci      res.setHeader('x-foo', 'keyboard cat');
1581cb0ef41Sopenharmony_ci      res.writeHead(200, { 'x-foo': 'bar', 'x-bar': 'baz' });
1591cb0ef41Sopenharmony_ci      break;
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci    default:
1621cb0ef41Sopenharmony_ci      assert.fail('Unknown test');
1631cb0ef41Sopenharmony_ci  }
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  res.statusCode = 201;
1661cb0ef41Sopenharmony_ci  res.end(content);
1671cb0ef41Sopenharmony_ci}, 4));
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_cis.listen(0, nextTest);
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_cifunction nextTest() {
1731cb0ef41Sopenharmony_ci  if (test === 'end') {
1741cb0ef41Sopenharmony_ci    return s.close();
1751cb0ef41Sopenharmony_ci  }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  let bufferedResponse = '';
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  const req = http.get({
1801cb0ef41Sopenharmony_ci    port: s.address().port,
1811cb0ef41Sopenharmony_ci    headers: { 'X-foo': 'bar' }
1821cb0ef41Sopenharmony_ci  }, common.mustCall((response) => {
1831cb0ef41Sopenharmony_ci    switch (test) {
1841cb0ef41Sopenharmony_ci      case 'headers':
1851cb0ef41Sopenharmony_ci        assert.strictEqual(response.statusCode, 201);
1861cb0ef41Sopenharmony_ci        assert.strictEqual(response.headers['x-test-header'], 'testing');
1871cb0ef41Sopenharmony_ci        assert.strictEqual(response.headers['x-test-array-header'],
1881cb0ef41Sopenharmony_ci                           [1, 2, 3].join(', '));
1891cb0ef41Sopenharmony_ci        assert.deepStrictEqual(cookies, response.headers['set-cookie']);
1901cb0ef41Sopenharmony_ci        assert.strictEqual(response.headers['x-test-header2'], undefined);
1911cb0ef41Sopenharmony_ci        test = 'contentLength';
1921cb0ef41Sopenharmony_ci        break;
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci      case 'contentLength':
1951cb0ef41Sopenharmony_ci        assert.strictEqual(+response.headers['content-length'], content.length);
1961cb0ef41Sopenharmony_ci        test = 'transferEncoding';
1971cb0ef41Sopenharmony_ci        break;
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci      case 'transferEncoding':
2001cb0ef41Sopenharmony_ci        assert.strictEqual(response.headers['transfer-encoding'], 'chunked');
2011cb0ef41Sopenharmony_ci        test = 'writeHead';
2021cb0ef41Sopenharmony_ci        break;
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci      case 'writeHead':
2051cb0ef41Sopenharmony_ci        assert.strictEqual(response.headers['x-foo'], 'bar');
2061cb0ef41Sopenharmony_ci        assert.strictEqual(response.headers['x-bar'], 'baz');
2071cb0ef41Sopenharmony_ci        assert.strictEqual(response.statusCode, 200);
2081cb0ef41Sopenharmony_ci        test = 'end';
2091cb0ef41Sopenharmony_ci        break;
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci      default:
2121cb0ef41Sopenharmony_ci        assert.fail('Unknown test');
2131cb0ef41Sopenharmony_ci    }
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci    response.setEncoding('utf8');
2161cb0ef41Sopenharmony_ci    response.on('data', (s) => {
2171cb0ef41Sopenharmony_ci      bufferedResponse += s;
2181cb0ef41Sopenharmony_ci    });
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci    response.on('end', common.mustCall(() => {
2211cb0ef41Sopenharmony_ci      assert.strictEqual(bufferedResponse, content);
2221cb0ef41Sopenharmony_ci      common.mustCall(nextTest)();
2231cb0ef41Sopenharmony_ci    }));
2241cb0ef41Sopenharmony_ci  }));
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  assert.deepStrictEqual(req.getHeaderNames(),
2271cb0ef41Sopenharmony_ci                         ['x-foo', 'host']);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  assert.deepStrictEqual(req.getRawHeaderNames(),
2301cb0ef41Sopenharmony_ci                         ['X-foo', 'Host']);
2311cb0ef41Sopenharmony_ci}
232