Axios: Content-Type application/x-www-form-urlencoded

Created on 28 Jun 2016  ·  220Comments  ·  Source: axios/axios

Try to send request with content type application/x-www-form-urlencoded

var data = Querystring.stringify({ 
                "grant_type": "password",
                "username": login,
                "password": password
            });
axios.post(Urls.login, data);

but there is no such header in request.

I tried to use code:

  var data = Querystring.stringify({ 
                "grant_type": "password",
                "username": login,
                "password": password
            });
        return axios({
            method: 'post',
            url: Urls.login,
            data: data,
            headers: {
                'Content-type': 'application/x-www-form-urlencoded'
            }
        });

same problem

jquery code works fine:

$.ajax({
            url: Urls.login,
            data: data,
            type: "POST",
            headers: {
                'Content-type': 'application/x-www-form-urlencoded'
            }
        });

How can I use axios to send request with this header?

Most helpful comment

You can use a library like qs instead:

var qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 });

All 220 comments

That should work as you've shown. Sounds like a bug. I will look into it.

The cause is interceptors. I can't send request with that Content-Type only when I use interceptors.

Here is my code:

axios.interceptors.request.use(function (config) {
        var token = LoginStore.getJwt();
        if (token) {
            config.headers["Authorization"] = "Bearer " + token;
        }

            return config;
        }, function (error) {    
            return Promise.reject(error);
        });

Inside interceptor I can see 'Content-Type' header, but it is not sent to the server.
Do I correctly use interceptors?

Any updates on this? I have the same issue. Axios doesn't send the header I set.

This seems to be the culprit line → https://github.com/mzabriskie/axios/blob/master/lib/adapters/xhr.js#L117

Any idea why the Content-Type header is removed before the request is sent?

A workaround option is to change your data to data || {} when you're making an axios request. This will make sure data is not undefined.

It looks like the logic for removing Content-Type when requestData is undefined came in this commit https://github.com/mzabriskie/axios/commit/9096d34186d5a5148f06c07854b21d6cc8035e96. There is no indication why it was added however.

I would vote if the requestData is undefined and method is PUT, POST or PATCH and no Content-Type has been set, then default Content-Type to application/x-www-form-urlencoded. Otherwise just honor whatever has been specified.

@mzabriskie But in the code snippet provided by @alborozd, the data is set to Querystring.stringify({...}), so requestData should not be undefined, right?

@mzabriskie I think you're right. When I use request interceptor fiddler shows that data is empty. Without interceptor I can see data and header and it works fine.

So, probably the problem occurs when you work with interceptors.

No interceptor is needed to crash this thing. I've set content type header defaults axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';, and i can't send any payload in POST body.

I've used workaround with URLSearchParams:

    var params = new URLSearchParams();
    params.append('email', email);
    return (dispatch) => {
        axios.post('/stack/' + uri, params)

But this is not supported by Safari and IE.

Edit: Okay :) Next update on workaround. Full supported workaround is send data as query string.
data: "flashcard=" + JSON.stringify(flashcard) + "&stackUri=" + stackUri. It hurts, but it works 👍

You can use a library like qs instead:

var qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 });

this is not a solution. What is difference if I will use "Querystring" or "qs" ? The problem is the header ['Content-Type'] = 'application/x-www-form-urlencoded' is empty because of interceptors.

Any updates here? Because i've lost 1h today on researching why my POSTs are not affecting API (til i reminded about that issue)... Or there are no plans to fix that and it's better to go somewhere else?

I have the same problem... still waiting for fix...

Please reopen @nickuraltsev as this is not fixed by your solution.

+1 for issue.

I use a interceptor with qs library to solve this problem. Works fine for me.

import qs from 'qs';

axios.interceptors.request.use((request) => {
  if (request.data && request.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
      request.data = qs.stringify(request.data);
  }
  return request;
});

+1 for issue.

hyanmandian commented 14 hours ago
I use a interceptor with qs library to solve this problem. Works fine for me.

Great, but it is not a way to solve issue in libraries IMHO by installing another.

You can just add a data: {} to the config, so the interceptor doesn't skip the headers which we specify.

This is what I did, and it worked for me:

import request from 'axios'

export const playSound = (soundFile) => (dispatch) => {
    dispatch(playSoundPending());
    return request
    .get(`/play/audio/${soundFile}`, { headers: {'Content-Type': 'audio/x-wav'}, data: {} })
    .then(response => response.data)
    });
};

