Skip to content

Instantly share code, notes, and snippets.

@mscdex
Created November 10, 2014 06:03
Show Gist options
  • Save mscdex/d39b0db1ae3ed51fb771 to your computer and use it in GitHub Desktop.
Save mscdex/d39b0db1ae3ed51fb771 to your computer and use it in GitHub Desktop.
Http.Agent instance for response headers with latin1 characters
// First: `npm install agent-base streamsearch iconv-lite`
var http = require('http'),
net = require('net'),
EventEmitter = require('events').EventEmitter,
HTTPParser = process.binding('http_parser').HTTPParser,
parsers = http.parsers;
var agentBase = require('agent-base'),
StreamSearch = require('streamsearch'),
decodeStream = require('iconv-lite').decodeStream;
function freeParser(parser, req) {
if (parser) {
parser._headers = [];
parser.onIncoming = null;
if (parser.socket) {
parser.socket.onend = null;
parser.socket.ondata = null;
parser.socket.parser = null;
}
parser.socket = null;
parser.incoming = null;
parsers.free(parser);
parser = null;
}
}
function ISOAgent(req, opts, fn) {
var socket = net.connect(opts),
iconv = decodeStream('ISO-8859-1'),
ss = new StreamSearch('\r\n\r\n'),
parsing = true,
rawHeader = '',
oldOnData;
function fixHeaders(res) {
var parser = parsers.alloc(),
d = new Buffer(rawHeader + '\r\n\r\n');
parser.reinitialize(HTTPParser.RESPONSE);
parser.onIncoming = function(incoming, shouldKeepAlive) {
return true;
};
rawHeader = ss = iconv = undefined;
parser.execute(d, 0, d.length);
if (parser.incoming && parser.incoming.complete)
res.headers = parser.incoming.headers;
freeParser(parser);
}
iconv.on('data', function(str) {
rawHeader += str;
});
ss.on('info', function infofn(isMatch, data, start, end) {
if (data) {
var buf = new Buffer(end - start);
data.copy(buf, 0, start, end);
iconv.write(buf);
}
if (isMatch) {
parsing = false;
ss.removeListener('info', infofn);
iconv.end();
socket.ondata = oldOnData;
}
});
fn(null, socket);
process.nextTick(function() {
oldOnData = socket.ondata;
socket.ondata = function(d, start, end) {
if (parsing) {
var buf = new Buffer(end - start);
d.copy(buf, 0, start, end);
ss.push(buf);
}
oldOnData.call(socket, d, start, end);
};
var parser = req.parser,
oldOnIncoming = parser.onIncoming;
parser.onIncoming = function(res, shouldKeepAlive) {
process.nextTick(function() {
fixHeaders(res);
parser.onIncoming = oldOnIncoming;
oldOnIncoming.call(parser, res, shouldKeepAlive);
});
};
});
}
module.exports = function() {
return agentBase(ISOAgent);
};
var http = require('http');
var ISOAgent = require('./isoagent');
var url = '...',
opts = require('url').parse(url);
opts.agent = ISOAgent();
http.get(opts, function(res) {
console.dir(res.headers);
res.socket.end();
});
@bradisbell
Copy link

Thanks again for this! Your Agent code got me through several months. Now that Node.js v0.12.0 is out, I was able to switch back to not using this method.

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