mirror of
https://github.com/tenrok/axios.git
synced 2026-06-11 18:02:32 +03:00
Axios ES2017 (#4787)
* Added AxiosHeaders class; * Fixed README.md href; * Fixed a potential bug with headers normalization; * Fixed a potential bug with headers normalization; Refactored accessor building routine; Refactored default transforms; Removed `normalizeHeaderName` helper; * Added `Content-Length` accessor; Added missed `has` accessor to TS types; * Added `AxiosTransformStream` class; Added progress capturing ability for node.js environment; Added `maxRate` option to limit the data rate in node.js environment; Refactored event handled by `onUploadProgress` && `onDownloadProgress` listeners in browser environment; Added progress & data rate tests for the http adapter; Added response stream aborting test; Added a manual progress capture test for the browser; Updated TS types; Added TS tests; Refactored request abort logic for the http adapter; Added ability to abort the response stream; * Remove `stream/promises` & `timers/promises` modules usage in tests; * Use `abortcontroller-polyfill`; * Fixed AxiosTransformStream dead-lock in legacy node versions; Fixed CancelError emitting in streams; * Reworked AxiosTransformStream internal logic to optimize memory consumption; Added throwing an error if the request stream was silently destroying (without error) Refers to #3966; * Treat the destruction of the request stream as a cancellation of the request; Fixed tests; * Emit `progress` event in the next tick; * Initial refactoring; * Refactored Mocha tests to use ESM; * Refactored Karma tests to use rollup preprocessor & ESM; Replaced grunt with gulp; Improved dev scripts; Added Babel for rollup build; * Added default commonjs package export for Node build; Added automatic contributors list generator for package.json; Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
+398
-38
@@ -1,24 +1,105 @@
|
||||
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 pkg = require('./../../../package.json');
|
||||
var server, proxy;
|
||||
var AxiosError = require('../../../lib/core/AxiosError');
|
||||
var FormData = require('form-data');
|
||||
var formidable = require('formidable');
|
||||
var express = require('express');
|
||||
var multer = require('multer');
|
||||
var bodyParser = require('body-parser');
|
||||
import axios from '../../../index.js';
|
||||
import http from 'http';
|
||||
import https from 'https';
|
||||
import net from 'net';
|
||||
import url from 'url';
|
||||
import zlib from 'zlib';
|
||||
import stream from 'stream';
|
||||
import util from 'util';
|
||||
import assert from 'assert';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {EventEmitter} from 'events';
|
||||
let server, proxy;
|
||||
import AxiosError from '../../../lib/core/AxiosError.js';
|
||||
import FormData from 'form-data';
|
||||
import formidable from 'formidable';
|
||||
import express from 'express';
|
||||
import multer from 'multer';
|
||||
import bodyParser from 'body-parser';
|
||||
const isBlobSupported = typeof Blob !== 'undefined';
|
||||
import {Throttle} from 'stream-throttle';
|
||||
import devNull from 'dev-null';
|
||||
import {AbortController} from 'abortcontroller-polyfill/dist/cjs-ponyfill.js';
|
||||
|
||||
const __filename = url.fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
import getStream from 'get-stream';
|
||||
|
||||
function setTimeoutAsync(ms) {
|
||||
return new Promise(resolve=> setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
const pipelineAsync = util.promisify(stream.pipeline);
|
||||
const finishedAsync = util.promisify(stream.finished);
|
||||
|
||||
function toleranceRange(positive, negative) {
|
||||
const p = (1 + 1 / positive);
|
||||
const n = (1 / negative);
|
||||
|
||||
return (actualValue, value) => {
|
||||
return actualValue - value > 0 ? actualValue < value * p : actualValue > value * n;
|
||||
}
|
||||
}
|
||||
|
||||
var noop = ()=> {};
|
||||
|
||||
const LOCAL_SERVER_URL = 'http://localhost:4444';
|
||||
|
||||
function startHTTPServer({useBuffering= false, rate = undefined, port = 4444} = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
http.createServer(async function (req, res) {
|
||||
try {
|
||||
req.headers['content-length'] && res.setHeader('content-length', req.headers['content-length']);
|
||||
|
||||
var dataStream = req;
|
||||
|
||||
if (useBuffering) {
|
||||
dataStream = stream.Readable.from(await getStream(req));
|
||||
}
|
||||
|
||||
var streams = [dataStream];
|
||||
|
||||
if (rate) {
|
||||
streams.push(new Throttle({rate}))
|
||||
}
|
||||
|
||||
streams.push(res);
|
||||
|
||||
stream.pipeline(streams, (err) => {
|
||||
err && console.log('Server warning: ' + err.message)
|
||||
});
|
||||
} catch (err){
|
||||
console.warn('HTTP server error:', err);
|
||||
}
|
||||
|
||||
}).listen(port, function (err) {
|
||||
err ? reject(err) : resolve(this);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function generateReadableStream(length = 1024 * 1024, chunkSize = 10 * 1024, sleep = 50) {
|
||||
return stream.Readable.from(async function* (){
|
||||
let dataLength = 0;
|
||||
|
||||
while(dataLength < length) {
|
||||
const leftBytes = length - dataLength;
|
||||
|
||||
const chunk = Buffer.alloc(leftBytes > chunkSize? chunkSize : leftBytes);
|
||||
|
||||
dataLength += chunk.length;
|
||||
|
||||
yield chunk;
|
||||
|
||||
if (sleep) {
|
||||
await setTimeoutAsync(sleep);
|
||||
}
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
describe('supports http with nodejs', function () {
|
||||
|
||||
afterEach(function () {
|
||||
@@ -635,14 +716,15 @@ describe('supports http with nodejs', function () {
|
||||
});
|
||||
});
|
||||
|
||||
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) {
|
||||
describe('streams', function(){
|
||||
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) {
|
||||
@@ -653,23 +735,49 @@ describe('supports http with nodejs', function () {
|
||||
done();
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass errors for a failed stream', function (done) {
|
||||
var notExitPath = path.join(__dirname, 'does_not_exist');
|
||||
it('should pass errors for a failed stream', async function () {
|
||||
server = await startHTTPServer();
|
||||
|
||||
server = http.createServer(function (req, res) {
|
||||
req.pipe(res);
|
||||
}).listen(4444, function () {
|
||||
axios.post('http://localhost:4444/',
|
||||
fs.createReadStream(notExitPath)
|
||||
).then(function (res) {
|
||||
var notExitPath = path.join(__dirname, 'does_not_exist');
|
||||
|
||||
try {
|
||||
await axios.post(LOCAL_SERVER_URL,
|
||||
fs.createReadStream(notExitPath)
|
||||
);
|
||||
assert.fail('expected ENOENT error');
|
||||
}).catch(function (err) {
|
||||
} catch (err) {
|
||||
assert.equal(err.message, `ENOENT: no such file or directory, open \'${notExitPath}\'`);
|
||||
done();
|
||||
}).catch(done);
|
||||
}
|
||||
});
|
||||
|
||||
it('should destroy the response stream with an error on request stream destroying', async function () {
|
||||
server = await startHTTPServer();
|
||||
|
||||
let stream = generateReadableStream();
|
||||
|
||||
setTimeout(function () {
|
||||
stream.destroy();
|
||||
}, 1000);
|
||||
|
||||
const {data} = await axios.post(LOCAL_SERVER_URL, stream, {responseType: 'stream'});
|
||||
|
||||
let streamError;
|
||||
|
||||
data.on('error', function(err) {
|
||||
streamError = err;
|
||||
});
|
||||
|
||||
try {
|
||||
await pipelineAsync(data, devNull());
|
||||
assert.fail('stream was not aborted');
|
||||
} catch(e) {
|
||||
console.log(`pipeline error: ${e}`);
|
||||
} finally {
|
||||
assert.strictEqual(streamError && streamError.code, 'ERR_CANCELED');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1241,7 +1349,7 @@ describe('supports http with nodejs', function () {
|
||||
|
||||
it('should supply a user-agent if one is not specified', function (done) {
|
||||
server = http.createServer(function (req, res) {
|
||||
assert.equal(req.headers["user-agent"], 'axios/' + pkg.version);
|
||||
assert.equal(req.headers["user-agent"], 'axios/' + axios.VERSION);
|
||||
res.end();
|
||||
}).listen(4444, function () {
|
||||
axios.get('http://localhost:4444/'
|
||||
@@ -1532,4 +1640,256 @@ describe('supports http with nodejs', function () {
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('progress', function () {
|
||||
describe('upload', function () {
|
||||
it('should support upload progress capturing', async function () {
|
||||
server = await startHTTPServer({
|
||||
rate: 100 * 1024
|
||||
});
|
||||
|
||||
let content = '';
|
||||
const count = 10;
|
||||
const chunk = "test";
|
||||
const chunkLength = Buffer.byteLength(chunk);
|
||||
const contentLength = count * chunkLength;
|
||||
|
||||
var readable = stream.Readable.from(async function* () {
|
||||
let i = count;
|
||||
|
||||
while (i-- > 0) {
|
||||
await setTimeoutAsync(1100);
|
||||
content += chunk;
|
||||
yield chunk;
|
||||
}
|
||||
}());
|
||||
|
||||
const samples = [];
|
||||
|
||||
const {data} = await axios.post(LOCAL_SERVER_URL, readable, {
|
||||
onUploadProgress: ({loaded, total, progress, bytes, upload}) => {
|
||||
samples.push({
|
||||
loaded,
|
||||
total,
|
||||
progress,
|
||||
bytes,
|
||||
upload
|
||||
});
|
||||
},
|
||||
headers: {
|
||||
'Content-Length': contentLength
|
||||
},
|
||||
responseType: 'text'
|
||||
});
|
||||
|
||||
assert.strictEqual(data, content);
|
||||
|
||||
assert.deepStrictEqual(samples, Array.from(function* () {
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
yield ({
|
||||
loaded: chunkLength * i,
|
||||
total: contentLength,
|
||||
progress: (chunkLength * i) / contentLength,
|
||||
bytes: 4,
|
||||
upload: true
|
||||
});
|
||||
}
|
||||
}()));
|
||||
});
|
||||
});
|
||||
|
||||
describe('download', function () {
|
||||
it('should support download progress capturing', async function () {
|
||||
server = await startHTTPServer({
|
||||
rate: 100 * 1024
|
||||
});
|
||||
|
||||
let content = '';
|
||||
const count = 10;
|
||||
const chunk = "test";
|
||||
const chunkLength = Buffer.byteLength(chunk);
|
||||
const contentLength = count * chunkLength;
|
||||
|
||||
var readable = stream.Readable.from(async function* () {
|
||||
let i = count;
|
||||
|
||||
while (i-- > 0) {
|
||||
await setTimeoutAsync(1100);
|
||||
content += chunk;
|
||||
yield chunk;
|
||||
}
|
||||
}());
|
||||
|
||||
const samples = [];
|
||||
|
||||
const {data} = await axios.post(LOCAL_SERVER_URL, readable, {
|
||||
onDownloadProgress: ({loaded, total, progress, bytes, download}) => {
|
||||
samples.push({
|
||||
loaded,
|
||||
total,
|
||||
progress,
|
||||
bytes,
|
||||
download
|
||||
});
|
||||
},
|
||||
headers: {
|
||||
'Content-Length': contentLength
|
||||
},
|
||||
responseType: 'text',
|
||||
maxRedirects: 0
|
||||
});
|
||||
|
||||
assert.strictEqual(data, content);
|
||||
|
||||
assert.deepStrictEqual(samples, Array.from(function* () {
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
yield ({
|
||||
loaded: chunkLength * i,
|
||||
total: contentLength,
|
||||
progress: (chunkLength * i) / contentLength,
|
||||
bytes: 4,
|
||||
download: true
|
||||
});
|
||||
}
|
||||
}()));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rate limit', function () {
|
||||
it('should support upload rate limit', async function () {
|
||||
const secs = 10;
|
||||
const configRate = 100_000;
|
||||
const chunkLength = configRate * secs;
|
||||
|
||||
server = await startHTTPServer();
|
||||
|
||||
const buf = Buffer.alloc(chunkLength).fill('s');
|
||||
const samples = [];
|
||||
const skip = 2;
|
||||
const compareValues = toleranceRange(10, 50);
|
||||
|
||||
const {data} = await axios.post(LOCAL_SERVER_URL, buf, {
|
||||
onUploadProgress: ({loaded, total, progress, bytes, rate}) => {
|
||||
samples.push({
|
||||
loaded,
|
||||
total,
|
||||
progress,
|
||||
bytes,
|
||||
rate
|
||||
});
|
||||
},
|
||||
maxRate: [configRate],
|
||||
responseType: 'text',
|
||||
maxRedirects: 0
|
||||
});
|
||||
|
||||
samples.slice(skip).forEach(({rate, progress}, i, _samples)=> {
|
||||
assert.ok(compareValues(rate, configRate),
|
||||
`Rate sample at index ${i} is out of the expected range (${rate} / ${configRate}) [${
|
||||
_samples.map(({rate}) => rate).join(', ')
|
||||
}]`
|
||||
);
|
||||
|
||||
const progressTicksRate = 2;
|
||||
const expectedProgress = ((i + skip) / secs) / progressTicksRate;
|
||||
|
||||
assert.ok(
|
||||
Math.abs(expectedProgress - progress) < 0.25,
|
||||
`Progress sample at index ${i} is out of the expected range (${progress} / ${expectedProgress}) [${
|
||||
_samples.map(({progress}) => progress).join(', ')
|
||||
}]`
|
||||
);
|
||||
});
|
||||
|
||||
assert.strictEqual(data, buf.toString(), 'content corrupted');
|
||||
});
|
||||
|
||||
it('should support download rate limit', async function () {
|
||||
const secs = 10;
|
||||
const configRate = 100_000;
|
||||
const chunkLength = configRate * secs;
|
||||
|
||||
server = await startHTTPServer();
|
||||
|
||||
const buf = Buffer.alloc(chunkLength).fill('s');
|
||||
const samples = [];
|
||||
const skip = 2;
|
||||
const compareValues = toleranceRange(10, 50);
|
||||
|
||||
const {data} = await axios.post(LOCAL_SERVER_URL, buf, {
|
||||
onDownloadProgress: ({loaded, total, progress, bytes, rate}) => {
|
||||
samples.push({
|
||||
loaded,
|
||||
total,
|
||||
progress,
|
||||
bytes,
|
||||
rate
|
||||
});
|
||||
},
|
||||
maxRate: [0, configRate],
|
||||
responseType: 'text',
|
||||
maxRedirects: 0
|
||||
});
|
||||
|
||||
samples.slice(skip).forEach(({rate, progress}, i, _samples)=> {
|
||||
assert.ok(compareValues(rate, configRate),
|
||||
`Rate sample at index ${i} is out of the expected range (${rate} / ${configRate}) [${
|
||||
_samples.map(({rate}) => rate).join(', ')
|
||||
}]`
|
||||
);
|
||||
|
||||
const progressTicksRate = 2;
|
||||
const expectedProgress = ((i + skip) / secs) / progressTicksRate;
|
||||
|
||||
assert.ok(
|
||||
Math.abs(expectedProgress - progress) < 0.25,
|
||||
`Progress sample at index ${i} is out of the expected range (${progress} / ${expectedProgress}) [${
|
||||
_samples.map(({progress}) => progress).join(', ')
|
||||
}]`
|
||||
);
|
||||
});
|
||||
|
||||
assert.strictEqual(data, buf.toString(), 'content corrupted');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('request aborting', function() {
|
||||
it('should be able to abort the response stream', async function () {
|
||||
server = await startHTTPServer({
|
||||
rate: 100_000,
|
||||
useBuffering: true
|
||||
});
|
||||
|
||||
const buf = Buffer.alloc(1024 * 1024);
|
||||
|
||||
const controller = new AbortController();
|
||||
|
||||
var {data} = await axios.post(LOCAL_SERVER_URL, buf, {
|
||||
responseType: 'stream',
|
||||
signal: controller.signal,
|
||||
maxRedirects: 0
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
controller.abort();
|
||||
}, 500);
|
||||
|
||||
let streamError;
|
||||
|
||||
data.on('error', function(err) {
|
||||
streamError = err;
|
||||
});
|
||||
|
||||
try {
|
||||
await pipelineAsync(data, devNull());
|
||||
assert.fail('stream was not aborted');
|
||||
} catch(e) {
|
||||
console.log(`pipeline error: ${e}`);
|
||||
} finally {
|
||||
assert.strictEqual(streamError && streamError.code, 'ERR_CANCELED');
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
import AxiosHeaders from '../../../lib/core/AxiosHeaders.js';
|
||||
import assert from 'assert';
|
||||
|
||||
|
||||
describe('AxiosHeaders', function () {
|
||||
it('should support headers argument', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
x: 1,
|
||||
y: 2
|
||||
});
|
||||
|
||||
assert.strictEqual(headers.get('x'), '1');
|
||||
assert.strictEqual(headers.get('y'), '2');
|
||||
})
|
||||
|
||||
|
||||
describe('set', function () {
|
||||
it('should support adding a single header', function(){
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar');
|
||||
|
||||
assert.strictEqual(headers.get('foo'), 'bar');
|
||||
})
|
||||
|
||||
it('should support adding multiple headers', function(){
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set({
|
||||
foo: 'value1',
|
||||
bar: 'value2',
|
||||
});
|
||||
|
||||
assert.strictEqual(headers.get('foo'), 'value1');
|
||||
assert.strictEqual(headers.get('bar'), 'value2');
|
||||
})
|
||||
|
||||
it('should not rewrite header the header if the value is false', function(){
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'value1');
|
||||
|
||||
headers.set('foo', 'value2', false);
|
||||
|
||||
assert.strictEqual(headers.get('foo'), 'value1');
|
||||
|
||||
headers.set('foo', 'value2');
|
||||
|
||||
assert.strictEqual(headers.get('foo'), 'value2');
|
||||
|
||||
headers.set('foo', 'value3', true);
|
||||
|
||||
assert.strictEqual(headers.get('foo'), 'value3');
|
||||
});
|
||||
|
||||
it('should not rewrite the header if its value is false, unless rewrite options is set to true', function(){
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', false);
|
||||
headers.set('foo', 'value2');
|
||||
|
||||
assert.strictEqual(headers.get('foo'), false);
|
||||
|
||||
headers.set('foo', 'value2', true);
|
||||
|
||||
assert.strictEqual(headers.get('foo'), 'value2');
|
||||
})
|
||||
});
|
||||
|
||||
describe('get', function () {
|
||||
describe('filter', function() {
|
||||
it('should support RegExp', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.get('foo', /^bar=(\w+)/)[1], 'value1');
|
||||
assert.strictEqual(headers.get('foo', /^foo=/), null);
|
||||
});
|
||||
|
||||
it('should support function', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.get('foo', (value, header) => {
|
||||
assert.strictEqual(value, 'bar=value1');
|
||||
assert.strictEqual(header, 'foo');
|
||||
return value;
|
||||
}), 'bar=value1');
|
||||
assert.strictEqual(headers.get('foo', () => false), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('has', function () {
|
||||
it('should return true if the header is defined, otherwise false', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.has('foo'), true);
|
||||
assert.strictEqual(headers.has('bar'), false);
|
||||
});
|
||||
|
||||
describe('filter', function () {
|
||||
it('should support RegExp', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.has('foo', /^bar=(\w+)/), true);
|
||||
assert.strictEqual(headers.has('foo', /^foo=/), false);
|
||||
});
|
||||
|
||||
it('should support function', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.has('foo', (value, header, headers)=> {
|
||||
assert.strictEqual(value, 'bar=value1');
|
||||
assert.strictEqual(header, 'foo');
|
||||
return true;
|
||||
}), true);
|
||||
assert.strictEqual(headers.has('foo', ()=> false), false);
|
||||
});
|
||||
|
||||
it('should support string pattern', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.has('foo', 'value1'), true);
|
||||
assert.strictEqual(headers.has('foo', 'value2'), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', function () {
|
||||
it('should delete the header', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.has('foo'), true);
|
||||
|
||||
headers.delete('foo');
|
||||
|
||||
assert.strictEqual(headers.has('foo'), false);
|
||||
});
|
||||
|
||||
it('should return true if the header has been deleted, otherwise false', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.delete('bar'), false);
|
||||
|
||||
assert.strictEqual(headers.delete('foo'), true);
|
||||
});
|
||||
|
||||
it('should support headers array', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'x');
|
||||
headers.set('bar', 'y');
|
||||
headers.set('baz', 'z');
|
||||
|
||||
assert.strictEqual(headers.delete(['foo', 'baz']), true);
|
||||
|
||||
assert.strictEqual(headers.has('foo'), false);
|
||||
assert.strictEqual(headers.has('bar'), true);
|
||||
assert.strictEqual(headers.has('baa'), false);
|
||||
});
|
||||
|
||||
describe('filter', function () {
|
||||
it('should support RegExp', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.has('foo'), true);
|
||||
|
||||
headers.delete('foo', /baz=/);
|
||||
|
||||
assert.strictEqual(headers.has('foo'), true);
|
||||
|
||||
headers.delete('foo', /bar=/);
|
||||
|
||||
assert.strictEqual(headers.has('foo'), false);
|
||||
});
|
||||
|
||||
it('should support function', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
headers.delete('foo', (value, header)=> {
|
||||
assert.strictEqual(value, 'bar=value1');
|
||||
assert.strictEqual(header, 'foo');
|
||||
return false;
|
||||
});
|
||||
|
||||
assert.strictEqual(headers.has('foo'), true);
|
||||
|
||||
assert.strictEqual(headers.delete('foo', ()=> true), true);
|
||||
|
||||
assert.strictEqual(headers.has('foo'), false);
|
||||
});
|
||||
|
||||
it('should support string pattern', function () {
|
||||
const headers = new AxiosHeaders();
|
||||
|
||||
headers.set('foo', 'bar=value1');
|
||||
|
||||
assert.strictEqual(headers.has('foo'), true);
|
||||
|
||||
headers.delete('foo', 'baz');
|
||||
|
||||
assert.strictEqual(headers.has('foo'), true);
|
||||
|
||||
headers.delete('foo', 'bar');
|
||||
|
||||
assert.strictEqual(headers.has('foo'), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toJSON', function () {
|
||||
it('should return headers object with original headers case', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
Foo: 'x',
|
||||
bAr: 'y'
|
||||
});
|
||||
|
||||
assert.deepStrictEqual({...headers.toJSON()}, {
|
||||
Foo: 'x',
|
||||
bAr: 'y'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('accessors', function () {
|
||||
it('should support get accessor', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
foo: 1
|
||||
});
|
||||
|
||||
headers.constructor.accessor('foo');
|
||||
|
||||
assert.strictEqual(typeof headers.getFoo, 'function');
|
||||
assert.strictEqual(headers.getFoo(), '1');
|
||||
});
|
||||
|
||||
it('should support set accessor', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
foo: 1
|
||||
});
|
||||
|
||||
headers.constructor.accessor('foo');
|
||||
|
||||
assert.strictEqual(typeof headers.setFoo, 'function');
|
||||
headers.setFoo(2);
|
||||
assert.strictEqual(headers.getFoo(), '2');
|
||||
});
|
||||
|
||||
it('should support has accessor', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
foo: 1
|
||||
});
|
||||
|
||||
headers.constructor.accessor('foo');
|
||||
|
||||
assert.strictEqual(typeof headers.hasFoo, 'function');
|
||||
assert.strictEqual(headers.hasFoo(), true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be caseless', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
fOo: 1
|
||||
});
|
||||
|
||||
assert.strictEqual(headers.get('Foo'), '1');
|
||||
assert.strictEqual(headers.get('foo'), '1');
|
||||
|
||||
headers.set('foo', 2);
|
||||
|
||||
assert.strictEqual(headers.get('foO'), '2');
|
||||
assert.strictEqual(headers.get('fOo'), '2');
|
||||
|
||||
assert.strictEqual(headers.has('fOo'), true);
|
||||
|
||||
headers.delete('FOO');
|
||||
|
||||
assert.strictEqual(headers.has('fOo'), false);
|
||||
|
||||
});
|
||||
|
||||
describe('normalize()', function () {
|
||||
it('should support auto-formatting', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
fOo: 1,
|
||||
'x-foo': 2,
|
||||
'y-bar-bAz': 3
|
||||
});
|
||||
|
||||
assert.deepStrictEqual({...headers.normalize(true).toJSON()}, {
|
||||
Foo: '1',
|
||||
'X-Foo': '2',
|
||||
'Y-Bar-Baz': '3'
|
||||
});
|
||||
});
|
||||
|
||||
it('should support external defined values', function () {
|
||||
const headers = new AxiosHeaders({
|
||||
foo: '1'
|
||||
});
|
||||
|
||||
headers['Foo'] = 2;
|
||||
|
||||
headers['bar'] = 3;
|
||||
|
||||
assert.deepStrictEqual({...headers.normalize().toJSON()}, {
|
||||
foo: '2',
|
||||
bar: '3'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,29 +1,53 @@
|
||||
var defaults = require('../../../lib/defaults');
|
||||
var transformData = require('../../../lib/core/transformData');
|
||||
var assert = require('assert');
|
||||
import defaults from '../../../lib/defaults/index.js';
|
||||
import transformData from '../../../lib/core/transformData.js';
|
||||
import assert from 'assert';
|
||||
|
||||
describe('transformResponse', function () {
|
||||
describe('200 request', function () {
|
||||
it('parses json', function () {
|
||||
var data = '{"message": "hello, world"}';
|
||||
var result = transformData(data, {'content-type': 'application/json'}, 200, defaults.transformResponse);
|
||||
const data = '{"message": "hello, world"}';
|
||||
const result = transformData.call({
|
||||
data,
|
||||
response: {
|
||||
headers: {'content-type': 'application/json'},
|
||||
status: 200
|
||||
}
|
||||
}, defaults.transformResponse);
|
||||
assert.strictEqual(result.message, 'hello, world');
|
||||
});
|
||||
it('ignores XML', function () {
|
||||
var data = '<message>hello, world</message>';
|
||||
var result = transformData(data, {'content-type': 'text/xml'}, 200, defaults.transformResponse);
|
||||
const data = '<message>hello, world</message>';
|
||||
const result = transformData.call({
|
||||
data,
|
||||
response: {
|
||||
headers: {'content-type': 'text/xml'},
|
||||
status: 200
|
||||
}
|
||||
}, defaults.transformResponse);
|
||||
assert.strictEqual(result, data);
|
||||
});
|
||||
});
|
||||
describe('204 request', function () {
|
||||
it('does not parse the empty string', function () {
|
||||
var data = '';
|
||||
var result = transformData(data, {'content-type': undefined}, 204, defaults.transformResponse);
|
||||
const data = '';
|
||||
const result = transformData.call({
|
||||
data,
|
||||
response: {
|
||||
headers: {'content-type': undefined},
|
||||
status: 204
|
||||
}
|
||||
}, defaults.transformResponse);
|
||||
assert.strictEqual(result, '');
|
||||
});
|
||||
it('does not parse undefined', function () {
|
||||
var data = undefined;
|
||||
var result = transformData(data, {'content-type': undefined}, 200, defaults.transformResponse);
|
||||
const data = undefined;
|
||||
const result = transformData.call({
|
||||
data,
|
||||
response: {
|
||||
headers: {'content-type': undefined},
|
||||
status: 200
|
||||
}
|
||||
}, defaults.transformResponse);
|
||||
assert.strictEqual(result, data);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var assert = require('assert');
|
||||
var fromDataURI = require('../../../lib/helpers/fromDataURI');
|
||||
import assert from 'assert';
|
||||
import fromDataURI from '../../../lib/helpers/fromDataURI.js';
|
||||
|
||||
describe('helpers::fromDataURI', function () {
|
||||
it('should return buffer from data uri', function () {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var assert = require('assert');
|
||||
var utils = require('../../../lib/utils');
|
||||
var parseProtocol = require('../../../lib/helpers/parseProtocol');
|
||||
import assert from 'assert';
|
||||
import utils from '../../../lib/utils.js';
|
||||
import parseProtocol from '../../../lib/helpers/parseProtocol.js';
|
||||
|
||||
describe('helpers::parseProtocol', function () {
|
||||
it('should parse protocol part if it exists', function () {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// https://github.com/axios/axios/issues/3407
|
||||
// https://github.com/axios/axios/issues/3369
|
||||
|
||||
const axios = require('../../../index');
|
||||
const http = require('http');
|
||||
const assert = require('assert');
|
||||
import axios from '../../../index.js';
|
||||
import http from 'http';
|
||||
import assert from 'assert';
|
||||
|
||||
const PROXY_PORT = 4777;
|
||||
const EVIL_PORT = 4666;
|
||||
@@ -58,4 +58,4 @@ describe('Server-Side Request Forgery (SSRF)', () => {
|
||||
return response;
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
var assert = require('assert');
|
||||
var isFormData = require('../../../lib/utils').isFormData;
|
||||
var FormData = require('form-data');
|
||||
|
||||
describe('utils::isFormData', function () {
|
||||
it('should detect the FormData instance provided by the `form-data` package', function () {
|
||||
[1, 'str', {}, new RegExp()].forEach(function (thing) {
|
||||
assert.equal(isFormData(thing), false);
|
||||
});
|
||||
assert.equal(isFormData(new FormData()), true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
import assert from 'assert';
|
||||
import utils from '../../../lib/utils.js';
|
||||
import FormData from 'form-data';
|
||||
import stream from 'stream';
|
||||
|
||||
describe('utils', function (){
|
||||
it('should validate Stream', function () {
|
||||
assert.strictEqual(utils.isStream(new stream.Readable()),true);
|
||||
assert.strictEqual(utils.isStream({ foo: 'bar' }),false);
|
||||
});
|
||||
|
||||
it('should validate Buffer', function () {
|
||||
assert.strictEqual(utils.isBuffer(Buffer.from('a')),true);
|
||||
assert.strictEqual(utils.isBuffer(null),false);
|
||||
assert.strictEqual(utils.isBuffer(undefined),false);
|
||||
});
|
||||
|
||||
describe('utils::isFormData', function () {
|
||||
it('should detect the FormData instance provided by the `form-data` package', function () {
|
||||
[1, 'str', {}, new RegExp()].forEach(function (thing) {
|
||||
assert.equal(utils.isFormData(thing), false);
|
||||
});
|
||||
assert.equal(utils.isFormData(new FormData()), true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user