This changed the Content-Type from application/json to audio/x-wav for me in the request headers in the network tab.

Has this been fixed yet? I can't seem to set my Content-Type with any of the solutions posted here.

I have same problem, any help?

I solved the problem using encodeURIComponent:

static getToken(username, password) {
return axios({
method: 'post',
url: 'endpoints',
data: Username=${**encodeURIComponent**(username)}& password=${**encodeURIComponent**(password)}& Grant_type=password
})

bump. One would definitely assume that if one sets defaults, they would be always be respected. Axios is definitely ignoring the defaults in certain contexts, causing issues for poor folks.

Here's a more specific merge where this happened: https://github.com/mzabriskie/axios/pull/195/files

+1 for this issue.
Spent over 3 hours trying to figure out what's wrong with my Tomcat config and apparently appears my headers were stolen on the way to the server. Workarounds did not help. God save the headers!

@polyakoff how did you solve for this?or are you still stuck. What I have observed is that this issue happens intermittently

@usopan Still stuck.

I moved to isomorphic-fetch for this particular request as a workaround.
Things seem to work OK on most browsers, but still not working on certain Safari versions.
I am begining to think that Safari is screwing me.

+1 for this issue.

I found the solution. Solution is to detect browser.
In Chrome use - https://github.com/ljharb/qs to parse json data to string and set Content-Type header
In Safari use - FormData as body and dont set any Content-Type header

Can't imagine how an issue like this does not get fixed for more than half a year already.

wow nice issue! still waiting for the update ☕️

it sucks.

it sucks + 1

+1

+1

+1

+1

+1

+1

+1

+1

+1

const querystring = require('querystring');

login(){
var _this = this;
this.$http({
url: url,
method: 'post',
data: querystring.stringify({
email: email,
password: pass
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
}

+1

+1

+1

so to summarise this any requests sent with Content-Type: application/x-www-form-urlencoded is:

  • Not encoding the payload automatically
  • Not setting the header even tho it has been specified

The workaround, for now, set the data: {} so the header get set, and encode manually the request data payload

I'm sharing my code:

import qs from 'qs'
...

const instance = axios.create({
  baseURL: config.api.host,
  responseType: config.api.responseType,
  timeout: config.api.timeout,
  data: {},
})

instance.interceptors.request.use((req) => {
  if (req.method === 'post') {
    req.headers['Content-Type'] = config.api.defaults.postContentType
    req.data = qs.stringify(req.data)
  }

  return req
}, (error) => Promise.reject(error))

This seems to work for me

Hello guys! I am wondering, should i make a fork and provide solution with small native query-parsing method? Will it be good 'pattern' for creators? @mzabriskie Would you like to integrate such a thing?

spend more than 3 hours to get in to this issue .. @Maxwell2022 can u please code with some sample data ?

+1

1

+1

@bsjaffer I've posted the code sample, what else do you want?

@Maxwell2022 i am good with it now.

+1

+1

+1

+1

+1

+1

+1

++1

Just do this, hope it helps.

let details = {
      key1: 'data1',
      key2: `data2`,
      key3: `data3`,
    };

    var formBody = [];
    for (var property in details) {
      var encodedKey = encodeURIComponent(property);
      var encodedValue = encodeURIComponent(details[property]);
      formBody.push(encodedKey + "=" + encodedValue);
    }
    formBody = formBody.join("&");

    const URL = `PUT-YOUR-API-URL-OVER-HERE`;
    return axios({
      method: 'POST',
      url: URL,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      data: formBody,
    })
    .then(res => res.data)
    .catch(error => { throw error });

+1

Yup, you guessed it, +1

+1

+1

+1, reznord's solution did the magic ( setting data alongside headers ):
const config = { headers: { 'Content-Type': 'multipart/form-data' }, data: {} };

@bruddah cool, glad it worked.

_Sent from my OnePlus ONEPLUS A3003 using FastHub_

+1

Using qs work for me!

In React, this worked for me:

import axios from 'axios';
import querystring from 'querystring';

const data = querystring.stringify({id:32, name:'john'});
axios.post('http://example.com/posturl', data)

The reason for this is that axios is not automatically encoding post data before adding it to the body of the HTTP request, so it needs to be encoded before sending the request. That's what query string does. It takes {id:32, name:'john'} and produces something like id=32&name=john and then axios sets that as the body of the post request.

You can test this by making the following request:

axios.post('http://example.com/posturl', 'id=32&name=john')

That should have the same result as the code above.

still not fixed more than a year since this opened....

+1

+1

Hey guys! You can try this, it works fine for me,but i don't know why.

get (url, data) {
    return axios({
      method: 'get',
      url: url,
      baseURL: 'http://xxxxx/api',
      timeout: 10000,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      },//this is important !
      data: data,//this is important !
      params: data//this is important !
    }).then(
      (response) => {
        console.log(response)
        return checkStatus(response)
      }
    )
  }

Trying to send _Content-Type:application/json-patch+json_ in a Patch request (following RFC6902),
the following worked for me (I have the right type in the request headers):

axios.patch(
          url,
          data,
          { headers: { 'Content-Type': 'application/json-patch+json;charset=UTF-8' } }  
          ))

For those having this issue because of the interceptor overwriting the headers just use in your interceptor:

config.header['yourheader'] = value;

instead of

config.header = {'yourheader': value}

@DavidJiang7 solution should work

This works for me:

static register(token, email, lang)
{
        let config = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }; // we do it to send SIMPLE post eequest (to avoid send CORS OPTIONS request before post)
        let params = new URLSearchParams(); // and we cannot send json but params are transform to  url-style
        params.append('email', email);
        params.append('lang', lang);

        return axios.post(ENV.API_URL + '/device/' + token + '/register', params, config);
}

Interesting picture showing CORS cases HERE. The OPTIONS request will be not send when we send SIMPLE request. Simple request is request which is GET, HEAD, POST and has header 'content-type' equal to application/x-www-form-urlencoded, multipart/form-data, or text/plain and any custom headers.

Just do this

const data = {name: 'my name'}
const form = 'data=' + JSON.stringify(data)
axios.post('/my_url', form)

Edited
sorry about the typo. and it works for me I've been using this for months.
I forgot to mention that in the server you have only the data param

...
 $data = json_decode($_POST['data'], 1);
 echo $data['name']; // my name
...

bump for a clean solution, willing to help as well.

@jesusantguerrero
Just do this

const data = {name: 'my name'}
const form = 'data=' + JSON.stringfy(data)
axios.post('/my_url', form)

doesn't work, but its JSON.stringify ^^typo above.

For those of you using Node.js, this works. Thanks everyone in the thread I basically combined a bunch of peoples solutions and references the Node.js docs

This is the cleanest I could come up with.

import { URLSearchParams } from 'url';

async function auth() {
  try {
    const config = {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    };
    const params = new URLSearchParams();
    params.append('grant_type', 'client_credentials');
    params.append('client_id', configuration.yelpClientId);
    params.append('client_secret', configuration.yelpClientSecret);

    const { data } = await axios.post(
      YELP_AUTH_ENDPOINT,
      params.toString(),
      config,
    );

    return data;
  } catch (error) {
    console.log(error.response.data);
    return {};
  }
}

use params instead of data

axios({
    method: 'post',
    url: '/my/api',
    headers: {
        'Content-type': 'application/x-www-form-urlencoded'
    },
    params: {
        'grant_type': 'code',
        'client_id': '1231453',
        'client_secret': 'THIS_IS_THE_SECRET'
    }
})
    .then((response) => {
        console.log(response);
    })
    .catch((error) => {
        console.log(error);
    }
);

@skuarch
use params instead of data

If that works, its the cleanest solution by far.

@oshalygin it sets the params to the query string, doesn't send as post variables.

An ajax library that can't post a simple form? Really?

1

anyone know who to set content-type to application/json.

axios.post(`${DOMAIN}${url}`,params, {'headers': {"Content-Type": "application/json;charset=UTF-8"}})

it doesn't works.

@hellomrbigshot probably CORS problem (read about it, also in this thread)

The troublesome bit of code in Axios for me (having trouble getting the payload right without using URLSearchParams) appears to be

        if (utils.isURLSearchParams(data)) {
          setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
          return data.toString();
        }
        if (utils.isObject(data)) {
          setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
          return JSON.stringify(data);
        }
        return data;
      }

So if data is an object that isn't a URLSearchParam (or one of a few other types that are checked for prior to this - FormData is in the list and used raw) then it's going to be JSON.stringified and might cause the header to be set to application/json.
On the other hand, if I pass in a string then it's just used as-is, so adeelibr's Jul 4 comment is the one that works for me and my form data.

They should provide a default header type. I solved this problem by using this code.
this is my vue + axios code on client side

Vue.prototype.$http = axios;
new Vue({
    el: '#root',
    data: {
        site_url: params.site_url,
        name: '',
        description: ''
    },
    methods:{
        onSubmit(){
            var url = this.site_url + 'project/create';
            this.$http.post( url, {
                name: this.name,
                description: this.description
            } ).then(
                response => console.log(response.data)
            );
        }
    },
    mounted(){

    }
});```
Here this.$http means axios. I using axios instead of vue resource.


My Server Side Code

if ( isset( $_POST ) ) {
$fields_to_add = array( 'name', 'description' );
$response = json_decode(file_get_contents("php://input"), true);
foreach ( $response as $k => $v ) {
if( in_array($k, $fields_to_add) ){
$_POST[$k] = $v;
}
}
echo json_encode( $_POST );
exit();
} else{
echo json_encode( array( 'message' => 'Invalid Request' ) );
exit();
}
```

Put field names as list of fields name. It will auotmatically convert it into post
Hope this helps

+1

+1

+1

OMG 😱 I didn't know sending a POST request with some application/x-www-form-urlencoded form data is so complicated like this. I have to re-read the README many times, and wrong understanding that the config's data field could be used with qs.stringify(), also params field.

At the moment, it seems that only instance methods support sending x-www-form-urlencoded form data such as:

  • axios#post(url[, data[, config]])
  • axios#put(url[, data[, config]])
  • axios#patch(url[, data[, config]])

+1

not solved!

It's open like... forever. The old request lib used to make it so simple.

+1

+1

+1

Here is an easy way to do this.
First of all, please read here : https://github.com/axios/axios#using-applicationx-www-form-urlencoded-format

Here is a fix :

  1. Go to : https://github.com/WebReflection/url-search-params

  2. You can npm install it or simply download the library from here : https://github.com/WebReflection/url-search-params/blob/master/build/url-search-params.js

  3. If you have downloaded the library, simply include it in your file.

//For e.g. in your index.html, 
<script src="url-search-params.js"></script>
  1. Then make a POST request like this :
var params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params)
.then(function (response)
                {
                    console.log(response.data);
                })
                .catch(function (error)
                {
                    console.log(error);
                });

