1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23require('../common'); 24const assert = require('assert'); 25const net = require('net'); 26const http = require('http'); 27const url = require('url'); 28const qs = require('querystring'); 29 30// TODO: documentation does not allow Array as an option, so testing that 31// should fail, but currently http.Server does not typecheck further than 32// if `option` is `typeof object` - so we don't test that here right now 33const invalid_options = [ 'foo', 42, true ]; 34 35invalid_options.forEach((option) => { 36 assert.throws(() => { 37 new http.Server(option); 38 }, { 39 code: 'ERR_INVALID_ARG_TYPE' 40 }); 41}); 42 43let request_number = 0; 44let requests_sent = 0; 45let server_response = ''; 46let client_got_eof = false; 47 48const server = http.createServer(function(req, res) { 49 res.id = request_number; 50 req.id = request_number++; 51 52 if (req.id === 0) { 53 assert.strictEqual(req.method, 'GET'); 54 assert.strictEqual(url.parse(req.url).pathname, '/hello'); 55 assert.strictEqual(qs.parse(url.parse(req.url).query).hello, 'world'); 56 assert.strictEqual(qs.parse(url.parse(req.url).query).foo, 'b==ar'); 57 } 58 59 if (req.id === 1) { 60 assert.strictEqual(req.method, 'POST'); 61 assert.strictEqual(url.parse(req.url).pathname, '/quit'); 62 } 63 64 if (req.id === 2) { 65 assert.strictEqual(req.headers['x-x'], 'foo'); 66 } 67 68 if (req.id === 3) { 69 assert.strictEqual(req.headers['x-x'], 'bar'); 70 this.close(); 71 } 72 73 setTimeout(function() { 74 res.writeHead(200, { 'Content-Type': 'text/plain' }); 75 res.write(url.parse(req.url).pathname); 76 res.end(); 77 }, 1); 78 79}); 80server.listen(0); 81 82server.httpAllowHalfOpen = true; 83 84server.on('listening', function() { 85 const c = net.createConnection(this.address().port); 86 87 c.setEncoding('utf8'); 88 89 c.on('connect', function() { 90 c.write('GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n\r\n'); 91 requests_sent += 1; 92 }); 93 94 c.on('data', function(chunk) { 95 server_response += chunk; 96 97 if (requests_sent === 1) { 98 c.write('POST /quit HTTP/1.1\r\n\r\n'); 99 requests_sent += 1; 100 } 101 102 if (requests_sent === 2) { 103 c.write('GET / HTTP/1.1\r\nX-X: foo\r\n\r\n' + 104 'GET / HTTP/1.1\r\nX-X: bar\r\n\r\n'); 105 // Note: we are making the connection half-closed here 106 // before we've gotten the response from the server. This 107 // is a pretty bad thing to do and not really supported 108 // by many http servers. Node supports it optionally if 109 // you set server.httpAllowHalfOpen=true, which we've done 110 // above. 111 c.end(); 112 assert.strictEqual(c.readyState, 'readOnly'); 113 requests_sent += 2; 114 } 115 116 }); 117 118 c.on('end', function() { 119 client_got_eof = true; 120 }); 121 122 c.on('close', function() { 123 assert.strictEqual(c.readyState, 'closed'); 124 }); 125}); 126 127process.on('exit', function() { 128 assert.strictEqual(request_number, 4); 129 assert.strictEqual(requests_sent, 4); 130 131 const hello = new RegExp('/hello'); 132 assert.ok(hello.test(server_response)); 133 134 const quit = new RegExp('/quit'); 135 assert.ok(quit.test(server_response)); 136 137 assert.strictEqual(client_got_eof, true); 138}); 139