Here is my server side code: (I use Laravel framework)
// route
Route::post('get_login_api_token', 'Auth\LoginController#get_login_api_token')->middleware('cors');
public function get_login_api_token(Request $request){
return $request;
}
And here is three kind of requests:
#1:
fetch('https://back.pronexo.net/get_login_api_token', {
method: 'POST', // or 'PUT'
mode: 'no-cors',
body: JSON.stringify({cell_phone:'whatever', password:'whatever'}),
headers:{
'Content-Type': 'application/json',
},
}).then(res => console.log('OK'));
returns []
#2:
fetch('https://back.pronexo.net/get_login_api_token?cell_phone=whatever&password=whatever', {
method: 'POST', // or 'PUT'
mode: 'no-cors',
headers:{
'Content-Type': 'application/json',
},
}).then(res => console.log('OK'));
returns {"cell_phone":"whatever","password":"whatever"}
#3:
Ok, as you can see, in the postman (request simulator) it works when when you pass parameters in the body section (not as query string in the url). But why it doesn't work in the code? (you can try it in the console tan of your browser). Any idea how can I make #1 working ?
EDIT: Noted that the header is different in the postman:
I didn't use header as application/json and didn't encoded body with json format.
I have used curl and i am getting response in json and when decoded it gives
stdClass Object ( [cell_phone] => whatever [pass] => whatever )
Are you sure that the POST requets is well formated ?
I think that you should test using the FormData API (doc).
var data = new FormData
data.append("cellphone", "whatever")
data.append("password", "whatever")
// using XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://back.pronexo.net/get_login_api_token')
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.onreadystatechange = function() {
if (xhr.readystate = 4 && xhr.status == 200) {
console.log(xhr.response, xhr.responseText)
}
}
xhr.send(data)
// using fetch method I don't know how it deals with FormData Objects.
fetch('https://back.pronexo.net/get_login_api_token', {
method: 'POST', // or 'PUT'
mode: 'no-cors',
body: data,
headers:{
'Content-Type': 'application/json',
},
}).then(res => console.log('OK'));
You can maybe use external tools like this: Insomnia REST Client to test your API.
Related
I'm trying to access to an API using fetch however the error I receive in console:
XHR GET https://api.geoapify.com/v1/geocode/search?street=buenos%20aires&city=barcelona&country=espa%C3%B1a&lang=es&limit=1&format=json&apiKey=hereIputmyrealkey
Estado 401 Unauthorized
Versión HTTP/2
Transferido1,52 KB (tamaño 97 B)
Política de referenciastrict-origin-when-cross-origin
The fetch looks like this:
var requestOptions = {
method: 'GET',
credentials: "include"
};
let response = await fetch("https://api.geoapify.com/v1/geocode/search?street=buenos aires&city=barcelona&country=españa&lang=es&limit=1&format=json&apiKey=${MYKEY}");
When I add:
.then(error => console.log(error)
It return response undefined.
I'm working on cakephp, the url for the fetch works and outside of cakephp the fetch works too. Do I need to add something to the fetch?
(The key in my code is my actual key and the url gives a response in json format).
I tried adding:
var requestOptions = {
method: 'GET',
credentials: "include"
};
and
var requestOptions = {
method: 'GET',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
};
but it gives the same error...
Use back ticks when adding ${variable}
let response = await fetch(`https://api.geoapify.com/v1/geocode/search?street=buenos aires&city=barcelona&country=españa&lang=es&limit=1&format=json&apiKey=${MYKEY}`);
I am using the Deepl API, and when I run the request in Postman it is successful, however using it in my app it returns only a 400 Error, which I assume means the headers aren't set up correctly, but it is just how it is in my Postman. Can anyone point out what may be the issue here?
async translateMessage(data = {}) {
const url = "https://api.deepl.com/v2/translate?auth_key=myAuthKey";
const response = await fetch(url, {
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': '*/*'
},
body: {
text: JSON.stringify(this.text),
target_lang: 'DE',
source_lang: 'EN'
}
});
return response.json();
},
Example HTTP Post Request from Documentation:
POST /v2/translate?auth_key=[yourAuthKey]> HTTP/1.0
Host: api.deepl.com
User-Agent: YourApp
Accept: */*
Content-Length: [length]
Content-Type: application/x-www-form-urlencoded
auth_key=[yourAuthKey]&text=Hello, world&source_lang=EN&target_lang=DE
The body property of a URL-encoded message (with the application/x-www-form-urlencoded content type) must be either a string of the query parameters, or a URLSearchParams instance.
Solution
Pass the object of key/value pairs to the URLSearchParams constructor.
You might as well add auth_key (one of the required query parameters) to that, and remove it from the URL.
Remove JSON.stringify() from the text property as that would insert unnecessary quotes into the translation.
const url = 'https://api.deepl.com/v2/translate';
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': '*/*'
}, 1️⃣
body: new URLSearchParams({
auth_key: myAuthKey, 2️⃣
text: this.text, 3️⃣
target_lang: 'DE',
source_lang: 'EN'
})
});
Here is my code:
function uploadImage(payload) {
return fetch('/api/storage/upload/image/', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
Accept: 'application/json',
Authorization: 'Bearer <token>',
},
body: payload,
});
}
function uploadImage2(payload) {
return axios.post('/api/storage/upload/image/', payload, {
headers: {
'Content-Type': 'multipart/form-data',
Accept: 'application/json',
Authorization: 'Bearer <token>',
},
});
}
function test(file, meta_data) {
var formBody = new FormData();
formBody.set('image', file);
formBody.set('meta_data', meta_data);
uploadImage(formBody);
// doesn't work
uploadImage2(formBody);
// works
}
Can someone please explain to me how I'm supposed to send multipart requests with fetch?
The error I get with this code is: 400 bad request, file and meta_data are null.
Do not use this header: 'Content-Type': 'multipart/form-data'.
Remove the header and it should work.
Explanation:
When using fetch with the 'Content-Type': 'multipart/form-data' you also have to set the boundary (the separator between the fields that are being sent in the request).
Without the boundary, the server receiving the request won't know where a field starts and where it ends.
You could set the boundary yourself, but it's better to let the browser do that automatically by removing the 'Content-Type' header altogether.
Here's some more insight: Uploading files using 'fetch' and 'FormData'
Here is what worked for me:
function uploadImage(payload) {
return fetch('/api/storage/upload/image/', {
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
},
body: payload,
});
}
By comparing the cURL requests sent by the browser I discovered that in the axios request has this:
"Content-Type": "multipart/form-data; boundary=---------------------------19679527153991285751414616421",
So I figured that when you manually specify the content type, fetch respects that and doesn't touch anything while still does it's thing the way it wants:-/ so you just shouldn't specify it, fetch will know itself since you are using formData()
I'm calling a simple login API with POST request following are the params:
Headers:
Content-type: application/x-www-form-urlencoded
Body:
email: String
password
Error returned from server is:422 Unprocessable Entity
CODE:
var formBody = new FormData();
formBody.set("email", "test5#gmail.com");
formBody.set("password", "12345678");
const data = new URLSearchParams(new FormData(details));
return dispatch => {
dispatch(requestData());
try {
fetch(`${BASE_URL}users/sign_in`, {
method: 'POST',
// headers: Interceptor.getHeaders(),
headers: {
Accept:'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
// body: formBody
body: data
})
.then(res => res.json())
.then(result=>
{
if (result.success === false) {}
}
)
} catch (error) {
console.log('error',error)
dispatch(failureData(error))
}
}
Screenshot of code
Got the answer, 422 is basically caused by semantic issue, in my case, Origin of my Request Header was going null.
I'm encountering a bit of a roadblock in my dev work. I'm trying to upload a photo that I'm sending using FormData in fetch. I'm guessing my problem is in my content header or my back-end handling. Eitherway, I can't seem to find a way around it. I hope you guys can help me
general.js - this is my handler for a request
export const postDataWithImage = (url, data) => {
return fetch(url, {
body: data, // must match 'Content-Type' header
credentials: 'same-origin', //pass cookies, for authentication
method: 'POST',
headers: {
'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
},
})
.then(response => response.json()); // parses response to JSON
};
user-creation.js - my actual usage of the function above (sending multiple data)
heres an image of the data I'm sending
![1] https://imgur.com/leBlC7L
const data = {...this.state, ...form};
const formData = new FormData();
Object.entries(data).forEach(([key, value]) => formData.append(key, value));
postDataWithImage('/users', data)
.then(data => {
if (data.error) {
console.log("theres an error");
this.setState({
error: data["error"]
});
console.log(this.state.error);
} else {
console.log(data["data"]);
}
})
.catch(error => message.warning(error.message));
views.py - my backend handler using Django REST not: this returns me an error either byte has no attribute 'get'... or an empty ModelDict for request.FILES
#staticmethod
def post(request):
print(request.body.get('image'))
print(request.FILES)
if "username" not in request.data or "password" not in request.data:
return Response(data={
"error": "Missing username or password"
}, status=400, content_type="application/json")
return Response(data=data, status=200, content_type="application/json")
Please help me I'm really stuck. Thank you!
I faced similar problem using Vue.js and Django.
Finally I noticed that the problem was that: boundary was not set to the header.
The solution is to remove headers from your request like this:
fetch(url, {
body: data, // assume this is some binary data
method: 'POST',
})
Then, your browser will automatically add proper headers for your request. And you will see boundary field which is added by your browser in your request headers.
Try to remove the "Content-Type" from the headers of fetch