can't receive monzo access token using axios - reactjs

I've been trying for the whole day to perform a post request using axios in react (I'm trying to get an access_token for a Monzo app). I've followed the instructions here and they work perfectly when trying them out with the httpie command line tool as illustrated on said instructions. However, when I try to use it from within my react app, things go awry. The post request in question using httpie is as follows:
http --form POST "https://api.monzo.com/oauth2/token" \
"grant_type=authorization_code" \
"client_id=my_client_id" \
"client_secret=my_client_secret" \
"redirect_uri=my_redirect_uri" \
"code=my_authorization_code"
and this works as expected and returns a JSON object containing my access_token.
The (problematic) axios command I've been using in my react app is:
axios.post(
"https://api.monzo.com/oauth2/token", {
grant_type: "authorization_code",
client_id: my_client_id,
client_secret: my_client_secret,
redirect_uri: my_redirect_uri,
code: my_authorization_code
})
The error message I'm getting is Failed to load resource: the server responded with a status of 400 ().
I found this very related question, which suggests I add a header specifying Content-Type: application/json so I changed my axios commands to:
axios({
method: "POST",
url: "https://api.monzo.com/oauth2/token",
data: JSON.stringify({
grant_type: "authorization_code",
client_id: my_client_id,
client_secret: my_client_secret,
redirect_uri: my_redirect_uri,
code: my_authorization_code
}),
headers: {
'Content-Type': 'application/json'
}
})
which, unfortunately, gives the exact same error.
Can anybody give me a few pointers on this? I'm very new to networking...thanks!

