Skip to content

Instantly share code, notes, and snippets.

@FooBarWidget
Last active December 22, 2015 20:19
Show Gist options
  • Save FooBarWidget/6525478 to your computer and use it in GitHub Desktop.
Save FooBarWidget/6525478 to your computer and use it in GitHub Desktop.
const HTTP_HEADERS_WITHOUT_PREFIX = {
'CONTENT_LENGTH': true,
'CONTENT_TYPE': true
};
function cgiKeyToHttpHeader(key) {
if (HTTP_HEADERS_WITHOUT_PREFIX[key]) {
return key.toLowerCase().replace(/_/g, '-');
} else if (key.match(/^HTTP_/)) {
return key.replace(/^HTTP_/, '').toLowerCase().replace(/_/g, '-');
} else {
return undefined;
}
}
function setHttpHeaders(httpHeaders, cgiHeaders) {
for (var i = 0; i < cgiHeaders.keys.length; i++) {
var key = cgiHeaders.keys[i];
var httpHeader = cgiKeyToHttpHeader(key);
if (httpHeader !== undefined) {
httpHeaders[httpHeader] = cgiHeaders[key];
}
}
if (cgiHeaders['HTTPS']) {
httpHeaders['x-forwarded-proto'] = 'https';
}
if (!httpHeaders['x-forwarded-for']) {
httpHeaders['x-forwarded-for'] = cgiHeaders['REMOTE_ADDR'];
}
}
function inferHttpVersion(protocolDescription) {
var match = protocolDescription.match(/^HTTP\/(.+)/);
if (match) {
return match[1];
}
}
function mayHaveRequestBody(headers) {
return headers['REQUEST_METHOD'] != 'GET' || headers['HTTP_UPGRADE'];
}
function createIncomingMessage(headers, socket) {
var message = new http.IncomingMessage(socket);
setHttpHeaders(message.headers, headers);
message.cgiHeaders = headers;
message.httpVersion = inferHttpVersion(headers['SERVER_PROTOCOL']);
message.method = headers['REQUEST_METHOD'];
message.url = headers['REQUEST_URI'];
message.connection.remoteAddress = headers['REMOTE_ADDR'];
message.connection.remotePort = parseInt(headers['REMOTE_PORT']);
function onSocketData(chunk) {
message.emit('data', chunk);
}
function onSocketEnd() {
message.emit('end');
}
socket.on('drain', function() {
message.emit('drain');
});
socket.on('timeout', function() {
message.emit('timeout');
});
/* Node's HTTP parser simulates an 'end' event if it determines that
* the request should not have a request body. Currently (Node 0.10.18),
* it thinks GET requests without an Upgrade header should not have a
* request body, even though technically such GET requests are allowed
* to have a request body. For compatibility reasons we implement the
* same behavior as Node's HTTP parser.
*/
if (mayHaveRequestBody(headers)) {
socket.on('data', onSocketData);
socket.on('end', onSocketEnd);
} else {
process.nextTick(onSocketEnd);
}
return message;
}
function createServerResponse(req) {
var res = new http.ServerResponse(req);
res.assignSocket(req.socket);
res.shouldKeepAlive = false;
res.once('finish', function() {
req.socket.destroySoon();
});
return res;
}
PhusionPassenger.on('request', function(headers, socket) {
var req = createIncomingMessage(headers, socket);
var res = createServerResponse(req);
res.writeHead(200, {'Content-Type': 'text/plain', 'Foo': 'bar'});
res.write('hello world');
res.end();
});
@FooBarWidget
Copy link
Author

I've fixed both problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment