var axios = require('../../../index'); var http = require('http'); var https = require('https'); var net = require('net'); var url = require('url'); var zlib = require('zlib'); var assert = require('assert'); var fs = require('fs'); var path = require('path'); var server, proxy; describe('supports http with nodejs', function () { afterEach(function () { if (server) { server.close(); server = null; } if (proxy) { proxy.close() proxy = null; } if (process.env.http_proxy) { delete process.env.http_proxy; } if (process.env.no_proxy) { delete process.env.no_proxy; } }); it('should respect the timeout property', function (done) { server = http.createServer(function (req, res) { setTimeout(function () { res.end(); }, 1000); }).listen(4444, function () { var success = false, failure = false; var error; axios.get('http://localhost:4444/', { timeout: 250 }).then(function (res) { success = true; }).catch(function (err) { error = err; failure = true; }); setTimeout(function () { assert.equal(success, false, 'request should not succeed'); assert.equal(failure, true, 'request should fail'); assert.equal(error.code, 'ECONNABORTED'); assert.equal(error.message, 'timeout of 250ms exceeded'); done(); }, 300); }); }); it('should allow passing JSON', function (done) { var data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com' }; server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'application/json;charset=utf-8'); res.end(JSON.stringify(data)); }).listen(4444, function () { axios.get('http://localhost:4444/').then(function (res) { assert.deepEqual(res.data, data); done(); }); }); }); it('should allow passing JSON with BOM', function (done) { var data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com' }; server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'application/json;charset=utf-8'); var bomBuffer = Buffer.from([0xEF, 0xBB, 0xBF]) var jsonBuffer = Buffer.from(JSON.stringify(data)); res.end(Buffer.concat([bomBuffer, jsonBuffer])); }).listen(4444, function () { axios.get('http://localhost:4444/').then(function (res) { assert.deepEqual(res.data, data); done(); }); }); }); it('should redirect', function (done) { var str = 'test response'; server = http.createServer(function (req, res) { var parsed = url.parse(req.url); if (parsed.pathname === '/one') { res.setHeader('Location', '/two'); res.statusCode = 302; res.end(); } else { res.end(str); } }).listen(4444, function () { axios.get('http://localhost:4444/one').then(function (res) { assert.equal(res.data, str); assert.equal(res.request.path, '/two'); done(); }); }); }); it('should not redirect', function (done) { server = http.createServer(function (req, res) { res.setHeader('Location', '/foo'); res.statusCode = 302; res.end(); }).listen(4444, function () { axios.get('http://localhost:4444/', { maxRedirects: 0, validateStatus: function () { return true; } }).then(function (res) { assert.equal(res.status, 302); assert.equal(res.headers['location'], '/foo'); done(); }); }); }); it('should support max redirects', function (done) { var i = 1; server = http.createServer(function (req, res) { res.setHeader('Location', '/' + i); res.statusCode = 302; res.end(); i++; }).listen(4444, function () { axios.get('http://localhost:4444/', { maxRedirects: 3 }).catch(function (error) { done(); }); }); }); it('should preserve the HTTP verb on redirect', function (done) { server = http.createServer(function (req, res) { if (req.method.toLowerCase() !== "head") { res.statusCode = 400; res.end(); return; } var parsed = url.parse(req.url); if (parsed.pathname === '/one') { res.setHeader('Location', '/two'); res.statusCode = 302; res.end(); } else { res.end(); } }).listen(4444, function () { axios.head('http://localhost:4444/one').then(function (res) { assert.equal(res.status, 200); done(); }).catch(function (err) { done(err); }); }); }); it('should support transparent gunzip', function (done) { var data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com' }; zlib.gzip(JSON.stringify(data), function (err, zipped) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'application/json;charset=utf-8'); res.setHeader('Content-Encoding', 'gzip'); res.end(zipped); }).listen(4444, function () { axios.get('http://localhost:4444/').then(function (res) { assert.deepEqual(res.data, data); done(); }); }); }); }); it('should support gunzip error handling', function (done) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'application/json;charset=utf-8'); res.setHeader('Content-Encoding', 'gzip'); res.end('invalid response'); }).listen(4444, function () { axios.get('http://localhost:4444/').catch(function (error) { done(); }); }); }); it('should support disabling automatic decompression of response data', function(done) { var data = 'Test data'; zlib.gzip(data, function(err, zipped) { server = http.createServer(function(req, res) { res.setHeader('Content-Type', 'text/html;charset=utf-8'); res.setHeader('Content-Encoding', 'gzip'); res.end(zipped); }).listen(4444, function() { axios.get('http://localhost:4444/', { decompress: false, responseType: 'arraybuffer' }).then(function(res) { assert.equal(res.data.toString('base64'), zipped.toString('base64')); done(); }); }); }); }); it('should support UTF8', function (done) { var str = Array(100000).join('ж'); server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(str); }).listen(4444, function () { axios.get('http://localhost:4444/').then(function (res) { assert.equal(res.data, str); done(); }); }); }); it('should support basic auth', function (done) { server = http.createServer(function (req, res) { res.end(req.headers.authorization); }).listen(4444, function () { var user = 'foo'; var headers = { Authorization: 'Bearer 1234' }; axios.get('http://' + user + '@localhost:4444/', { headers: headers }).then(function (res) { var base64 = Buffer.from(user + ':', 'utf8').toString('base64'); assert.equal(res.data, 'Basic ' + base64); done(); }); }); }); it('should support basic auth with a header', function (done) { server = http.createServer(function (req, res) { res.end(req.headers.authorization); }).listen(4444, function () { var auth = { username: 'foo', password: 'bar' }; var headers = { Authorization: 'Bearer 1234' }; axios.get('http://localhost:4444/', { auth: auth, headers: headers }).then(function (res) { var base64 = Buffer.from('foo:bar', 'utf8').toString('base64'); assert.equal(res.data, 'Basic ' + base64); done(); }); }); }); it('should support max content length', function (done) { var str = Array(100000).join('ж'); server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(str); }).listen(4444, function () { var success = false, failure = false, error; axios.get('http://localhost:4444/', { maxContentLength: 2000 }).then(function (res) { success = true; }).catch(function (err) { error = err; failure = true; }); setTimeout(function () { assert.equal(success, false, 'request should not succeed'); assert.equal(failure, true, 'request should fail'); assert.equal(error.message, 'maxContentLength size of 2000 exceeded'); done(); }, 100); }); }); it('should support max content length for redirected', function (done) { var str = Array(100000).join('ж'); server = http.createServer(function (req, res) { var parsed = url.parse(req.url); if (parsed.pathname === '/two') { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(str); } else { res.setHeader('Location', '/two'); res.statusCode = 302; res.end(); } }).listen(4444, function () { var success = false, failure = false, error; axios.get('http://localhost:4444/one', { maxContentLength: 2000 }).then(function (res) { success = true; }).catch(function (err) { error = err; failure = true; }); setTimeout(function () { assert.equal(success, false, 'request should not succeed'); assert.equal(failure, true, 'request should fail'); assert.equal(error.message, 'maxContentLength size of 2000 exceeded'); done(); }, 100); }); }); it('should support max body length', function (done) { var data = Array(100000).join('ж'); server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(); }).listen(4444, function () { var success = false, failure = false, error; axios.post('http://localhost:4444/', { data: data }, { maxBodyLength: 2000 }).then(function (res) { success = true; }).catch(function (err) { error = err; failure = true; }); setTimeout(function () { assert.equal(success, false, 'request should not succeed'); assert.equal(failure, true, 'request should fail'); assert.equal(error.code, 'ERR_FR_MAX_BODY_LENGTH_EXCEEDED'); assert.equal(error.message, 'Request body larger than maxBodyLength limit'); done(); }, 100); }); }); it('should support sockets', function (done) { // Different sockets for win32 vs darwin/linux var socketName = './test.sock'; if (process.platform === 'win32') { socketName = '\\\\.\\pipe\\libuv-test'; } server = net.createServer(function (socket) { socket.on('data', function () { socket.end('HTTP/1.1 200 OK\r\n\r\n'); }); }).listen(socketName, function () { axios({ socketPath: socketName, url: '/' }) .then(function (resp) { assert.equal(resp.status, 200); assert.equal(resp.statusText, 'OK'); done(); }) .catch(function (error) { assert.ifError(error); done(); }); }); }); it('should support streams', function (done) { server = http.createServer(function (req, res) { req.pipe(res); }).listen(4444, function () { axios.post('http://localhost:4444/', fs.createReadStream(__filename), { responseType: 'stream' }).then(function (res) { var stream = res.data; var string = ''; stream.on('data', function (chunk) { string += chunk.toString('utf8'); }); stream.on('end', function () { assert.equal(string, fs.readFileSync(__filename, 'utf8')); done(); }); }); }); }); it('should pass errors for a failed stream', function (done) { var notExitPath = path.join(__dirname, 'does_not_exist'); server = http.createServer(function (req, res) { req.pipe(res); }).listen(4444, function () { axios.post('http://localhost:4444/', fs.createReadStream(notExitPath) ).then(function (res) { assert.fail(); }).catch(function (err) { assert.equal(err.message, `ENOENT: no such file or directory, open \'${notExitPath}\'`); done(); }); }); }); it('should support buffers', function (done) { var buf = Buffer.alloc(1024, 'x'); // Unsafe buffer < Buffer.poolSize (8192 bytes) server = http.createServer(function (req, res) { assert.equal(req.headers['content-length'], buf.length.toString()); req.pipe(res); }).listen(4444, function () { axios.post('http://localhost:4444/', buf, { responseType: 'stream' }).then(function (res) { var stream = res.data; var string = ''; stream.on('data', function (chunk) { string += chunk.toString('utf8'); }); stream.on('end', function () { assert.equal(string, buf.toString()); done(); }); }); }); }); it('should support HTTP proxies', function (done) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('12345'); }).listen(4444, function () { proxy = http.createServer(function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path }; http.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '6789'); }); }); }).listen(4000, function () { axios.get('http://localhost:4444/', { proxy: { host: 'localhost', port: 4000 } }).then(function (res) { assert.equal(res.data, '123456789', 'should pass through proxy'); done(); }); }); }); }); it('should support HTTPS proxies', function (done) { var options = { key: fs.readFileSync(path.join(__dirname, 'key.pem')), cert: fs.readFileSync(path.join(__dirname, 'cert.pem')) }; server = https.createServer(options, function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('12345'); }).listen(4444, function () { proxy = https.createServer(options, function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path, protocol: parsed.protocol, rejectUnauthorized: false }; https.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '6789'); }); }); }).listen(4000, function () { axios.get('https://localhost:4444/', { proxy: { host: 'localhost', port: 4000, protocol: 'https' }, httpsAgent: new https.Agent({ rejectUnauthorized: false }) }).then(function (res) { assert.equal(res.data, '123456789', 'should pass through proxy'); done(); }).catch(function (err) { assert.fail(err); done() }); }); }); }); it('should not pass through disabled proxy', function (done) { // set the env variable process.env.http_proxy = 'http://does-not-exists.example.com:4242/'; server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('123456789'); }).listen(4444, function () { axios.get('http://localhost:4444/', { proxy: false }).then(function (res) { assert.equal(res.data, '123456789', 'should not pass through proxy'); done(); }); }); }); it('should support proxy set via env var', function (done) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('4567'); }).listen(4444, function () { proxy = http.createServer(function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path }; http.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '1234'); }); }); }).listen(4000, function () { // set the env variable process.env.http_proxy = 'http://localhost:4000/'; axios.get('http://localhost:4444/').then(function (res) { assert.equal(res.data, '45671234', 'should use proxy set by process.env.http_proxy'); done(); }); }); }); }); it('should support HTTPS proxy set via env var', function (done) { var options = { key: fs.readFileSync(path.join(__dirname, 'key.pem')), cert: fs.readFileSync(path.join(__dirname, 'cert.pem')) }; server = https.createServer(options, function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('12345'); }).listen(4444, function () { proxy = https.createServer(options, function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path, protocol: parsed.protocol, rejectUnauthorized: false }; https.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '6789'); }); }); }).listen(4000, function () { process.env.https_proxy = 'https://localhost:4000/'; axios.get('https://localhost:4444/', { httpsAgent: new https.Agent({ rejectUnauthorized: false }) }).then(function (res) { assert.equal(res.data, '123456789', 'should pass through proxy'); done(); }).catch(function (err) { assert.fail(err); done() }).finally(function () { process.env.https_proxy = '' }); }); }); }); it('should not use proxy for domains in no_proxy', function (done) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('4567'); }).listen(4444, function () { proxy = http.createServer(function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path }; http.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '1234'); }); }); }).listen(4000, function () { // set the env variable process.env.http_proxy = 'http://localhost:4000/'; process.env.no_proxy = 'foo.com, localhost,bar.net , , quix.co'; axios.get('http://localhost:4444/').then(function (res) { assert.equal(res.data, '4567', 'should not use proxy for domains in no_proxy'); done(); }); }); }); }); it('should use proxy for domains not in no_proxy', function (done) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('4567'); }).listen(4444, function () { proxy = http.createServer(function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path }; http.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '1234'); }); }); }).listen(4000, function () { // set the env variable process.env.http_proxy = 'http://localhost:4000/'; process.env.no_proxy = 'foo.com, ,bar.net , quix.co'; axios.get('http://localhost:4444/').then(function (res) { assert.equal(res.data, '45671234', 'should use proxy for domains not in no_proxy'); done(); }); }); }); }); it('should support HTTP proxy auth', function (done) { server = http.createServer(function (req, res) { res.end(); }).listen(4444, function () { proxy = http.createServer(function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path }; var proxyAuth = request.headers['proxy-authorization']; http.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(proxyAuth); }); }); }).listen(4000, function () { axios.get('http://localhost:4444/', { proxy: { host: 'localhost', port: 4000, auth: { username: 'user', password: 'pass' } } }).then(function (res) { var base64 = Buffer.from('user:pass', 'utf8').toString('base64'); assert.equal(res.data, 'Basic ' + base64, 'should authenticate to the proxy'); done(); }); }); }); }); it('should support proxy auth from env', function (done) { server = http.createServer(function (req, res) { res.end(); }).listen(4444, function () { proxy = http.createServer(function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path }; var proxyAuth = request.headers['proxy-authorization']; http.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(proxyAuth); }); }); }).listen(4000, function () { process.env.http_proxy = 'http://user:pass@localhost:4000/'; axios.get('http://localhost:4444/').then(function (res) { var base64 = Buffer.from('user:pass', 'utf8').toString('base64'); assert.equal(res.data, 'Basic ' + base64, 'should authenticate to the proxy set by process.env.http_proxy'); done(); }); }); }); }); it('should support proxy auth with header', function (done) { server = http.createServer(function (req, res) { res.end(); }).listen(4444, function () { proxy = http.createServer(function (request, response) { var parsed = url.parse(request.url); var opts = { host: parsed.hostname, port: parsed.port, path: parsed.path }; var proxyAuth = request.headers['proxy-authorization']; http.get(opts, function (res) { var body = ''; res.on('data', function (data) { body += data; }); res.on('end', function () { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(proxyAuth); }); }); }).listen(4000, function () { axios.get('http://localhost:4444/', { proxy: { host: 'localhost', port: 4000, auth: { username: 'user', password: 'pass' } }, headers: { 'Proxy-Authorization': 'Basic abc123' } }).then(function (res) { var base64 = Buffer.from('user:pass', 'utf8').toString('base64'); assert.equal(res.data, 'Basic ' + base64, 'should authenticate to the proxy'); done(); }); }); }); }); it('should support cancel', function (done) { var source = axios.CancelToken.source(); server = http.createServer(function (req, res) { // call cancel() when the request has been sent, but a response has not been received source.cancel('Operation has been canceled.'); }).listen(4444, function () { axios.get('http://localhost:4444/', { cancelToken: source.token }).catch(function (thrown) { assert.ok(thrown instanceof axios.Cancel, 'Promise must be rejected with a Cancel obejct'); assert.equal(thrown.message, 'Operation has been canceled.'); done(); }); }); }); it('should combine baseURL and url', function (done) { server = http.createServer(function (req, res) { res.end(); }).listen(4444, function () { axios.get('/foo', { baseURL: 'http://localhost:4444/', }).then(function (res) { assert.equal(res.config.baseURL, 'http://localhost:4444/'); assert.equal(res.config.url, '/foo'); done(); }); }); }); });