While working with axios to make POST requests, I encountered an interesting behavior. I am passing URLs entered by the user to my Spring RestController, which accepts the request body as a String. The code snippet looks like this:
@PostMapping("user/{userId}/link")
public ResponseEntity<UserLinkDTO> addUserLink(
@PathVariable(value = "userId") Integer userId, @RequestBody String url) {
...
}
On the front end, my axios request is structured as follows:
const saveUserLink = async (userId: number, url: string): Promise<UserLinkDTO> => {
return axiosInstance.post(`user/${userId}/link`, url))
.then(r => r.data)
);
When sending some random URLs (containing =
) such as:
https://www.google.com/search?client=firefox
https://www.yahoo.com/somePage?key=value&hello=world
The Spring POST method receives the url
exactly as it was sent.
However, when sending URLs without any =
, like:
https://www.google.com
https://www.yahoo.com/somePage
The Spring POST method receives the url
with an appended =
. This results in the links being received as:
https://www.google.com=
https://www.yahoo.com/somePage=
I noticed that these requests are being sent with
Content-Type: application/x-www-form-urlencoded
instead of the expected application/json
. According to the axios documentation, all requests should be serialized to JSON and sent with Content-Type: application/json
. Interestingly, only this specific request is being converted to Content-Type: application/x-www-form-urlencoded
.
To resolve this issue, I added custom headers to my axios post request to change the Content-Type
back to application/json
:
const saveUserLink = async (userId: number, url: string): Promise<UserLinkDTO> => {
return axiosInstance.post(`user/${userId}/link`, url, {
headers: {
'Content-Type': 'application/json',
}
})
.then(r => r.data)
);
As a result, my Spring POST method now successfully receives the URLs without any extra =
appended, regardless of their content. This adjustment resolves the issue and ensures consistent handling of URLs by the API.
This experience raises the question: why does axios change the Content-Type
from application/json
to
application/x-www-form-urlencoded
when providing a string as the request body?