46

I'm testing out the Uber API on Postman, and I'm able to send a request with form data successfully. When I try to translate this request using Node.js and the axios library I get an error.

Here is what my Postman request looks like:

Postman POST request

The response I get is: { "error": "invalid_client" }

Here is what I'm doing in Node.js and axios:

var axios = require("axios");

const config = { headers: { 'Content-Type': 'multipart/form-data' } };

axios.post('https://login.uber.com/oauth/v2/token', {
  client_id: '***',
  client_secret: '***',
  grant_type: 'authorization_code',
  redirect_uri: 'http://localhost:8080/',
  code: '***'
}, config)
  .then(function(response) {
    console.log(response.data)
  })
  .catch(function(error) {
    console.log(error)
  })

When I do this, I get a 400 response.

I added the 'multipart/form-data' header because I filled out the form-data in the Postman request. Without the header I get the same result.

I'm expecting to get the same response I'm getting from Postman, is there something wrong with my config variable in the Node.js script?

Any help would be appreciated!

4
  • It seems you are sending an additional parameter in your API call.. When you send additional parameters you are tend to receive this Invalid Client error. Commented Jan 20, 2017 at 12:58
  • 1
    Have you tried passing the data using querystring.stringify? Like this: var querystring = require('querystring'); axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }); Commented Jan 20, 2017 at 13:08
  • @KingJulien wrapping the data in the querystring module didn't help me out this time... Commented Jan 20, 2017 at 17:48
  • @KingJulien This querystring.stringify worked for me. I was sending data in dict format rather than string Commented Dec 28, 2021 at 11:55

7 Answers 7

48

You might be able to use Content-Type: 'application/x-www-form-urlencoded'. I ran into a similar issue with https://login.microsoftonline.com where it was unable to handle incoming application/json.

var axios = require("axios");

axios({
  url: 'https://login.uber.com/oauth/v2/token',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  data: `client_id=${encodeURIComponent('**')}&client_secret=${encodeURIComponent('**')}&grant_type=authorization_code&redirect_uri=${encodeURIComponent('http://localhost:8080/')}&code=${encodeURIComponent('**')}`
})
.then(function(response) {
  console.log(response.data)
})
.catch(function(error) {
  console.log(error)
})

You could also use a function to handle the translation to formUrlEncoded like so

const formUrlEncoded = x =>
   Object.keys(x).reduce((p, c) => p + `&${c}=${encodeURIComponent(x[c])}`, '')

var axios = require("axios");

axios({
  url: 'https://login.uber.com/oauth/v2/token',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  data: formUrlEncoded({
     client_id: '***',
     client_secret: '***',
     grant_type: 'authorization_code',
     redirect_uri: 'http://localhost:8080/',
     code: '***' 
  })
})
.then(function(response) {
  console.log(response.data)
})
.catch(function(error) {
  console.log(error)
})
Sign up to request clarification or add additional context in comments.

2 Comments

'qs' npm package mentioned on another question can do the url encoding.
this is an outdated answer. these days axios supports sending multipart/form-data from Node.js by using one of the polyfills of FormData
20

Starting with Axios 1.3, you can send multipart/form-data data using FormData:

const axios = require('axios');

const form = new FormData();
form.append('my_field', 'my value');
form.append('my_other_field', 'my second value');

axios.post('http://example.com', form)

FormData is available on Node 17.6.0 (or newer), on older versions you'll have to use a polyfill such as form-data.

If you're using older versions of both Node and Axios, you have to set the Content-Type header yourself as well:

const axios = require('axios');
const FormData = require('form-data');
const form = new FormData();
axios.post('http://example.com', form, { headers: form.getHeaders() })

1 Comment

form-data is a dependency of Axios, so you should already have it installed.
8

To send data with Content-Type application/x-www-form-urlencoded, wrap your {} with new URLSearchParams(). Like this snippet:

const axios = require("axios");
axios
  .post("https://api.zipwhip.com/user/login", new URLSearchParams({
  username: "hello",
  password: "my-password",
}))
  .then((res) => console.log(res.data));


1 Comment

The question is about sending data as multipart/form-data, not application/x-www-form-urlencoded
7

As for 10 June 2017, axios library does not support posting form data in Node.js. Here is the issue on GitHub - https://github.com/mzabriskie/axios/issues/789

We had the similar problem and decided to switch to request library.

3 Comments

Is this still the issue because I can't post form data by setting data parameter, works fine with request
Yes, I think the issue wasn't fixed and they have closed the issue with the following comment: github.com/axios/axios/issues/789#issuecomment-568146899
the comment they closed the issue with describes how to do this (by posting a FormData object from the form-data package) not that they decided they won't fix it.
3

This use case is now clearly documented with multiple solutions in the axios docs: https://axios-http.com/docs/urlencoded#form-data

Comments

0

From the error it seems your client_id or client_secret is incorrect. Enable debugging and share the raw request/response (after filtering credentials out).

Comments

-5

It is not true! You can post data with axios using nodejs. I have done it. The problem is, if you use PHP on the server side, there is a pitfall you need to be aware of. Axios posts data in JSON format (Content-Type: application/json) PHP's standard $_POST array is not populated when this content type is used. So it will always be empty. In order to get post parameters sent via a json request, you need to use file_get_contents("http://php://input") .

A simple PHP script on the server side would be:

if($_SERVER['REQUEST_METHOD']==='POST' && empty($_POST)) {
 $_POST = json_decode(file_get_contents('http://php://input'));
}

Using this method you can avoid the formData dependency. You CAN post data directly from node.js.

1 Comment

What if posting form data is the only option you have. That is if you don't have access to the API? Please see @Reid Evans answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.