mirror of https://github.com/lukechilds/node.git
Browse Source
includes parsing improvements to ensure closer HTTP spec conformance PR-URL: https://github.com/nodejs/node-private/pull/26 Reviewed-By: Rod Vagg <r@va.gg> Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>process-exit-stdio-flushing
James M Snell
9 years ago
12 changed files with 409 additions and 18 deletions
@ -0,0 +1,28 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
const http = require('http'); |
||||
|
const net = require('net'); |
||||
|
const assert = require('assert'); |
||||
|
|
||||
|
const reqstr = 'HTTP/1.1 200 OK\r\n' + |
||||
|
'Content-Length: 1\r\n' + |
||||
|
'Transfer-Encoding: chunked\r\n\r\n'; |
||||
|
|
||||
|
const server = net.createServer((socket) => { |
||||
|
socket.write(reqstr); |
||||
|
}); |
||||
|
|
||||
|
server.listen(common.PORT, () => { |
||||
|
// The callback should not be called because the server is sending
|
||||
|
// both a Content-Length header and a Transfer-Encoding: chunked
|
||||
|
// header, which is a violation of the HTTP spec.
|
||||
|
const req = http.get({port:common.PORT}, (res) => { |
||||
|
assert.fail(null, null, 'callback should not be called'); |
||||
|
}); |
||||
|
req.on('error', common.mustCall((err) => { |
||||
|
assert(/^Parse Error/.test(err.message)); |
||||
|
assert.equal(err.code, 'HPE_UNEXPECTED_CONTENT_LENGTH'); |
||||
|
server.close(); |
||||
|
})); |
||||
|
}); |
@ -0,0 +1,27 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
const http = require('http'); |
||||
|
const net = require('net'); |
||||
|
const assert = require('assert'); |
||||
|
|
||||
|
const reqstr = 'HTTP/1.1 200 OK\r\n' + |
||||
|
'Foo: Bar\r' + |
||||
|
'Content-Length: 1\r\n\r\n'; |
||||
|
|
||||
|
const server = net.createServer((socket) => { |
||||
|
socket.write(reqstr); |
||||
|
}); |
||||
|
|
||||
|
server.listen(common.PORT, () => { |
||||
|
// The callback should not be called because the server is sending a
|
||||
|
// header field that ends only in \r with no following \n
|
||||
|
const req = http.get({port:common.PORT}, (res) => { |
||||
|
assert.fail(null, null, 'callback should not be called'); |
||||
|
}); |
||||
|
req.on('error', common.mustCall((err) => { |
||||
|
assert(/^Parse Error/.test(err.message)); |
||||
|
assert.equal(err.code, 'HPE_LF_EXPECTED'); |
||||
|
server.close(); |
||||
|
})); |
||||
|
}); |
@ -0,0 +1,33 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
const http = require('http'); |
||||
|
const assert = require('assert'); |
||||
|
|
||||
|
// The callback should never be invoked because the server
|
||||
|
// should respond with a 400 Client Error when a double
|
||||
|
// Content-Length header is received.
|
||||
|
const server = http.createServer((req, res) => { |
||||
|
assert(false, 'callback should not have been invoked'); |
||||
|
res.end(); |
||||
|
}); |
||||
|
server.on('clientError', common.mustCall((err, socket) => { |
||||
|
assert(/^Parse Error/.test(err.message)); |
||||
|
assert.equal(err.code, 'HPE_UNEXPECTED_CONTENT_LENGTH'); |
||||
|
socket.destroy(); |
||||
|
})); |
||||
|
|
||||
|
server.listen(common.PORT, () => { |
||||
|
const req = http.get({ |
||||
|
port: common.PORT, |
||||
|
// Send two content-length header values.
|
||||
|
headers: {'Content-Length': [1, 2]}}, |
||||
|
(res) => { |
||||
|
assert.fail(null, null, 'an error should have occurred'); |
||||
|
server.close(); |
||||
|
} |
||||
|
); |
||||
|
req.on('error', common.mustCall(() => { |
||||
|
server.close(); |
||||
|
})); |
||||
|
}); |
@ -0,0 +1,52 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
const http = require('http'); |
||||
|
const assert = require('assert'); |
||||
|
|
||||
|
const MAX_COUNT = 2; |
||||
|
|
||||
|
const server = http.createServer((req, res) => { |
||||
|
const num = req.headers['x-num']; |
||||
|
// TODO(@jasnell) At some point this should be refactored as the API
|
||||
|
// should not be allowing users to set multiple content-length values
|
||||
|
// in the first place.
|
||||
|
switch (num) { |
||||
|
case '1': |
||||
|
res.setHeader('content-length', [2, 1]); |
||||
|
break; |
||||
|
case '2': |
||||
|
res.writeHead(200, {'content-length': [1, 2]}); |
||||
|
break; |
||||
|
default: |
||||
|
assert.fail(null, null, 'should never get here'); |
||||
|
} |
||||
|
res.end('ok'); |
||||
|
}); |
||||
|
|
||||
|
var count = 0; |
||||
|
|
||||
|
server.listen(common.PORT, common.mustCall(() => { |
||||
|
for (let n = 1; n <= MAX_COUNT ; n++) { |
||||
|
// This runs twice, the first time, the server will use
|
||||
|
// setHeader, the second time it uses writeHead. In either
|
||||
|
// case, the error handler must be called because the client
|
||||
|
// is not allowed to accept multiple content-length headers.
|
||||
|
http.get( |
||||
|
{port:common.PORT, headers:{'x-num': n}}, |
||||
|
(res) => { |
||||
|
assert(false, 'client allowed multiple content-length headers.'); |
||||
|
} |
||||
|
).on('error', common.mustCall((err) => { |
||||
|
assert(/^Parse Error/.test(err.message)); |
||||
|
assert.equal(err.code, 'HPE_UNEXPECTED_CONTENT_LENGTH'); |
||||
|
count++; |
||||
|
if (count === MAX_COUNT) |
||||
|
server.close(); |
||||
|
})); |
||||
|
} |
||||
|
})); |
||||
|
|
||||
|
process.on('exit', () => { |
||||
|
assert.equal(count, MAX_COUNT); |
||||
|
}); |
@ -0,0 +1,31 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
const http = require('http'); |
||||
|
const net = require('net'); |
||||
|
const assert = require('assert'); |
||||
|
|
||||
|
const reqstr = 'POST / HTTP/1.1\r\n' + |
||||
|
'Content-Length: 1\r\n' + |
||||
|
'Transfer-Encoding: chunked\r\n\r\n'; |
||||
|
|
||||
|
const server = http.createServer((req, res) => { |
||||
|
assert.fail(null, null, 'callback should not be invoked'); |
||||
|
}); |
||||
|
server.on('clientError', common.mustCall((err) => { |
||||
|
assert(/^Parse Error/.test(err.message)); |
||||
|
assert.equal(err.code, 'HPE_UNEXPECTED_CONTENT_LENGTH'); |
||||
|
server.close(); |
||||
|
})); |
||||
|
server.listen(common.PORT, () => { |
||||
|
const client = net.connect({port: common.PORT}, () => { |
||||
|
client.write(reqstr); |
||||
|
client.end(); |
||||
|
}); |
||||
|
client.on('data', (data) => { |
||||
|
// Should not get to this point because the server should simply
|
||||
|
// close the connection without returning any data.
|
||||
|
assert.fail(null, null, 'no data should be returned by the server'); |
||||
|
}); |
||||
|
client.on('end', common.mustCall(() => {})); |
||||
|
}); |
@ -0,0 +1,33 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
const net = require('net'); |
||||
|
const http = require('http'); |
||||
|
const assert = require('assert'); |
||||
|
|
||||
|
const str = 'GET / HTTP/1.1\r\n' + |
||||
|
'Dummy: Header\r' + |
||||
|
'Content-Length: 1\r\n' + |
||||
|
'\r\n'; |
||||
|
|
||||
|
|
||||
|
const server = http.createServer((req, res) => { |
||||
|
assert.fail(null, null, 'this should not be called'); |
||||
|
}); |
||||
|
server.on('clientError', common.mustCall((err) => { |
||||
|
assert(/^Parse Error/.test(err.message)); |
||||
|
assert.equal(err.code, 'HPE_LF_EXPECTED'); |
||||
|
server.close(); |
||||
|
})); |
||||
|
server.listen(common.PORT, () => { |
||||
|
const client = net.connect({port:common.PORT}, () => { |
||||
|
client.on('data', (chunk) => { |
||||
|
assert.fail(null, null, 'this should not be called'); |
||||
|
}); |
||||
|
client.on('end', common.mustCall(() => { |
||||
|
server.close(); |
||||
|
})); |
||||
|
client.write(str); |
||||
|
client.end(); |
||||
|
}); |
||||
|
}); |
Loading…
Reference in new issue