It will work like a charm! :+1:

@aditya43 Thank You!

You can actually do this as well. This comes straight from the axios Github Page. You will have to create the encoded URL yourself, but I just tested it, and it works.

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

This bug still exists, any update?

@DZuz14 I try it and doesn't work. Using the axios globals, per instance, and nothing.
It appear to be hardcoded.

+1

axios sucks , use request for replacement

+1

It is working!

https://www.npmjs.com/package/form-data-urlencoded

import getFormData from 'form-data-urlencoded';

let data = getFormData({"_csrf": 'wrwrwrvwg4657rhed4hehe4',
                            "Res1[Test1]": "segf96767", 
                            "Res2[Test2]": "hello"});
let options = {
     method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
    url: 'http://fhfhfhfh/455454545/fhfhfhf',
    data
};

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
axios(options).then(function (response) {
              console.log(response);
    }).catch(function (error) {
             console.log(error);
        });

I defined the charset (UTF-8) in the "Content-Type" and I modified the above "interceptors" solution.
Finally it works.

import axios from 'axios'
import qs from 'qs'

axios.interceptors.request.use((request) => {
  if (request.data && (request.headers['Content-Type'].indexOf('application/x-www-form-urlencoded') !== -1)) {
    request.data = qs.stringify(request.data)
  }
  return request
})

