This will add the capability for handling gzipped content to the

http connector. On one hand, the response is handled with buffers
instead of assuming it is a string, and then depending on the
presence of the "content-encoding" header, will try to uncompress
the response or return it as it is. Either way, it will try to
handle the final result as an utf8 encoded string
This commit is contained in:
Marcelo Gornstein
2014-09-02 13:05:14 -03:00
parent 01d233a428
commit aec0333a91
2 changed files with 63 additions and 5 deletions

View File

@ -16,6 +16,7 @@ var _ = require('../utils');
var qs = require('querystring');
var ForeverAgent = require('./_custom_agent');
var ConnectionAbstract = require('../connection');
var zlib = require('zlib');
/**
* Connector used to talk to an elasticsearch node via HTTP
@ -123,8 +124,9 @@ HttpConnector.prototype.request = function (params, cb) {
var request;
var response;
var status = 0;
var headers;
var headers = {};
var log = this.log;
var buffers = [];
var reqParams = this.makeReqParams(params);
@ -144,7 +146,20 @@ HttpConnector.prototype.request = function (params, cb) {
if (err) {
cb(err);
} else {
cb(err, response, status, headers);
response = Buffer.concat(buffers);
if (headers['content-encoding'] && headers['content-encoding'].match(/gzip/i)) {
zlib.unzip(response, function(gzErr, uncompressedResponse) {
if(gzErr) {
err = gzErr;
response = response.toString('binary');
} else {
response = uncompressedResponse.toString('utf8');
}
cb(err, response, status, headers);
});
} else {
cb(err, response.toString('utf8'), status, headers);
}
}
}, this);
@ -152,11 +167,10 @@ HttpConnector.prototype.request = function (params, cb) {
incoming = _incoming;
status = incoming.statusCode;
headers = incoming.headers;
incoming.setEncoding('utf8');
response = '';
buffers = [];
incoming.on('data', function (d) {
response += d;
buffers.push(new Buffer(d));
});
incoming.on('error', cleanUp);

View File

@ -17,6 +17,8 @@ describe('Http Connector', function () {
var expectSubObject = require('../../utils/expect_sub_object');
var MockRequest = require('../../mocks/request');
var MockIncommingMessage = require('../../mocks/incomming_message');
var zlib = require('zlib');
var estr = require('event-stream');
nock.disableNetConnect();
@ -302,6 +304,48 @@ describe('Http Connector', function () {
});
});
it('collects the whole request body (compressed)', function (done) {
var server = nock('http://esjs.com:9200');
var con = new HttpConnection(new Host('http://esjs.com:9200'));
var body = '{ "USER": "doc" }';
zlib.deflate(body, function(err, compressedBody) {
server
.get('/users/1')
.reply(200, compressedBody, {'Content-Encoding': 'gzip'});
con.request({
method: 'GET',
path: '/users/1'
}, function (err, resp, status) {
expect(err).to.be(undefined);
expect(resp).to.eql(body);
expect(status).to.eql(200);
server.done();
done();
});
});
});
it('Can handle uncompress errors', function (done) {
var server = nock('http://esjs.com:9200');
var con = new HttpConnection(new Host('http://esjs.com:9200'));
var body = 'blah';
server
.get('/users/1')
.reply(200, body, {'Content-Encoding': 'gzip'});
con.request({
method: 'GET',
path: '/users/1'
}, function (err, resp, status) {
expect(err.errno).to.be(-3);
expect(resp).to.eql(body);
expect(status).to.eql(200);
server.done();
done();
});
});
it('Ignores serialization errors', function (done) {
var server = nock('http://esjs.com:9200');
var con = new HttpConnection(new Host('http://esjs.com:9200'));