mirror of
https://github.com/tenrok/axios.git
synced 2026-06-23 20:40:40 +03:00
fix: support URL object as config.url input (#10866)
* fix(buildURL): support URL object as input Fixes #6546 When passing a URL object (e.g., new URL(...)) to axios methods like axios.get(url, { params: {...} }), the buildURL function would crash with 'url.indexOf is not a function' because it assumed url was always a string. This fix converts URL objects to strings before processing. * fix: support URL object as config.url input - Move URL object coercion from buildURL to Axios._request so that all downstream consumers (buildFullPath, combineURLs, adapters) see a string. This fixes the crash when using URL object with baseURL (combineURLs calls .replace() on the URL object). - Remove the broken buildURL unit test that tested buildURL(url, null) without actually exercising URL coercion (buildURL early-returns when !params). - Add e2e tests via the HTTP adapter for URL object with params and URL object without params (no crash). * feat: note + example added under axios(url[, config]) documenting URL support * feat: url widened to string | URL * feat: oercion now uses config.url instanceof url * chore: add additional test cases to improve coverage * fix: apply suggestions from cubic review --------- Co-authored-by: liuwei53 <liuwei53@baidu.com> Co-authored-by: Jason Saayman <jasonsaayman@gmail.com>
This commit is contained in:
@@ -592,11 +592,20 @@ response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'));
|
|||||||
|
|
||||||
##### axios(url[, config])
|
##### axios(url[, config])
|
||||||
|
|
||||||
|
`url` accepts either a string or a [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) instance. The `URL` is coerced to a string before the request is dispatched.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Send a GET request (default method)
|
// Send a GET request (default method)
|
||||||
axios('/user/12345');
|
axios('/user/12345');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
// `url` may also be a URL object
|
||||||
|
axios.get(new URL('https://api.example.com/foo'), {
|
||||||
|
params: { a: 1 },
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### Request method aliases
|
### Request method aliases
|
||||||
|
|
||||||
For convenience, aliases have been provided for all common request methods.
|
For convenience, aliases have been provided for all common request methods.
|
||||||
|
|||||||
+13
-13
@@ -176,53 +176,53 @@ declare class Axios {
|
|||||||
config: axios.AxiosRequestConfig<D>
|
config: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
get<T = any, R = axios.AxiosResponse<T>, D = any>(
|
get<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
delete<T = any, R = axios.AxiosResponse<T>, D = any>(
|
delete<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
head<T = any, R = axios.AxiosResponse<T>, D = any>(
|
head<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
options<T = any, R = axios.AxiosResponse<T>, D = any>(
|
options<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
post<T = any, R = axios.AxiosResponse<T>, D = any>(
|
post<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
put<T = any, R = axios.AxiosResponse<T>, D = any>(
|
put<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
patch<T = any, R = axios.AxiosResponse<T>, D = any>(
|
patch<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
postForm<T = any, R = axios.AxiosResponse<T>, D = any>(
|
postForm<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
putForm<T = any, R = axios.AxiosResponse<T>, D = any>(
|
putForm<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
patchForm<T = any, R = axios.AxiosResponse<T>, D = any>(
|
patchForm<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
query<T = any, R = axios.AxiosResponse<T>, D = any>(
|
query<T = any, R = axios.AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: axios.AxiosRequestConfig<D>
|
config?: axios.AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
@@ -473,7 +473,7 @@ declare namespace axios {
|
|||||||
type LookupAddress = string | LookupAddressEntry;
|
type LookupAddress = string | LookupAddressEntry;
|
||||||
|
|
||||||
interface AxiosRequestConfig<D = any> {
|
interface AxiosRequestConfig<D = any> {
|
||||||
url?: string;
|
url?: string | URL;
|
||||||
method?: Method | string;
|
method?: Method | string;
|
||||||
baseURL?: string;
|
baseURL?: string;
|
||||||
allowAbsoluteUrls?: boolean;
|
allowAbsoluteUrls?: boolean;
|
||||||
@@ -661,7 +661,7 @@ declare namespace axios {
|
|||||||
interface AxiosInstance extends Axios {
|
interface AxiosInstance extends Axios {
|
||||||
<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
|
<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
|
||||||
<T = any, R = AxiosResponse<T>, D = any>(
|
<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
|
|
||||||
|
|||||||
Vendored
+13
-13
@@ -364,7 +364,7 @@ export interface LookupAddressEntry {
|
|||||||
export type LookupAddress = string | LookupAddressEntry;
|
export type LookupAddress = string | LookupAddressEntry;
|
||||||
|
|
||||||
export interface AxiosRequestConfig<D = any> {
|
export interface AxiosRequestConfig<D = any> {
|
||||||
url?: string;
|
url?: string | URL;
|
||||||
method?: StringLiteralsOrString<Method>;
|
method?: StringLiteralsOrString<Method>;
|
||||||
baseURL?: string;
|
baseURL?: string;
|
||||||
allowAbsoluteUrls?: boolean;
|
allowAbsoluteUrls?: boolean;
|
||||||
@@ -609,53 +609,53 @@ export class Axios {
|
|||||||
getUri(config?: AxiosRequestConfig): string;
|
getUri(config?: AxiosRequestConfig): string;
|
||||||
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
|
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
|
||||||
get<T = any, R = AxiosResponse<T>, D = any>(
|
get<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
delete<T = any, R = AxiosResponse<T>, D = any>(
|
delete<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
head<T = any, R = AxiosResponse<T>, D = any>(
|
head<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
options<T = any, R = AxiosResponse<T>, D = any>(
|
options<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
post<T = any, R = AxiosResponse<T>, D = any>(
|
post<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
put<T = any, R = AxiosResponse<T>, D = any>(
|
put<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
patch<T = any, R = AxiosResponse<T>, D = any>(
|
patch<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
postForm<T = any, R = AxiosResponse<T>, D = any>(
|
postForm<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
putForm<T = any, R = AxiosResponse<T>, D = any>(
|
putForm<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
patchForm<T = any, R = AxiosResponse<T>, D = any>(
|
patchForm<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
query<T = any, R = AxiosResponse<T>, D = any>(
|
query<T = any, R = AxiosResponse<T>, D = any>(
|
||||||
url: string,
|
url: string | URL,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>
|
config?: AxiosRequestConfig<D>
|
||||||
): Promise<R>;
|
): Promise<R>;
|
||||||
@@ -663,7 +663,7 @@ export class Axios {
|
|||||||
|
|
||||||
export interface AxiosInstance extends Axios {
|
export interface AxiosInstance extends Axios {
|
||||||
<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
|
<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
|
||||||
<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
|
<T = any, R = AxiosResponse<T>, D = any>(url: string | URL, config?: AxiosRequestConfig<D>): Promise<R>;
|
||||||
|
|
||||||
create(config?: CreateAxiosDefaults): AxiosInstance;
|
create(config?: CreateAxiosDefaults): AxiosInstance;
|
||||||
defaults: Omit<AxiosDefaults, 'headers'> & {
|
defaults: Omit<AxiosDefaults, 'headers'> & {
|
||||||
|
|||||||
+25
-3
@@ -12,6 +12,19 @@ import transitionalDefaults from '../defaults/transitional.js';
|
|||||||
|
|
||||||
const validators = validator.validators;
|
const validators = validator.validators;
|
||||||
|
|
||||||
|
const { toString } = Object.prototype;
|
||||||
|
|
||||||
|
const isURL = (url) => {
|
||||||
|
if (url === null || typeof url !== 'object') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prototype = Object.getPrototypeOf(url);
|
||||||
|
return prototype !== null && prototype !== Object.prototype && toString.call(url) === '[object URL]';
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizeURL = (url) => (isURL(url) ? url.toString() : url);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of Axios
|
* Create a new instance of Axios
|
||||||
*
|
*
|
||||||
@@ -31,7 +44,7 @@ class Axios {
|
|||||||
/**
|
/**
|
||||||
* Dispatch a request
|
* Dispatch a request
|
||||||
*
|
*
|
||||||
* @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults)
|
* @param {String|URL|Object} configOrUrl The config specific for this request (merged with this.defaults)
|
||||||
* @param {?Object} config
|
* @param {?Object} config
|
||||||
*
|
*
|
||||||
* @returns {Promise} The Promise to be fulfilled
|
* @returns {Promise} The Promise to be fulfilled
|
||||||
@@ -82,13 +95,19 @@ class Axios {
|
|||||||
_request(configOrUrl, config) {
|
_request(configOrUrl, config) {
|
||||||
/*eslint no-param-reassign:0*/
|
/*eslint no-param-reassign:0*/
|
||||||
// Allow for axios('example/url'[, config]) a la fetch API
|
// Allow for axios('example/url'[, config]) a la fetch API
|
||||||
if (typeof configOrUrl === 'string') {
|
if (typeof configOrUrl === 'string' || isURL(configOrUrl)) {
|
||||||
config = config || {};
|
config = config || {};
|
||||||
config.url = configOrUrl;
|
config.url = normalizeURL(configOrUrl);
|
||||||
} else {
|
} else {
|
||||||
config = configOrUrl || {};
|
config = configOrUrl || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Coerce config.url to a string if it's a URL object, so that all downstream
|
||||||
|
// consumers (buildFullPath, combineURLs, adapters) see a string.
|
||||||
|
if (isURL(config.url)) {
|
||||||
|
config.url = normalizeURL(config.url);
|
||||||
|
}
|
||||||
|
|
||||||
config = mergeConfig(this.defaults, config);
|
config = mergeConfig(this.defaults, config);
|
||||||
|
|
||||||
const { transitional, paramsSerializer, headers } = config;
|
const { transitional, paramsSerializer, headers } = config;
|
||||||
@@ -232,6 +251,9 @@ class Axios {
|
|||||||
|
|
||||||
getUri(config) {
|
getUri(config) {
|
||||||
config = mergeConfig(this.defaults, config);
|
config = mergeConfig(this.defaults, config);
|
||||||
|
if (isURL(config.url)) {
|
||||||
|
config.url = normalizeURL(config.url);
|
||||||
|
}
|
||||||
const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
|
const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
|
||||||
return buildURL(fullPath, config.params, config.paramsSerializer);
|
return buildURL(fullPath, config.params, config.paramsSerializer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,25 @@ import CanceledError from '../cancel/CanceledError.js';
|
|||||||
import AxiosHeaders from '../core/AxiosHeaders.js';
|
import AxiosHeaders from '../core/AxiosHeaders.js';
|
||||||
import adapters from '../adapters/adapters.js';
|
import adapters from '../adapters/adapters.js';
|
||||||
|
|
||||||
|
const { toString } = Object.prototype;
|
||||||
|
|
||||||
|
const isURL = (url) => {
|
||||||
|
if (url === null || typeof url !== 'object') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prototype = Object.getPrototypeOf(url);
|
||||||
|
return prototype !== null && prototype !== Object.prototype && toString.call(url) === '[object URL]';
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizeURL = (url) => (isURL(url) ? url.toString() : url);
|
||||||
|
|
||||||
|
function normalizeConfigURL(config) {
|
||||||
|
if (isURL(config.url)) {
|
||||||
|
config.url = normalizeURL(config.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws a `CanceledError` if cancellation has been requested.
|
* Throws a `CanceledError` if cancellation has been requested.
|
||||||
*
|
*
|
||||||
@@ -32,6 +51,8 @@ function throwIfCancellationRequested(config) {
|
|||||||
* @returns {Promise} The Promise to be fulfilled
|
* @returns {Promise} The Promise to be fulfilled
|
||||||
*/
|
*/
|
||||||
export default function dispatchRequest(config) {
|
export default function dispatchRequest(config) {
|
||||||
|
normalizeConfigURL(config);
|
||||||
|
|
||||||
throwIfCancellationRequested(config);
|
throwIfCancellationRequested(config);
|
||||||
|
|
||||||
config.headers = AxiosHeaders.from(config.headers);
|
config.headers = AxiosHeaders.from(config.headers);
|
||||||
@@ -43,6 +64,8 @@ export default function dispatchRequest(config) {
|
|||||||
config.headers.setContentType('application/x-www-form-urlencoded', false);
|
config.headers.setContentType('application/x-www-form-urlencoded', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normalizeConfigURL(config);
|
||||||
|
|
||||||
const adapter = adapters.getAdapter(config.adapter || defaults.adapter, config);
|
const adapter = adapters.getAdapter(config.adapter || defaults.adapter, config);
|
||||||
|
|
||||||
return adapter(config).then(
|
return adapter(config).then(
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ export function encode(val) {
|
|||||||
* @returns {string} The formatted url
|
* @returns {string} The formatted url
|
||||||
*/
|
*/
|
||||||
export default function buildURL(url, params, options) {
|
export default function buildURL(url, params, options) {
|
||||||
|
// Safeguard for direct callers (e.g. via ./unsafe/helpers/buildURL.js): coerce URL-like
|
||||||
|
// objects to strings before using string methods below.
|
||||||
|
if (url !== null && typeof url === 'object' && typeof url.toString === 'function') {
|
||||||
|
url = url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
if (!params) {
|
if (!params) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3116,6 +3116,46 @@ describe('supports http with nodejs', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support URL object with params', async () => {
|
||||||
|
const server = await startHTTPServer(
|
||||||
|
(req, res) => {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.end(JSON.stringify({ url: req.url }));
|
||||||
|
},
|
||||||
|
{ port: SERVER_PORT }
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = new URL(`http://localhost:${server.address().port}/foo?a=1`);
|
||||||
|
const response = await axios.get(url, { params: { b: '2' } });
|
||||||
|
|
||||||
|
assert.strictEqual(response.status, 200);
|
||||||
|
assert.strictEqual(response.data.url, '/foo?a=1&b=2');
|
||||||
|
} finally {
|
||||||
|
await stopHTTPServer(server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support URL object without params (no crash)', async () => {
|
||||||
|
const server = await startHTTPServer(
|
||||||
|
(req, res) => {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.end(JSON.stringify({ url: req.url }));
|
||||||
|
},
|
||||||
|
{ port: SERVER_PORT }
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = new URL(`http://localhost:${server.address().port}/foo`);
|
||||||
|
const response = await axios.get(url);
|
||||||
|
|
||||||
|
assert.strictEqual(response.status, 200);
|
||||||
|
assert.strictEqual(response.data.url, '/foo');
|
||||||
|
} finally {
|
||||||
|
await stopHTTPServer(server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should support HTTP protocol', async () => {
|
it('should support HTTP protocol', async () => {
|
||||||
const server = await startHTTPServer(
|
const server = await startHTTPServer(
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
|
|||||||
@@ -35,6 +35,94 @@ describe('static api', () => {
|
|||||||
await promise;
|
await promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support URL object shorthand with config', async () => {
|
||||||
|
const url = new URL('http://example.com/test?a=1');
|
||||||
|
|
||||||
|
const response = await axios(url, {
|
||||||
|
params: {
|
||||||
|
b: 2,
|
||||||
|
},
|
||||||
|
adapter: (config) =>
|
||||||
|
Promise.resolve({
|
||||||
|
data: null,
|
||||||
|
status: 200,
|
||||||
|
statusText: 'OK',
|
||||||
|
headers: {},
|
||||||
|
config,
|
||||||
|
request: {},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(response.config.url, url.toString());
|
||||||
|
assert.deepStrictEqual(response.config.params, { b: 2 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not require global URL to be a constructor for string requests', async () => {
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'URL');
|
||||||
|
|
||||||
|
Object.defineProperty(globalThis, 'URL', {
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios('/test', {
|
||||||
|
adapter: (config) =>
|
||||||
|
Promise.resolve({
|
||||||
|
data: null,
|
||||||
|
status: 200,
|
||||||
|
statusText: 'OK',
|
||||||
|
headers: {},
|
||||||
|
config,
|
||||||
|
request: {},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(response.config.url, '/test');
|
||||||
|
} finally {
|
||||||
|
if (descriptor) {
|
||||||
|
Object.defineProperty(globalThis, 'URL', descriptor);
|
||||||
|
} else {
|
||||||
|
delete globalThis.URL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should normalize URL object set by a request interceptor before dispatch', async () => {
|
||||||
|
const url = new URL('http://example.com/interceptor');
|
||||||
|
let transformUrl;
|
||||||
|
const interceptorId = axios.interceptors.request.use((config) => {
|
||||||
|
config.url = url;
|
||||||
|
return config;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios('/test', {
|
||||||
|
transformRequest: [
|
||||||
|
function (data) {
|
||||||
|
transformUrl = this.url;
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
adapter: (config) =>
|
||||||
|
Promise.resolve({
|
||||||
|
data: null,
|
||||||
|
status: 200,
|
||||||
|
statusText: 'OK',
|
||||||
|
headers: {},
|
||||||
|
config,
|
||||||
|
request: {},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(transformUrl, url.toString());
|
||||||
|
assert.strictEqual(response.config.url, url.toString());
|
||||||
|
} finally {
|
||||||
|
axios.interceptors.request.eject(interceptorId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should have defaults', () => {
|
it('should have defaults', () => {
|
||||||
assert.strictEqual(typeof axios.defaults, 'object');
|
assert.strictEqual(typeof axios.defaults, 'object');
|
||||||
assert.strictEqual(typeof axios.defaults.headers, 'object');
|
assert.strictEqual(typeof axios.defaults.headers, 'object');
|
||||||
@@ -69,6 +157,16 @@ describe('static api', () => {
|
|||||||
assert.strictEqual(typeof axios.getUri, 'function');
|
assert.strictEqual(typeof axios.getUri, 'function');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support URL object config in getUri', () => {
|
||||||
|
const url = new URL('https://api.example.com/foo');
|
||||||
|
|
||||||
|
assert.strictEqual(axios.getUri({ url }), url.toString());
|
||||||
|
assert.strictEqual(
|
||||||
|
axios.getUri({ baseURL: 'https://example.com/base', url }),
|
||||||
|
url.toString()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should have isAxiosError properties', () => {
|
it('should have isAxiosError properties', () => {
|
||||||
assert.strictEqual(typeof axios.isAxiosError, 'function');
|
assert.strictEqual(typeof axios.isAxiosError, 'function');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -101,6 +101,51 @@ describe('helpers::buildURL', () => {
|
|||||||
expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz');
|
expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support URL object without params', () => {
|
||||||
|
const url = new URL('http://example.com/foo?a=1');
|
||||||
|
expect(buildURL(url)).toEqual('http://example.com/foo?a=1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support URL object with params', () => {
|
||||||
|
const url = new URL('http://example.com/foo?a=1');
|
||||||
|
expect(buildURL(url, { b: 2 })).toEqual('http://example.com/foo?a=1&b=2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support URL-like object with params', () => {
|
||||||
|
const url = {
|
||||||
|
toString() {
|
||||||
|
return 'http://example.com/foo?a=1';
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(buildURL(url, { b: 2 })).toEqual('http://example.com/foo?a=1&b=2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not require global URL to be a constructor', () => {
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'URL');
|
||||||
|
const url = {
|
||||||
|
toString() {
|
||||||
|
return 'http://example.com/foo?a=1';
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(globalThis, 'URL', {
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
expect(buildURL(url, { b: 2 })).toEqual('http://example.com/foo?a=1&b=2');
|
||||||
|
} finally {
|
||||||
|
if (descriptor) {
|
||||||
|
Object.defineProperty(globalThis, 'URL', descriptor);
|
||||||
|
} else {
|
||||||
|
delete globalThis.URL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should support custom serialize function', () => {
|
it('should support custom serialize function', () => {
|
||||||
const params = {
|
const params = {
|
||||||
x: 1,
|
x: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user