axios({
  method: 'POST',
  url,
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  data
}).then(() => {
// DO SOMETHING
})

I found only cors cases, the failure of sending options request headers set cross-domain failure, behind the operation will not be implemented.

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

I started with axios, as one of my colleagues recommended it to me, and the first endeavor for me was to get the access token from a working API. and I collide with this bug, and then I returned to jQuery, (honestly, I heat jQuery so much, but it was forced to do that). So I think there is no better way to make people flee from this library than this old, unsolved bug.

I appreciate all the work done in this library, as a developer I know creating a library is not a trivial task, and I hope to let the jQuery down one day and come back to here again.

@HakamFostok I am successfully using github/fetch in production for getting api token you could explore that as an alternative to jquery.
https://github.com/github/fetch

@usopan thank you very much, I will take a look at it

@HakamFostok
The easiest way to get past this error is to use QS. You do not have to install qs just use it directly with qs.stringify

let qs = require('qs');
let result = await axios.post(url,
    qs.stringify({
        refresh_token: refresh_token,
        grant_type: 'refresh_token'
    }),
    {
        headers: {
            "Content-Type": "application/json"
        },
        auth: {
            username: 'username',
            password: 'secret'
        }
    });

With that you can use axios which ist much better with ES6 ;)

But you are completely right. This Bug should have been solved ages ago. Don't know what is taking them so long.

