2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-17 19:21:29 +03:00

revert: "fix: support URL object as config.url input (#10866)" (#10874)

This reverts commit 847d89b436.
This commit is contained in:
Jay
2026-05-10 08:56:26 +02:00
committed by GitHub
parent 847d89b436
commit 34adfd90ef
9 changed files with 29 additions and 272 deletions
-9
View File
@@ -592,20 +592,11 @@ response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'));
##### 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
// Send a GET request (default method)
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
For convenience, aliases have been provided for all common request methods.
+13 -13
View File
@@ -176,53 +176,53 @@ declare class Axios {
config: axios.AxiosRequestConfig<D>
): Promise<R>;
get<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
delete<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
head<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
options<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
post<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
put<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
patch<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
postForm<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
putForm<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
patchForm<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
query<T = any, R = axios.AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: axios.AxiosRequestConfig<D>
): Promise<R>;
@@ -473,7 +473,7 @@ declare namespace axios {
type LookupAddress = string | LookupAddressEntry;
interface AxiosRequestConfig<D = any> {
url?: string | URL;
url?: string;
method?: Method | string;
baseURL?: string;
allowAbsoluteUrls?: boolean;
@@ -661,7 +661,7 @@ declare namespace axios {
interface AxiosInstance extends Axios {
<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: AxiosRequestConfig<D>
): Promise<R>;
Vendored
+13 -13
View File
@@ -364,7 +364,7 @@ export interface LookupAddressEntry {
export type LookupAddress = string | LookupAddressEntry;
export interface AxiosRequestConfig<D = any> {
url?: string | URL;
url?: string;
method?: StringLiteralsOrString<Method>;
baseURL?: string;
allowAbsoluteUrls?: boolean;
@@ -609,53 +609,53 @@ export class Axios {
getUri(config?: AxiosRequestConfig): string;
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
get<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: AxiosRequestConfig<D>
): Promise<R>;
delete<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: AxiosRequestConfig<D>
): Promise<R>;
head<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: AxiosRequestConfig<D>
): Promise<R>;
options<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
config?: AxiosRequestConfig<D>
): Promise<R>;
post<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: AxiosRequestConfig<D>
): Promise<R>;
put<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: AxiosRequestConfig<D>
): Promise<R>;
patch<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: AxiosRequestConfig<D>
): Promise<R>;
postForm<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: AxiosRequestConfig<D>
): Promise<R>;
putForm<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: AxiosRequestConfig<D>
): Promise<R>;
patchForm<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: AxiosRequestConfig<D>
): Promise<R>;
query<T = any, R = AxiosResponse<T>, D = any>(
url: string | URL,
url: string,
data?: D,
config?: AxiosRequestConfig<D>
): Promise<R>;
@@ -663,7 +663,7 @@ export class 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>(url: string | URL, config?: AxiosRequestConfig<D>): Promise<R>;
<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
create(config?: CreateAxiosDefaults): AxiosInstance;
defaults: Omit<AxiosDefaults, 'headers'> & {
+3 -25
View File
@@ -12,19 +12,6 @@ import transitionalDefaults from '../defaults/transitional.js';
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
*
@@ -44,7 +31,7 @@ class Axios {
/**
* Dispatch a request
*
* @param {String|URL|Object} configOrUrl The config specific for this request (merged with this.defaults)
* @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults)
* @param {?Object} config
*
* @returns {Promise} The Promise to be fulfilled
@@ -95,19 +82,13 @@ class Axios {
_request(configOrUrl, config) {
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
if (typeof configOrUrl === 'string' || isURL(configOrUrl)) {
if (typeof configOrUrl === 'string') {
config = config || {};
config.url = normalizeURL(configOrUrl);
config.url = configOrUrl;
} else {
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);
const { transitional, paramsSerializer, headers } = config;
@@ -251,9 +232,6 @@ class Axios {
getUri(config) {
config = mergeConfig(this.defaults, config);
if (isURL(config.url)) {
config.url = normalizeURL(config.url);
}
const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
return buildURL(fullPath, config.params, config.paramsSerializer);
}
-23
View File
@@ -7,25 +7,6 @@ import CanceledError from '../cancel/CanceledError.js';
import AxiosHeaders from '../core/AxiosHeaders.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.
*
@@ -51,8 +32,6 @@ function throwIfCancellationRequested(config) {
* @returns {Promise} The Promise to be fulfilled
*/
export default function dispatchRequest(config) {
normalizeConfigURL(config);
throwIfCancellationRequested(config);
config.headers = AxiosHeaders.from(config.headers);
@@ -64,8 +43,6 @@ export default function dispatchRequest(config) {
config.headers.setContentType('application/x-www-form-urlencoded', false);
}
normalizeConfigURL(config);
const adapter = adapters.getAdapter(config.adapter || defaults.adapter, config);
return adapter(config).then(
-6
View File
@@ -29,12 +29,6 @@ export function encode(val) {
* @returns {string} The formatted url
*/
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) {
return url;
}
-40
View File
@@ -3116,46 +3116,6 @@ 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 () => {
const server = await startHTTPServer(
(req, res) => {
-98
View File
@@ -35,94 +35,6 @@ describe('static api', () => {
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', () => {
assert.strictEqual(typeof axios.defaults, 'object');
assert.strictEqual(typeof axios.defaults.headers, 'object');
@@ -157,16 +69,6 @@ describe('static api', () => {
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', () => {
assert.strictEqual(typeof axios.isAxiosError, 'function');
});
-45
View File
@@ -101,51 +101,6 @@ describe('helpers::buildURL', () => {
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', () => {
const params = {
x: 1,