I want to make a post request with axios and the data that I must send must be json. I have seen that the content type of my header must be application / json and this is done by default. but when I see the request my called the content type is Content-Type: application / x-www-form-urlencoded
I have tried different ways to set it to change it but it always shows up in the request headers.
The service does the insert but with empty data.
Any idea? I've lost two days with this. Thanks!
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Authorization'
}
const dataJson = JSON.stringify(solicitudObj);
axios.post(state.basePath + 'Api/Solicitud/SaveSolicitud/',
dataJson,
headers
)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
})
Related
I have an axios request to the backend. And our backend said that he already configure the cors for the front end. But when I send my axios request. It only gets me this headers even if I put an header in my post request.
Here is my axios
for (var i = 0; i < this.rows.length; i++) {
console.log(this.rows[i].from)
console.log(this.rows[i].to)
axios.post(' https://pa-staging.propnex.net/index.php/public/addDiyOpenhouse?listing-id=506&start-time='+this.rows[i].from +'&end-time='+this.rows[i].to+'&date=2020-06-20',{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then((res)=>{
console.log(res);
})
}
The axios.post API dictates that the second parameter is for data (like form data or json, etc) and headers can be defined in the third parameter. So change you line to this syntax:
axios.post(url, requestData (or empty object for no data), {headers: { headerName: headerValue }})
For the context, I'm creating presigned URL to upload to S3. For these requests the Cache-Control header has to be set to the value public, max-age=31536000, immutable.
I do the fetch with this code
fetch(
uploadUrl,
{
method: 'PUT',
cache: 'no-store',
headers: { 'Content-Type': contentType, 'Cache-Control': 'public, max-age=31536000, immutable' },
body: data
})
.then(response => {
if (response.ok) {
doneFunc(publicUrl);
} else {
failureFunc(response.status);
}
})
.catch(response => {
failureFunc(response.status);
});
With Chrome the PUT request is actually sent with the Cache-Control header set in the fetch call public, max-age=31536000, immutable
With Firefox the PUT request is sent with the Cache-Control header set to public, max-age=31536000, immutable, no-cache. Notice the addition of no-cache at the end. This addition makes my presigned URL not valid.
I tried by removing the cache parameter, by setting it to no-cache and to no-store. Firefox always adds something to the Cache-Control header.
Do you know a way to make Firefox behaves like Chrome and respect the headers I set?
Try using the Headers object to add headers.
const headers = new Headers();
headers.append('Content-Type', contentType);
headers.append('cache-control', 'public, max-age=31536000, immutable, no-store');
fetch(
uploadUrl,
{
method: 'PUT',
headers: headers,
body: data
})
.then(response => {
if (response.ok) {
doneFunc(publicUrl);
} else {
failureFunc(response.status);
}
})
.catch(response => {
failureFunc(response.status);
});
My sample fetch request (if you want to test in firefox console)
const headers = new Headers();
headers.append('Content-Type', 'text/json');
headers.append('cache-control', 'public, max-age=31536000, immutable, no-custom');
const options = {
method: 'PUT',
headers: headers,
body: JSON.stringify({})
};
fetch('https://www.mozilla.org/', options)
.then(response => console.log(response.ok ? 'done' : 'fail'))
.catch(response => console.log('fail catch'));
Colin Nicholson had the right answer for me, but it was buried in a comment, so I'm reposting it at the top level:
When the network tab is open in Safari or Firefox, they add an extra no-cache header which causes the presigned S3 URL PUT request to fail. Close the dev console and the upload should work.
I have built an API and app that uses that API. When I POST method via Postman, it works fine, but when I try fetching it via app, I get a bad request 400 status response. What am I doing wrong?
Here is my JavaScript code:
const myForm = document.getElementById('loginForm');
myForm.addEventListener('submit', function(e) {
e.preventDefault();
const url = 'https://thawing-peak-69345.herokuapp.com/api/auth';
const myHeaders = new Headers();
myHeaders.append('Accept', 'application/json, text/html, */* ');
myHeaders.append('Content-Type', 'application/json, charset=utf-8')
const formData = {
email: this.email.value,
password: this.password.value
};
console.log(formData);
const fetchOptions = {
method: 'POST',
mode: 'no-cors',
cache: 'no-cache',
headers: myHeaders,
body: JSON.stringify(formData)
};
fetch(url, fetchOptions)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.log(err))
})
Request
Response
Headers request:
Headers response:
You said:
mode: 'no-cors',
This is a declaration that you are not doing anything that requires permission be granted with CORS. If you try to do anything that does need permission, it will be silently ignored.
myHeaders.append( 'Content-Type', 'application/json, charset=utf-8')
Setting the Content-Type header to a value not supported by the HTML form element's type attribute requires permission from CORS. application/json is not such a value.
Consequently, the request is sent as text/plain.
Since it isn't marked as being JSON, the server throws a 400 error.
You need to:
Remove mode: 'no-cors',
Make sure that the service you are making the request to will use CORS to grant you permission (or to use a service on the same origin as the request).
On making request like that:
return fetch(
'http://localhost:8000/login',
{ method: 'POST',
headers: new Headers(
{"Content-Type": "application/json",
"Accept":"application/json"}
),
body: JSON.stringify(
{'name': 'Tom', 'password': 'Soyer'}
)
}
).then( response => { console.log(response);})
.catch(err => console.log(err))
request running with method OPTIONS instead POST.
Only on adding mode: 'no-cors' request become POST:
return fetch(
'http://localhost:8000/login',
{ method: 'POST',
mode: 'no-cors',
headers: new Headers(
{"Content-Type": "application/json",
"Accept":"application/json"}
),
body: JSON.stringify(
{'name': 'Tom', 'password': 'Soyer'}
)
}
).then( response => { console.log(response);})
.catch(err => console.log(err))
but response not ok than (even if network response status is 200): {type: "opaque", url: "", status: 0, ok: false, statusText: ""…}
I suppose it because
The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded multipart/form-data text/plain
described here https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Is any way bring to live POST json data with fetch?
The custom Content-Type header you're sending causes your request to be preflighted, which means an OPTIONS request, containing some metadata about the POST request that is about to be dispatched, will be sent before the actual POST request.
Your server needs to be prepared to deal with this OPTIONS request. You haven't specified what the server is written in, but with express for example, you can register a middleware that intercepts all 'OPTIONS' requests, sets the Access-Control-Allow-Origin: * and Access-Control-Allow-Headers: Content-Type headers, and responds with 200.
If it is possible for you to make the request using a 'Content-Type': 'text/plain' header, that would solve your problem. Alternatively you could use something that bypasses XHR entirely, like JSONP.
When using non-cors, all headers must be valid simple-headers. The only valid values for the content-type header that qualifies as a simple-header is:
headers: [
['Content-Type', 'application/x-www-form-urlencoded'],
['Content-Type', 'multipart/form-data'],
['Content-Type', 'text/plain'],
]
Exceptions with contingencies:
headers: [
['Content-Type', 'application/csp-report'],
['Content-Type', 'application/expect-ct-report+json'],
['Content-Type', 'application/xss-auditor-report'],
['Content-Type', 'application/ocsp-request'],
]
simple-header
cors-protocol-exceptions
If you are trying to call an api and getting stuck with this in your react app you can add a proxy to the server and the cors error will get removed
just add this line at the package.json
"proxy":"url-to-your-server",
I'm running tests on my api via frisby.js. When I login a user, I'm setting a header cookie from the response like this
.after(function(err, res, body){
header: { content-type: 'application/json',
Cookie: res.headers['set-cookie']
...}
Then in my following tests I write
frisby.create('test with cookie')
.get('http://myapi/',{ headers: header})
This works fine, but when I do a post request
frisby.create('test update email')
.post('http://myapi/user/update', {
email: 'newEmail#test.com',
headers: header
})
I look at my console from the server, and the header is coming across as
{ 'content-type': 'application/x-www-form-urlencoded',
'host': config.baseDomain,
'content-length': '269',
'connection': 'keep-alive'
}
I thought maybe frisby was checking that the applied header was of the correct type, and updating the header without the Cookie, so I created a separate postHeader as
var postHeader = { 'content-type': 'application/x-www-form-urlencoded',
'host': config.baseDomain,
'content-length': '269',
'connection': 'keep-alive'
};
and appended the cookie to the post header and sent that through, but that doesn't work either.
Any way I can get the cookie sent in a post header?
have you tried adding:
.addHeader('Content-Type', 'application/json')
so something like:
frisby.create('test update email')
.addHeader('Content-Type', 'application/json')
.post('http://myapi/user/update', { email: 'newEmail#test.com'}, {json: true})
.expectStatus(200)
.toss();