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 assert.strictEqual(res.req, req); 53 54 if (req.id === 0) { 55 assert.strictEqual(req.method, 'GET'); 56 assert.strictEqual(url.parse(req.url).pathname, '/hello'); 57 assert.strictEqual(qs.parse(url.parse(req.url).query).hello, 'world'); 58 assert.strictEqual(qs.parse(url.parse(req.url).query).foo, 'b==ar'); 59 } 60 61 if (req.id === 1) { 62 assert.strictEqual(req.method, 'POST'); 63 assert.strictEqual(url.parse(req.url).pathname, '/quit'); 64 } 65 66 if (req.id === 2) { 67 assert.strictEqual(req.headers['x-x'], 'foo'); 68 } 69 70 if (req.id === 3) { 71 assert.strictEqual(req.headers['x-x'], 'bar'); 72 this.close(); 73 } 74 75 setTimeout(function() { 76 res.writeHead(200, { 'Content-Type': 'text/plain' }); 77 res.write(url.parse(req.url).pathname); 78 res.end(); 79 }, 1); 80 81}); 82server.listen(0); 83 84server.httpAllowHalfOpen = true; 85 86server.on('listening', function() { 87 const c = net.createConnection(this.address().port); 88 89 c.setEncoding('utf8'); 90 91 c.on('connect', function() { 92 c.write('GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n\r\n'); 93 requests_sent += 1; 94 }); 95 96 c.on('data', function(chunk) { 97 server_response += chunk; 98 99 if (requests_sent === 1) { 100 c.write('POST /quit HTTP/1.1\r\n\r\n'); 101 requests_sent += 1; 102 } 103 104 if (requests_sent === 2) { 105 c.write('GET / HTTP/1.1\r\nX-X: foo\r\n\r\n' + 106 'GET / HTTP/1.1\r\nX-X: bar\r\n\r\n'); 107 // Note: we are making the connection half-closed here 108 // before we've gotten the response from the server. This 109 // is a pretty bad thing to do and not really supported 110 // by many http servers. Node supports it optionally if 111 // you set server.httpAllowHalfOpen=true, which we've done 112 // above. 113 c.end(); 114 assert.strictEqual(c.readyState, 'readOnly'); 115 requests_sent += 2; 116 } 117 118 }); 119 120 c.on('end', function() { 121 client_got_eof = true; 122 }); 123 124 c.on('close', function() { 125 assert.strictEqual(c.readyState, 'closed'); 126 }); 127}); 128 129process.on('exit', function() { 130 assert.strictEqual(request_number, 4); 131 assert.strictEqual(requests_sent, 4); 132 133 const hello = new RegExp('/hello'); 134 assert.match(server_response, hello); 135 136 const quit = new RegExp('/quit'); 137 assert.match(server_response, quit); 138 139 assert.strictEqual(client_got_eof, true); 140}); 141