I am working on REST API.
From my end, everything seems to be fine. I've tried multiple libraries (AXIOS, request, fetch) in order to make a PUT call.
However, I keep on getting 429 or 400 as a response code.
Below is the implemented code
const fetch = require('node-fetch');
const date= new Date();
const bodyData = `{"fields":
{
"priority":{"name":"Blocker"},
"date":"${date}"
}
}`;
await fetch('url', {
method: 'PUT',
headers: {
'Authorization': `Basic ${Buffer.from('username:password').toString('base64')}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: bodyData
})
.then((response) => { console.log(response.data) }) //print the result
.catch((err) => {return res.json({'msg': "Something went wrong"})});
Observation:-
The 429 error should not appear if the structure of the fetch call is incorrect.
I am not sure If am missing something, could you guys help me please?
Related
it's me again.
I'm learning react native, for now im trying to upload a file, the api is already tested using postman and it does work so I wrote this code:
import * as DocumentPicker from 'expo-document-picker';
async login () {
let response = await DocumentPicker.getDocumentAsync({type: '*/*'})
const data = new FormData();
data.append('file', response)
// Fetch attempt ----------------------------------------
fetch("http://192.168.0.3:8000/api/file", {
method: "POST",
headers:{
"Content-Type": "application/x-www-form-urlencoded",
},
body: data
})
.then(response => response.json())
.then(response => {
console.log("upload succes", response);
})
.catch(error => {
console.log("upload error", error, JSON.stringify(error));
});
// Axios attempt ----------------------------------------
axios.post('http://192.168.0.3:8000/api/file', data, { headers:{ "Content-Type": "application/x-www-form-urlencoded"} } )
.then(res => {
console.log("goddaamittt wooork", res)
})
.catch(error => {
console.log("error", error, JSON.stringify(error))
});
}
When I remove the body and headers from that request it actually returns what the api should return when you try to POST to it without a 'file', some message "{'fileName': 'A file is required'}" but adding it to it I get a network error, the error I get when using fetch it:
upload error [TypeError: Network request failed] {"line":24646,"column":31,"sourceURL":"http://127.0.0.1:19001/node_modules/expo/AppEntry.bundle?platform=android&dev=true&minify=false&hot=false"}
when it reaches the axios attempt it says something like this:
[Unhandled promise rejection: TypeError: Network request failed]
I tried everything I knew, I need some help!
Idk if it is important but here is what DocumentPicker returns when I pick a file:
Object {
"name": "FB_IMG_1573232116651.jpg",
"size": 32482,
"type": "success",
"uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fjsonplaceholder-bcb4c1c6-b37d-4634-99a5-3410d9b8654e/DocumentPicker/db8d78dd-2587-40e4-aed9-656c36df29f4.jpg",
}
This is the error I get when I remove the body from the axios request
error [Error: Request failed with status code 400] {"config":{"transformRequest":{},"transformResponse":{},"headers":{"Accept":"application/json, text/plain, /"},"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"method":"post","url":"http://192.168.0.3:8000/api/file"},"response":{"data":{"message":"File is required"},"status":400,"headers":{"map":{"cache-control":"public, max-age=0","x-robots-tag":"noindex","x-debug-token-link":"http://192.168.0.3:8000/_profiler/54e68c","x-debug-token":"54e68c","link":"http://192.168.0.3:8000/api/docs.jsonld; rel=\"http://www.w3.org/ns/hydra/core#apiDocumentation\"","content-type":"application/json","x-powered-by":"PHP/7.2.4","connection":"close","date":"Fri, 08 Nov 2019 17:54:12 GMT","host":"192.168.0.3:8000"}},"config":{"transformRequest":{},"transformResponse":{},"headers":{"Accept":"application/json, text/plain, /"},"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"method":"post","url":"http://192.168.0.3:8000/api/file"},"request":{"url":"http://192.168.0.3:8000/api/file","credentials":"omit","headers":{"map":{"accept":"application/json, text/plain, /"}},"method":"POST","mode":null,"referrer":null,"_bodyText":""}},"line":178773,"column":26,"sourceURL":"http://127.0.0.1:19001/node_modules/expo/AppEntry.bundle?platform=android&dev=true&minify=false&hot=false"}
It was such a dump solution, it took me hours to find this:
When I get the file from DocumentPicker I had to add the type of the file because DocumentPicker return an odd type called "success", when I changed it to 'image/jpeg' it worked :D its not a solution at all because I will need to find a way to know what type of file is each file a user chooses, anyways, this code works c:
let response = await DocumentPicker.getDocumentAsync({type: 'image/jpeg'})
response.type = 'image/jpeg' // <- lasdfkasdfaslfkfsdkdsaf
const data = new FormData();
data.append('file', response);
axios.post('http://192.168.0.3:8000/api/file', data , {headers: { 'Content-type': 'application/x-www-form-urlencoded' }} )
.then(res => {
console.log("gooosh", res.data)
})
.catch(error => {
console.log("error", error, JSON.stringify(error))
});
you should try to modify the content-type to
fetch("http://192.168.0.3:8000/api/file", {
method: "POST",
headers:{
'Content-Type': 'multipart/form-data',
},
body: data
})
and for the form-url-urlencoded, the fetch is not supported. you have to push it by yourself.you can see this answer.
I am having an issue in using the fetch method in the componentDidMount method when an api call is redirecting and returning the response. Initial 302 response is trying to get processed in then method after fetch and throwing a JSON.parse: unexpected end of data at line 1 column 1 of the JSON data. Any suggestion on how I can solve this issue ?
componentDidMount(){
let config = {
method: 'GET',
mode: 'no-cors',
redirect:'follow',
cache: 'default',
headers: new Headers({
'Content-Type': 'application/json'
})
};
fetch("ACTUAL_URL",config)
.then(response => response.text())
.then( val => JSON.parse(val))
.then(response => {
this.setState({val:response.json()})
})
}
API CALL response
-302
- 200
fetch only rejects in case of network error . For other cases you have to use
the ok method
fetch("ACTUAL_URL",config)
.then(function(data){
if (!data.ok) {
throw Error(data);
}
}).then(response => response.text())
.then( val => JSON.parse(val))
.then(response => {
this.setState({val:response.json()})
}).catch(function(error){
// handle the 302 error here
})
I'm using fetch-mock to test my client action creators in cases where there is an async call being made to the BE.
While all get requests are working well I'm having hard time doing the same to post and put requests.
Attached here a code example that if works I believe that my actual code will work as well.
I'm using import fetchMock from 'fetch-mock' for mocking the response and require('isomorphic-fetch') directly to replace the default fetch
I added some comments but I do get a response with status 200 (if I change the mocked response status to 400 I get it as well. The problem is that res.json() resulted with undefined instead of the mocked result body.
Using JSON.stringify is something that I used after not being able to make it work without it.
const responseBody = {response: 'data from the server'};
fetchMock.once('http://test.url', {
status: 200,
body: JSON.stringify(responseBody),
statusText: 'OK',
headers: {'Content-Type': 'application/json'},
sendAsJson: false
}, {method: 'POST'});
fetch('http://test.url',
{
method: 'post',
body: JSON.stringify({data: 'Sent payload'}),
headers : {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then(function (res) {
expect(res.status).toEqual(200); // Pass
res.json();
})
.then(function (json) {
console.log(json); // print undefine
expect(json).toEqual(responseBody); // Fail expected value to equal: {"response": "data from the server"} Received: undefined
done();
})
Mocking GET requests is working just fine
I also tried using it with fetchMock.post but had no luck
Would also appreciate if someone knows how I can test the post request sent payload as well (can't see any reference for that in the documentation)
In your first then, you don't have an explicit return, with the keyword return
If you don't do a return, the next then doesn't know the value. That's why your json is undefined.
For example:
var myInit = { method: 'GET', mode: 'cors', cache: 'default' };
fetch('https://randomuser.me/api/',myInit)
.then(function(res) {
return res.json()
})
.then(function(r) {
console.log(r)
})
So, for you:
const responseBody = {response: 'data from the server'};
fetchMock.once('http://test.url', {
status: 200,
body: JSON.stringify(responseBody),
statusText: 'OK',
headers: {'Content-Type': 'application/json'},
sendAsJson: false
}, {method: 'POST'});
fetch('http://test.url',
{
method: 'post',
body: JSON.stringify({data: 'Sent payload'}),
headers : {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then(function (res) {
expect(res.status).toEqual(200); // Pass
return res.json(); // return here
})
.then(function (json) {
console.log(json); // print undefine
expect(json).toEqual(responseBody); // Fail expected value to equal: {"response": "data from the server"} Received: undefined
done();
})
I am having huge troubles getting my fetch POST calls to work on iOS. My standard Fetch calls work and the Fetch POST calls work fine on android but not iOS.
The error that comes up is "Possible Unhandled Promise Rejection (id: 0): Unexpected token < in JSON at position 0"
It actually saves the post data to my server but throws that error.
I tried debugging the network request using GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest; before the API call coupled with using CORS in my chrome debug tools. From there I can see that it is making two post calls one after the other. The first one has type "OPTIONS" while the second one has type "POST". It should probably be noted that the call works in the App while using CORS and the line of code above.
I'm very confused and have exhausted all avenues.
My code im using for refrence is as follows.
return fetch(url,{
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then((res) => res.json());
If JSON.stringify is not working, then try to use FormData.
import FormData from 'FormData';
var formData = new FormData();
formData.append('key1', 'value');
formData.append('key2', 'value');
let postData = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
}
fetch(api_url, postData)
.then((response) => response.json())
.then((responseJson) => { console.log('response:', responseJson); })
.catch((error) => { console.error(error); });
You use the following code for POST request in react native easily. You need to only
replace the parameter name and value and your URL only.
var details = {
'userName': 'test#gmail.com',
'password': 'Password!',
'grant_type': 'password'
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
fetch('http://identity.azurewebsites.net' + '/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formBody
}).
.then((response) => response.json())
.then((responseData) => {
console.log("Response:",responseData);
}).catch((error) => {
Alert.alert('problem while adding data');
})
.done();
I would guess the response you are receiving is in HTML. Try:
console.warn(xhr.responseText)
Then look at the response.
Also, IOS requires HTTPS.
Edit: Possible duplicate: "SyntaxError: Unexpected token < in JSON at position 0" in React App
Here is an example with date that works for me!
The trick was the "=" equal and "&" sign and has to be in a string format in the body object.
Find a way to create that string and pass it to the body.
====================================
fetch('/auth/newdate/', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
body: "start="+start.toLocaleString()+"&end="+end.toLocaleString()+"",
headers: new Headers({
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
})
}).then(function(response) {
/* handle response */
if(response.ok) {
response.json().then(function(json) {
let releasedate = json;
//sucess do something with places
console.log(releasedate);
});
} else {
console.log('Network failed with response ' + response.status + ': ' + response.statusText);
}
}).catch(function(resp){ console.log(resp) });
server node.js?
npm i cors --save
var cors = require('cors');
app.use(cors());
res.header("Access-Control-Allow-Origin: *");
I'm starting to learn react-native and ran into some problems while using fetch on Android.
try {
let response = await fetch(REQUEST_URL, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
***parameters***
})
});
let responseJson = await response;
if(responseJson){
// console.log(responseJson);
console.log(responseJson.text());
// console.log(responseJson.json());
}
} catch(error) {
console.error(error);
}
The request is sent correctly but the answer isn't shown in it's totality:
(**loads more data before**){"ID":"779","DESCRICAO":"ZXCVB","CLIENTENUMERO":"10133","CLIENTENOME":"Lda 1","TREGISTO":"2015\\/11\\/24 09:34:15","TTERMO":"","SITUACAO":"C","TIPO":"P","NOTIFICACOES":"email","NOTIFI_TAREFA":"","ESFORCOS_TOT":"4","TEMPOGASTO_TOT":"0:01:44","TEMPOGASTO_PES":"0:01:44","PROJECTO":"New Products","USERNAME":"AT","UREGISTO":"S","EMCURSO":"0","TULTIMO":"2015\\/12\\/18 20:37:56","EQUIPA":"","NIVEL":"AVISAX"},{"ID":"783","DESCRICAO":"123","CLIENTENUMERO":"10133","CLIENTENOME":"Lda 1","TREGISTO":"2015\\/11\\/24 09:43:26","TTERMO":"","SITUACAO":"C","TIPO":"P","NOTIFICAC
As you can see, the JSON object isn't complete. Sending the same request using other methods in a browser returns the JSON correctly.
I'm wondering if this is an actual issue with fetch or with Android.
I've tried setting size and timeout parameters to 0 in fetch but it did nothing.
Edit: also tried using synchronous fetch instead of async, with the same effect:
fetch(REQUEST_URL, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
***params***
})
})
.then((response) => response.text())
.then((responseText) => {
console.log(responseText);
})
.catch((error) => {
console.warn(error);
}
Also tried:
console.log(responseJson);
and
console.log(responseJson.json());
Edit for further clarification:
When using response.json(), the response is shown as json (as to be expected) but it's still incomplete.
Edit :: Issue was with console.log limiting the number of characters it displays in the console.
Quick question:
Can you get the json object in its entirety if you hit the endpoint with postman? It could very well be your server/service that is cutting off the message.
Lastly, (and I see you mentioned this above) but I always use the 'json' method off the response obj when I know that is the notation type - which should return a promise.
fetch(REQUEST_URL, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
***params***
})
})
//get the response and execute .json
.then((r) => r.json())
//then listen for the json promise
.then((j) => {
console.log(j);
})
.catch((error) => {
console.warn(error);
}
Let me know what happens and if you get the full response with postman (or fiddler compose).