@HakamFostok @Silve2611 I confirm the qs workaround works, I use it to obtain tokens here: https://github.com/Halceyon/aspnet-auth/blob/master/src/AspnetAuth.js

Yes, the 'qs' work around is working, BUT, the problem is that I do not use 'qs' in the project. thanks for the help anyway, I ended up with throwing this library and use the ajax library https://github.com/fdaciuk/ajax it is much better, and I encourage everyone to rid this library off and migrate to there.

qs is downloaded almost 60 million times a month, it is 4.8Kb gzipped.
Express, body-parser, request, superagent and many others depend on it, you can add it without fear to your project.

@HakamFostok As far as i know it is part of the core module so you don't have to install it manually if your node version is up to date.

I just do not want to install any library, which I do not need, just to create a workaround for a problem which should be solved from many years ago. Just for your information, My project is not React project nor I use node, I am using ASP.NET MVC with vue.js

"querystring" module is built in, and as far as I know, it does the same.

@axios What about this bug that persists?

@HakamFostok I am also using vue and it really works perfectly with axios. Consider using qs because axios has a lot of advantages if you want to use async await.

The issue still happend and I have to manual use qs like this

axios.post(
      "connect/token",
      qs.stringify({
        username: this.state.username,
        password: this.state.password,
        grant_type: "password",
        scope: "offline_access"
      })
    );

Is this really even a bug? I am doing url encoded in two different projects with axios, and it works just fine. The comment I posted here previously is the only thing I set, and it works.

Of course it is a bug! It does not work as described in the docs. Also it does not make sense to add the additional step for something that should clearly be handled by axios. Other methods do not need the step.

Yes, it not make sense when you have to add adition step.
If I want to post

headers: {
     'Content-type': 'application/x-www-form-urlencoded'
}

I have to write like this

axios.post(
      "connect/token",
      qs.stringify({
        username: this.state.username,
        password: this.state.password,
        grant_type: "password",
        scope: "offline_access"
      })
    );

I had the same issue with setting Content-Type to application/vnd.api+json, similar to #340, which was unfortunately closed without resolution.

My workaround was to stringify the object data in order to send the Content-Type, which is a bit hacky, since we'd have to deal with axios way of setting application/json;charset=utf-8 when dealing it is with an object data.

Hope we'd have more capability in manually setting the Content-Type rather than have axios "guess" it for us.

It should „guess“ it for us or throw an error that we can handle. At the moment everything looks fine but the parans are obviously not correcf. A beginner working with axios will not be able to trace down such an error. At least it should be documented correctly.

+1 Just spent 2 hours tracking this issue down. Would have appreciated a better explanation/note in the readme at the very least. Will update if qs solves the problem.

UPDATE: Using react, qs worked for me. This was my solution. I needed both form parameters and a query parameter in my case.

var data = qs.stringify({
    id: 'MY_ID',
    action: 'MY_DATA'
});
var params = {
  params: {
    token: 'MY_TOKEN'
  }
};
axios.post('MY_URL', data, params)
    .then(function (response) {
      console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    });

I needed to use Axios with React to perform a login process and after struggling for hours with this problem the solution was to create independently the objects required to make the request.

The error was: unsupported_grant_type

This work.

import axios from 'axios';
import qs from 'qs' ;

const endPoint = `${endPointApi}/ControllerX`;  

const data = qs.stringify({ 
    grant_type: 'password',            
    user: userName, 
    password: userPass
});

const headers = {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
};

axios.post(endPoint, data, headers)
.then(function (response) {
    debugger;
    console.log(response);
})
.catch(function (error) {
    debugger;
    console.log(error);
});

This other way doesn't work.

axios.post({
    url: endPoint, 
    data: data, 
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    }
})...

After 2 years and this bug is still not resolved

+1

+1

+1 there still has the problem

+1

+1
ping @mzabriskie @nickuraltsev

The issue on the nodejs side is that one of the dependencies, follow-redirects, is deleting the content-type header:

screenshot from 2018-05-15 17-17-46
https://github.com/olalonde/follow-redirects/blob/1b6340f83ad5596a0a38c16a7113692bd90301f2/index.js#L188-L192

+1 definitely running into the same issue here

+1

