javascriptaxioscorsfetchpreflight

Fetch Api vs Axios Api


If i use fetch request to send API request from my react js front end and if i tried to put body in the fetch request. the browser will throw error saying

Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body

But if i use Axios instead of fetch API to make the get request, here there is data field instead of body of fetch API. and if put something in the data field and send the get request, browser does not throw error. but the server will not get anything in the body of request.Another strange behavior is that in this Axios get request with data field having value,browser also sends a CORS preflight request which is strange because this is a get request.

Using Axios

The following is the code to generate new access token using refresh token stored in httpOnly cookie.This is axios get request

Without Data Field

Code

    const response = (
      await axios.request<AuthType>({
        url: "http://192.168.1.34:4488/webadmin/generatenewaccesstoken",
        method: "GET",
        withCredentials: true,
      })
    ).data;

Browser Network Tab

No preflight for generateaccesstoken endpoint

With Data Field

If i change the axios get request to include data with empty object the browser will send a preflight for this axios request.

Code

    const response = (
      await axios.request<AuthType>({
        url: "http://192.168.1.34:4488/webadmin/generatenewaccesstoken",
        method: "GET",
        withCredentials: true,
        data:{}
      })

Browser Network Tab

the following image is the browser's network tab and you can see that preflight is sent even though the request method is still GET enter image description here

Using Fetch

without body field

Code

    let response = await (
      await fetch("http://192.168.1.34:4488/webadmin/generatenewaccesstoken", {
        method: "GET",
        credentials: "include",
      })
    ).json();

Browser Network Tab

enter image description here

With body field

Code

    let response = await (
      await fetch("http://192.168.1.34:4488/webadmin/generatenewaccesstoken", {
        method: "GET",
        credentials: "include",
        body: JSON.stringify({}),
      })
    ).json();

Browser Network Tab

enter image description here

when using axios,if we include data field in the get request, the browser sends preflight for the request even though request method is 'GET'. but when using fetch Api with method set to 'GET if we try to include the body field. the browser will send nothing. Also I'am using edge browser

From the above, I' am inferring that data of Axios is not just a abstraction of body of axios, there is a fundamental difference in these two. Can someone tell me if my inference is correct and explain the reason for this behavior .

P.S

Also if we change the above endpoint method type to 'POST'. and whatever we are using axios or fetch api. if we are sending the post request without body field in the case of fetch api or without data field in the case of axios, the preflight request will not be send. From articles and documentation i have read,what i understood was if the request is request other than 'GET' or 'OPTION' a preflight request will be send. but in this case preflight will not be send for just a 'POST' request, it should contain a body or data for the browser to send preflight.


Solution

  • You may not set a body on a GET request.

    If you try to do that with fetch then it will complain at you.

    If you try to do that with XMLHttpRequest (which axios is a wrapper around) then it will ignore your nonsense.


    When you set a body on an HTTP request, you need to specify the Content-Type of that body (unless you set it using a mechanism which from which it can be inferred).

    Passing an object to data on axios will make axios set the Content-Type to application/json.

    Cross-origin requests with Content-Type: application/json require a preflight request.

    XMLHttpRequest won't ignore axios setting the Content-Type but it will ignore axios setting the request body.

    This results in a preflighted request which, if successful, will make the real request with a content-type but no content in the body.