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
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
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
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
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.
2
Answers
MDN explains pretty well how CORS works, what is a simple request and which requests need preflight
GET requests can not have a body – but they can have query parameters in the URL.
POST requests can have query parameters in the URL, too – but they also can have a body (optionally).
Even if you provide
data
to Axios – if the request is GET then Axios will not add a body to the XHR.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
(whichaxios
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
onaxios
will makeaxios
set theContent-Type
toapplication/json
.Cross-origin requests with
Content-Type: application/json
require a preflight request.XMLHttpRequest
won’t ignoreaxios
setting theContent-Type
but it will ignoreaxios
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.