fix this finally not to use hacks as qs (but yes, qs works)

Hej

  1. maj 2018 23.31 skrev "Leonid Ershov" notifications@github.com:

fix this finally not to use hacks as qs


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/axios/axios/issues/362#issuecomment-390337824, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AJZ-B0lPoCseiT4WNhJFlHVUTBHbmo9Yks5tzz3FgaJpZM4JAIfw
.

Seem like this issue will not be fixed

It's starting to get ridiculous!

Not even a "f**k you, we will never fix this!" :/

+1

+1

It seems that some hero, fixed it and created a specific version "aaxios"
Allow setting of content-type
Didn't test it though, moved on to fetch

+1

+1

+1

+1

👍
as @camposjorge said we may see a fix (soon?) thanks to https://github.com/axios/axios/pull/1544

no fix?

+1

solved it! it's not a axios problem,just about cross origin

set { headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}}
and
just use transformRequest from axios options

transformRequest: [function (data) { return format(data) }],

format function used to parse {a:"a",b:"b"} to "a=a&b=b"

+1, and none of the above solutions worked

+1

Seems like a lot of people are still waiting for a fix for this issue, myself included - surely after all this time there must be some proposed solution to this.

fixed this issue with qs.stringify in react.

u just have to qs.stringify the data before passing it into axios.post

the problem is that by default the CSRF Token is register as a common header with Axios so
to solve this issue

1- replace these lines in bootstrap.js "

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
"
by this line "
window.axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
"
2- install qs module by npm click here

3- define const of qs like below :
const qs = require('qs');
4- use axios by defult like this :
axios.post('your link here ',qs.stringify({
'a1': 'b1',
'a2 ':'b2'
}))
.then(response => {

                     alert('ok');

                })
                .catch(error => alert(error));

With this I was able to submit a form using axios irrespective of the fact that the content-type cannot be changed on axios