And as it usually happens with these things, I found the answer shortly after posting the question. Apparently, the 'Content-Type' needs to be sent as 'application/xxx-form-urlencoded' and the data to be transformed accordingly like so:
const queryString = require('query-string')
axios({
method: "POST",
url: "https://api.monzo.com/oauth2/token",
data: queryString.stringify({grant_type: ...}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})

Related

Post request in redux-saga not working, nothing seems to happen

I would like to make post request in redux-saga. My code looks like:
var formdata = new FormData();
formdata.append("points", "a,b");
formdata.append("pid", "someid");
formdata.append("tions", "cses");
formdata.append("exp", "cx");
const ans = yield call(fetch,
'http://localhost:8000/api',
{
method: "POST",
headers: { 'Authorization': 'Token tokenid',
"Content-Type": "application/json",},
body : formdata
});
In Postman it is working fine (selected form-data in body), but in saga, the POST request is not happening at all.
Please suggest where I am doing wrong?
The problem is with your Exceptions on server-side, When you are throwing an error the headers are not set. So what you should do is with CORS Errors only with 400 bad request react fetch request.
Update :- The 400 Bad request has gone away after I added "Content-Type": "application/x-www-form-urlencoded" in the headers and changed the body type accordingly
Example :-
fetch("api/xxx", {
body: "email=test#example.com&password=pw",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
method: "post",
}

Invalid input file upload api platform

I'm trying to upload a file using api platform file upload. I'm using React-redux with redux-saga to make this request, but the server keeps throwing bad request response.
Api platform documentation says the following for making the request:
This endpoint accepts standard multipart/form-data-encoded data, but
not JSON data. You will need to format your request accordingly.
My Saga:
I tried appending my uploaded file to formData and use that as body for my request.
let data = new FormData();
data.append("file", action.payload.file)
const fileResponse = yield call(
fetch,
`${api.url}/api/media_objects`,
{
method: 'POST',
mode: 'no-cors',
body: data,
headers: { 'content-type': 'multipart/form-data' }
}
);
return console.log(fileResponse);
This is the api platform example request for posting a new media object
curl -X POST
"https://api.myroute/api/media_objects" -H
"accept: application/ld+json" -H "Content-Type: multipart/form-data"
-F "file=#1.6b.jpg;type=image/jpeg"
Api platform keeps returning a 400 error, which refers to invalid input. Any idea how the valid input should look like?
For my media object entity I followed the api platform documentation, so it looks exactly the same as in the docs
Details matter
headers: { 'content-type': 'multipart/form-data' }
It should be
headers: { 'Content-Type': 'multipart/form-data' }
There is no 'content-type', only 'Content-Type' header is defined (RFC) and widely accpeted.
I had a very similar issue recently (I can't remember the exact error), with API Platform (and the MediaObject entity), and React - redux (but no redux-saga).
I was able to fix it by removing the header part of my request :
headers: { 'content-type': 'multipart/form-data' }
So my new request looked exactly like that in my case :
const formData = new FormData();
formData.append('file', file);
return fetch(id, {
method: 'POST',
body: formData
})
...
I don't really know why, but it did the trick. Maybe it is handled automatically since we send a FormData object.
Hope it can work for you too !

Reactjs POST request using axios [duplicate]

This question already has answers here:
Why is an OPTIONS request sent and can I disable it?
(15 answers)
Closed 4 years ago.
I am trying to call a POST request in ReactJs using Axios, but getting an error. Code:
const payload =
{
device_id: 'ASDACCAS',
device_type: 'Web',
device_version: '1.2',
device_user_id: 'ASDBADKKK1234AS'
}
axios({
method: 'post',
url: 'https://stageapi.myapi.com/v3_2/user/splash',
data: payload,
headers: {
'secret-key': 'mysecretkey',
'Content-Type': 'application/json'
},
})
But this is giving me error:
Failed to load https://stageapi.myapi.com/v3_2/user/splash: Response for preflight does not have HTTP ok status.
Kindly help me whats wrong here. I am new to ReactJS and moving from mobile app development environment. I have been on this for so long, tried every method for axios POST including by appending formdata to body. Still the same.
EDIT:
Also, I am not sure if its something related to CORS. I have installed the the CORS plugin in chrome. Are there any changes that I need to make in API side code? Which is written in php.
When you want to make a post request, you need to stringify body request like this:
axios({
method: 'post',
url: 'https://stageapi.myapi.com/v3_2/user/splash',
data: JSON.stringify(payload),
headers: {
secret-key': 'mysecretkey',
'Content-Type': 'application/json'
},
})
axios.post('https://stageapi.myapi.com/v3_2/user/splash',
payload,
headers: {
'secret-key': 'mysecretkey',
'Content-Type': 'application/json'
}
})
.then((response) => {
console.log(response.data);
});

ReactJS seems to turn POST requests into GET requests

I'm using React and the fetch API to do a POST request to a user authentication backend. I can do this POST request below with Postman, and I get the correct JWT back, but oddly - whenever I use the following code in React, the POST request somehow hits the server as a GET request.
Code in React:
return this.fetch('http://fakeURL.com/auth', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "email#email.com",
"password": "password",
})
}).then(res => {
this.setToken(res.token);
return Promise.resolve(res);
})
The logs show (first the pre-flight request):
Request URL: http://fakeURL.com/auth
Request Method: OPTIONS
Status Code: 200 OK
Referrer Policy: no-referrer-when-downgrade
And the actual request:
Request URL: http://fakeURL.com/auth
Request Method: GET
Status Code: 405 METHOD NOT ALLOWED
Referrer Policy: no-referrer-when-downgrade
Things I've tried:
Running the app both locally and in an AWS S3 bucket (with CORS configured to allow all methods, and from any origin)
Using Flask on our backend to enable CORS
Hitting our backend via Postman with the same API POST request (when we use Postman, the API request works as intended, as a POST that returns a token)
Hitting other URLs (e.g. http://httpbin.org/post) to see if my code can hit those endpoints with a POST rather than a GET... and those endpoints see GET requests as well (instead of the intended POST)
This is so confusing - what could possibly cause our POST request to go out as a GET request? I feel like we've eliminated every possibly cause outside of something weird happening in React. Thanks for the help!
npm install --save axios
on your auth page:
import axios from 'axios'
Modify your post so instead of using fetch:
login(emailValue, passwordValue) {
return axios({
url: `yourAuthURL`,
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
data: {
"email": emailValue,
"password": passwordValue,
}
}).then(res => {
console.log(res);
})
}

Making an axios POST request with multipart/form-data, via React Native Debugger

I am trying to upload a file from React Native to my server. However I am unable to set the 'Content-Type' header to multipart/form-data.
Here's my simple request:
axios({
uri: 'http://localhost:3000',
method: 'POST',
data: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data'
}
});
I am using the React Native Debugger to monitor Network requests.
When I see my Network request inside the Debugger, I see this:
'Content-Type': 'text/plain;charset=UTF-8'
and the Request Payload is simply [object Object]
User Agent:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) ReactNativeDebugger/0.7.13 Chrome/58.0.3029.110 Electron/1.7.9 Safari/537.36
If I am unable to do this with the React Native Debugger, can anyone suggest any steps to testing via Expo.
Using the latest version of Axios (0.17.1), you make an HTTP request with 'Content-Type': 'multipart/form-data' in the header as follows:
const formData = new FormData();
formData.append('action', 'ADD');
formData.append('param', 0);
formData.append('secondParam', 0);
formData.append('file', new Blob(['test payload'], {
type: 'text/csv',
}));
axios({
url: 'http://localhost:5000/api/hello',
method: 'POST',
data: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
});
Two things: I am using url, not uri. Also, please insert your own form data and url. Inspecting the request, which has been replied successfully, this is what I get for the request header:
After hours trying to make it work, I realized that a multipart/form-data needs a boundary that is generated dynamically depending on the amount of data that is being sent.
Here is the code that works for me:
const data = new FormData();
data.append('field_name', 'field_pictures');
data.append('files[file]', fs.createReadStream(filepath), filename);
const headers = {
'Content-Type': 'multipart/form-data',
'Authorization': 'here you can set your headers',
...data.getHeaders() // this line is the key
// you need to mix your headers with those generated by the form data
}
return axios.post(url, data, { headers });
You can do simply:
axios.defaults.headers.common['Content-Type'] = 'multipart/form-data; boundary=someArbitraryUniqueString';
It will set your headers for sure. However, I have been struggling with form data in React Native for a day and without success. After some experimental aproaches, I found out that everything works without debugger. I don't know why but with debugger, I have been sending empty body to the server.
What's more I didn't need to set headers as it is your question in this post.
According to #JMA answer,
import axios from 'axios';
export async function somefunction(data) {
const formData = new FormData(); // No imports needed
for(let key in userData) {
formData.append(key.toString(), data[key].toString())
}
return axios.post(`${ROUTE}`, formData, {
'Content-Type': 'multipart/form-data',
});
}
where: data is your payload to what you want to send. somefunction is function that send POST request to ROUTE.

Resources