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_cirequire('../common');
241cb0ef41Sopenharmony_ciconst assert = require('assert');
251cb0ef41Sopenharmony_ciconst net = require('net');
261cb0ef41Sopenharmony_ciconst http = require('http');
271cb0ef41Sopenharmony_ciconst url = require('url');
281cb0ef41Sopenharmony_ciconst qs = require('querystring');
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci// TODO: documentation does not allow Array as an option, so testing that
311cb0ef41Sopenharmony_ci// should fail, but currently http.Server does not typecheck further than
321cb0ef41Sopenharmony_ci// if `option` is `typeof object` - so we don't test that here right now
331cb0ef41Sopenharmony_ciconst invalid_options = [ 'foo', 42, true ];
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciinvalid_options.forEach((option) => {
361cb0ef41Sopenharmony_ci  assert.throws(() => {
371cb0ef41Sopenharmony_ci    new http.Server(option);
381cb0ef41Sopenharmony_ci  }, {
391cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
401cb0ef41Sopenharmony_ci  });
411cb0ef41Sopenharmony_ci});
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cilet request_number = 0;
441cb0ef41Sopenharmony_cilet requests_sent = 0;
451cb0ef41Sopenharmony_cilet server_response = '';
461cb0ef41Sopenharmony_cilet client_got_eof = false;
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciconst server = http.createServer(function(req, res) {
491cb0ef41Sopenharmony_ci  res.id = request_number;
501cb0ef41Sopenharmony_ci  req.id = request_number++;
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  assert.strictEqual(res.req, req);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  if (req.id === 0) {
551cb0ef41Sopenharmony_ci    assert.strictEqual(req.method, 'GET');
561cb0ef41Sopenharmony_ci    assert.strictEqual(url.parse(req.url).pathname, '/hello');
571cb0ef41Sopenharmony_ci    assert.strictEqual(qs.parse(url.parse(req.url).query).hello, 'world');
581cb0ef41Sopenharmony_ci    assert.strictEqual(qs.parse(url.parse(req.url).query).foo, 'b==ar');
591cb0ef41Sopenharmony_ci  }
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  if (req.id === 1) {
621cb0ef41Sopenharmony_ci    assert.strictEqual(req.method, 'POST');
631cb0ef41Sopenharmony_ci    assert.strictEqual(url.parse(req.url).pathname, '/quit');
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  if (req.id === 2) {
671cb0ef41Sopenharmony_ci    assert.strictEqual(req.headers['x-x'], 'foo');
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  if (req.id === 3) {
711cb0ef41Sopenharmony_ci    assert.strictEqual(req.headers['x-x'], 'bar');
721cb0ef41Sopenharmony_ci    this.close();
731cb0ef41Sopenharmony_ci  }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  setTimeout(function() {
761cb0ef41Sopenharmony_ci    res.writeHead(200, { 'Content-Type': 'text/plain' });
771cb0ef41Sopenharmony_ci    res.write(url.parse(req.url).pathname);
781cb0ef41Sopenharmony_ci    res.end();
791cb0ef41Sopenharmony_ci  }, 1);
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci});
821cb0ef41Sopenharmony_ciserver.listen(0);
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ciserver.httpAllowHalfOpen = true;
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ciserver.on('listening', function() {
871cb0ef41Sopenharmony_ci  const c = net.createConnection(this.address().port);
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  c.setEncoding('utf8');
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  c.on('connect', function() {
921cb0ef41Sopenharmony_ci    c.write('GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n\r\n');
931cb0ef41Sopenharmony_ci    requests_sent += 1;
941cb0ef41Sopenharmony_ci  });
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  c.on('data', function(chunk) {
971cb0ef41Sopenharmony_ci    server_response += chunk;
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci    if (requests_sent === 1) {
1001cb0ef41Sopenharmony_ci      c.write('POST /quit HTTP/1.1\r\n\r\n');
1011cb0ef41Sopenharmony_ci      requests_sent += 1;
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci    if (requests_sent === 2) {
1051cb0ef41Sopenharmony_ci      c.write('GET / HTTP/1.1\r\nX-X: foo\r\n\r\n' +
1061cb0ef41Sopenharmony_ci              'GET / HTTP/1.1\r\nX-X: bar\r\n\r\n');
1071cb0ef41Sopenharmony_ci      // Note: we are making the connection half-closed here
1081cb0ef41Sopenharmony_ci      // before we've gotten the response from the server. This
1091cb0ef41Sopenharmony_ci      // is a pretty bad thing to do and not really supported
1101cb0ef41Sopenharmony_ci      // by many http servers. Node supports it optionally if
1111cb0ef41Sopenharmony_ci      // you set server.httpAllowHalfOpen=true, which we've done
1121cb0ef41Sopenharmony_ci      // above.
1131cb0ef41Sopenharmony_ci      c.end();
1141cb0ef41Sopenharmony_ci      assert.strictEqual(c.readyState, 'readOnly');
1151cb0ef41Sopenharmony_ci      requests_sent += 2;
1161cb0ef41Sopenharmony_ci    }
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  });
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  c.on('end', function() {
1211cb0ef41Sopenharmony_ci    client_got_eof = true;
1221cb0ef41Sopenharmony_ci  });
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  c.on('close', function() {
1251cb0ef41Sopenharmony_ci    assert.strictEqual(c.readyState, 'closed');
1261cb0ef41Sopenharmony_ci  });
1271cb0ef41Sopenharmony_ci});
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ciprocess.on('exit', function() {
1301cb0ef41Sopenharmony_ci  assert.strictEqual(request_number, 4);
1311cb0ef41Sopenharmony_ci  assert.strictEqual(requests_sent, 4);
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  const hello = new RegExp('/hello');
1341cb0ef41Sopenharmony_ci  assert.match(server_response, hello);
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  const quit = new RegExp('/quit');
1371cb0ef41Sopenharmony_ci  assert.match(server_response, quit);
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  assert.strictEqual(client_got_eof, true);
1401cb0ef41Sopenharmony_ci});
141