```
const { fullname, email, password, phone } = this.state;
axios(url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
data: this.serialize({
name: fullname,
email: email,
password: password,
phone: phone
})
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error.response);
});

serialize = obj => {
let str = [];
for (let p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
};

Bump. Ridiculously, after years, this annoying bug is still not fixed.

Bump. Same issue here, fix required af.

@mzabriskie

Shouldn't this be closed as fixed?
Tested it with appropriate headers and they are getting correctly set in the request.
Headers in request
Setting headers here

form-urlencoded library help me to fix that (for temporary).

return preset.post("/app/BookingProc.do",formurlencoded(dat),{
        headers:{
            Cookie:session
        }
    }).then(response=>{
        return response
    })

@mzabriskie

Shouldn't this be closed as fixed?
Tested it with appropriate headers and they are getting correctly set in the request.
Headers in request
Setting headers here

no this cannot be closed!!!
Everybody is running into the problem and does not where to find the solution. It should work without setting headers or a standard header should be set.
If not an error should be thrown showing where the problem is.
Also the documentation has to be updated.

It is still broken!

Bump. This bug is still in its place and feels great!

bump

This bug still lives!

I also am experiencing this here bug.

still disgusting here

const axios = require('axios');
const qs = require('querystring');

axios.post(`${this.api}siteverify`, qs.stringify({
  secret: this.secret,
  response: recaptchaToken,
  remoteip: userIP,
}), {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
});

This works for me. I ripped it off from the app I'm currently developing, this part is for verifying google's recaptcha.

Still having the same problem...

Setting as default is not working:
axios.defaults.headers.common['Accept'] = 'application/json'; // working axios.defaults.headers.common['Content-Type'] = 'application/json;charset=UTF-8'; // NOT working

And also setting in request is not working:
axios.get(url, { headers: { 'Content-Type': 'application/json;charset=UTF-8' } })

@aaroninn this does not seem to be the same problem, please open a new issue if you think your problem is related to axios (which seems to be more related to a basic usage of vuex to me, but I can't be sure)

this thread is already full of +1, no need to gather other issues here

https://github.com/axios/axios/issues/362#issuecomment-229817415

@mzabriskie it seems that you're the author of the commit which introduced this issue, can't you do anything about it (if you don't even understand why you did it in the first place, you could/should revert it, right?)

thanks in advance

It's 2018! Which answer, above, should I not downvote?

Tell me again why we all love Axios?

This issue need a fix ? Or it's voluntary, i'm asking, it's opened since 2 years but no one fixed it. Is it voluntary and no need to be fix ?

@jeremycare I just create a PR for that problem... I think it's a really annoying "bug" and should be fixed. Especially it's really easy to fix this and get rid of that problem.

Guys, I think I understand why this ticket still open.
People who tell that it works for them now use "qs" module, those who tells it doesn't work use "querystring" module.
I see people aslo having problems with headers, this ticket so long to read everything and may be I understand not everything about issue in this ticket, but if somebody can't make requests with form data work, checkout this before trying other things:

Described everything here: https://github.com/axios/axios/issues/1894

It's disappointing to see a swap in of native fetch in browsers work instantly with the setting of Content-Type when Axios fails to set it. Interop between platforms was its biggest selling point for me.

I can see in the transformRequest method that the header is set but it never makes it to the actual request. I can't use the qs module as I'm simply sending a body of text.

To rephrase what I'm experiencing: I can't set a Content-Type header in the browser using axios as it's overwritten. I'm sending a string payload (no formdata), so the qs/querystring modules are not relevant for my case.

What can we do to fix this?

EDIT: For now I'm just going to use fetch when in browser, but this kind of negates the whole point to using axios for me. I'm ready and willing to test ideas if anyone has something I can try.

EDIT2: I've built my own library - cowl -to handle my requests in multiple environments (targeting Node/Browser/React-Native). It's by no means a replacement for axios and its wealth of features, but it does support all the basics.

Got the same issue. And if I set the key to anything else, it works, except for "Content-Type"! Please help!

I've actually had to create yet another messy hybrid app by using fetch in browsers and axios in node and within react-native. Seems funny that it's like this and not the other way around. Really hoping to see this tackled soon so I can remove my monkey-patch.

I think it's important to realise that this is definitely not only an issue with querystring.. My body content is just raw text with no parameters, yet I can't send it using axios with a Content-Type.

I tried using post, it works fine, default of post is json

I'm experiencing this bug right now... so there Is no solution for this after years? wow...

I created a PR that would fix the problem over two months ago... I don’t understand why it not get merged?!

I created a PR that would fix the problem over two months ago... I don’t understand why it not get merged?!

Keep in mind that no one has pushed anything since september last year, maybe they're searching for maintainers?. Also, I think you missed a test when I compare your PR with: https://github.com/axios/axios/pull/1544/files

@mzabriskie could you maybe take the responsibility to merge one of these PR's? As currently some software requires get requests to have a content-type set (RoR params for instance: https://guides.rubyonrails.org/api_app.html#using-actiondispatch-request). The solution specified in https://github.com/axios/axios/issues/362#issuecomment-229817415 seems like the proper way to go and it would most of all solve all the desperate hacks like using fetch for this specific use case.

I moved to got pagkage, since axios seems abandoned.

So Axios is officially unable to send requests with 'Content-Type': 'application/x-www-form-urlencoded' or does @ChBernat solution actually work?

Is there any workaround on this issue atm?

Is there any workaround on this issue atm?

Lookup a year up here and you will see plenty of workarounds... Though I would recommend, like others and myself included, move on from axios. It's abandoned...

Wow... they should just abandon the project at this point, I know I am. Almost 3 years since issue originally reported and now we're still trying to solve this thing? Unbelievable. I love open source so I'm not harboring any ill feelings for this project not have maintainers but... it's used by TONS of people so the least you could do is abandon it so we all know this project is dead/dying. Thanks.

@justintime4tea Do you have a new recommendation?

got

@kslr got or request seems like what everyone else has started migrating too. I'm trying to stick with Axios but I think it'll end up just coming down to me writing some abstraction layer over it so I can swap out the underlying HTTP request library and then if I use a different library which has a "built-in" HTTP client it uses, just let it do its thing.

I tried something like this and worked for me.
Maybe not the best solution but it can really help (i think), any suggestion, if this solution is horrible, is welcome.

const foo= yield qs.stringify({ 'grant_type' : 'yourGrantType', 'param' : param, 'param' : param }) const bar= yield axios.post('/baz', foo)

I have removed the header, and it seems like it has received well.

axios({
  url,
  method: 'POST',
  headers:{
    'Content-Type': 'application/json'
  },
  data: null, // important
})

I had two problems using RoR as backend.

My context:

I had a project using deprecated vue-resource and everything works ok without additional config. And now, I'm organizing the project's dependencies and replacing deprecated dependencies, so I replaced vue-resource with axios ;)...


But, we had some problems and below I will share what I do to solve these problems. Maybe help someone! So sorry if I haven't helped you as you expected

First problem, the problem is the same as this issue, I solved using:

axios.interceptors.request.use(config => {
  config.paramsSerializer = params => qs.stringify(params);
  return config;
});

Now, params like:

q: {
  search: "Something",
  sort: "asc",
}

will be transformed to:
http://xxxx/?q%5Bsearch%5D=something&q%5Bsort%5D=asc

this parsed will be:

q[search]: something
q[sort]: asc

Second problem, RoR is returning HTML response instead of JSON response:

This problem occurs because our backend must distinguish AJAX requests from other types of requests.

By default, vue-resource already set X-Requested-With header as expected. But, axios not. So, I had to define this key in the request header. My Axios global config was as follows in the end:

axios.interceptors.request.use(config => {
  config.paramsSerializer = params => qs.stringify(params);
  return config;
});
axios.defaults.headers.common['Accept'] = 'application/json';
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

===

If you use Rails as backend and no one of the solutions worked for you, let me know, maybe I help you =).

Am working on react-native and getting bad request 400 error when use this :
import * as qs from 'querystring';
axios.post(url,qs.stringify({
'first_name': 'deep',
'last_name': 'palotra',
}),{
headers : {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then((response)=>{
console.log('worked')
}).catch((error)=>{
console.log('error')
console.log(error)
})

so,how to resolve this problem?

any solution :(

Solved By qs

{ data: qs.stringify(bodyObject) }

Sad to see that so many people are confused in this issue. I have try my best to read those comments. But it seems to have involved many other problems.

Everyone, forgive me to close it. If someone can open a new issue to describe the problem clearly, that will be really big thanks to you.

Hey everyone,

I thought I'd chime in as I wasted almost a full working day of my life trying to solve this. This may help some partially, or completely so here's to hoping this is useful.

My reply stems from seeing various reasons why a POST was failing with Axios ranging from:

  1. 400 Bad Request
  2. Can't post with custom Headers (like this thread)
  3. Need to serialize/stringify the data/payload

I was facing the same issue as everyone in this thread with the Bad Request 400 when passing in custom headers to Axios in the config like this, and tried many of the responses here, like using qs.stringify(), setting data in the config to null or {} to no avail.

1) Note - Adding the .catch() block and logging the error like so really helped me because I was able to surface an error that wasn't so cryptic. I was able to use the message to debug and ultimately figure out the issue I was having.

2) It's important in the .then() block to return response.data, otherwise you'll run into this error:

Converting circular structure to JSON

Now my issue was the api POST body was not what the endpoint wanted, but I couldn't see it until I was able to log the error.

Further, I'm also using NestJS and the HttpService, which is a wrapper around Axios, and that further complicated the issue because the real error wasn't bubbling up in the catchError callback in my pipe.

So here is the solution for both pure Axios and NestJS.

Axios:

const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
return axios.post('https://some-made-up-endpoint, dataString, { headers })
.then(resp => resp.data)
.catch(error => {
this.logger.log('ERROR: ${JSON.stringify(error.response.data)}');
});

NestJS:

const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
return this.http.post('https://some-made-up-endpoint, dataString, { headers }).pipe(
map(response => response.data), // This is important otherwise - circular JSON error
catchError((error: any) => {
this.logger.error('[[[[ ERROR TRYING TO FETCH TOKEN: ${error.message} ]]]]');
return of()
})
).toPromise();

TLDR;

1) Add the .catch() block to properly log the real error, otherwise it's 400 Bad Request
2) Make sure your data signature matches what the API is expecting. This is part of the reason an error exists since a code 400 is a 'Bad Request'
3) Return the response.data in the .then() block if you're using Axios, or in a map operator if you're using NestJS or you'll get the Converting circular JSON error

Sorry for the long post and good luck everyone!

Cheers

Am working on react-native and getting bad request 400 error when use this :
import * as qs from 'querystring';
axios.post(url,qs.stringify({
'first_name': 'deep',
'last_name': 'palotra',
}),{
headers : {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then((response)=>{
console.log('worked')
}).catch((error)=>{
console.log('error')
console.log(error)
})

this work for me. with query stringfy thanks a lot.
you save my live

You can use a library like qs instead:

var qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 });

Your solution is working. Thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghprod picture ghprod  ·  3Comments

helmus picture helmus  ·  3Comments

jdpagley picture jdpagley  ·  3Comments

altruisticsoftware picture altruisticsoftware  ·  3Comments

Baoyx007 picture Baoyx007  ·  3Comments