axios icon indicating copy to clipboard operation
axios copied to clipboard

Inconsistencies on request configurations in documentation vs real world

Open notanengineercom opened this issue 3 years ago • 2 comments

Section/Content To Improve

https://github.com/axios/axios#request-config

Only the url is required. Requests will default to GET if method is not specified.

I don't know if it's lack of information on the documentation or a bug. But the conflict here is when you create an axios instance with a default url, data and / or method. When making a request on a custom axios instance with the mentioned default properties, the final request object doesn't include the url and data properties.

To reproduce

import axios from 'axios'

const instance = axios.create({
  method: 'POST',
  baseURL: 'https://httpbin.org/',
  url: '/anything',
  data: { foo: 'bar' }
})

const resp = await instance.request({ headers: { foo: 'bar' } })
// or
const resp = await instance({ headers: { foo: 'bar' } })

// throws with 405 -> method not allowed.
// url and data from the instance config get replaced with undefined in the final config object

final config before firing the request -> you can see that data and url are missing

{
  transitional: {
    silentJSONParsing: true,
    forcedJSONParsing: true,
    clarifyTimeoutError: false
  },
  adapter: [Function: httpAdapter],
  transformRequest: [ [Function: transformRequest] ],
  transformResponse: [ [Function: transformResponse] ],
  timeout: 0,
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',
  maxContentLength: -1,
  maxBodyLength: -1,
  validateStatus: [Function: validateStatus],
  headers: {
    common: { Accept: 'application/json, text/plain, */*' },
    delete: {},
    get: {},
    head: {},
    post: { 'Content-Type': 'application/x-www-form-urlencoded' },
    put: { 'Content-Type': 'application/x-www-form-urlencoded' },
    patch: { 'Content-Type': 'application/x-www-form-urlencoded' }
  },
  baseURL: 'https://httpbin.org/'
}

Suggested Improvement

The confusing aspect is that according to the documentation, only the url is a required property -> you wouldn't expect data being replaced by undefined.

Also stating that Requests will default to GET if method is not specified is confusing - I think that mentioning that the method on the default instance's config will be used if a method is not defined in the request configuration.

Additionally, I think that adjusting the typescript interfaces would help guiding the developer in these situations. For example (if sticking to current documentation -> url is required property of request config):

If the url property will always be ignored on the default config, and needs to be defined in the request config, url should be a required property in the AxiosRequestConfig interface, but should not be part of the .create config interface and should not be assignable via instance.defaults

export interface AxiosRequestConfig<D = any> {
  url: string; // Removed question mark to flag as required. 
  // Another option is to explicitly allow undefined
  url: string | undefined;
...

interface AxiosInstanceConfig<D = any> extends Omit<AxiosRequestConfig<D>, 'url'> {};

const instance = axios.create({
  method: 'POST',
  baseURL: 'https://httpbin.org/',
  url: '/anything', // 'url' does not exist in type 'AxiosInstanceConfig<any>'
  data: { foo: 'bar' }
})

A similar approach can be applied to data.

Relevant File(s)

[e.g. README.md]

I'd be more than happy to contribute for any changes, but I think that first some discussion is needed

notanengineercom avatar Oct 28 '21 12:10 notanengineercom