Response has valid set-cookie header, shows up in response inspector and everything:
But it doesn't set it and therefore doesn't send it with next requests. window.document.cookie returns empty string. Setting path or expires doesn't help, neither does domain=localhost.com;.
Starting to lose my mind after 2 days, Im missing something or it's impossible? I've googled a lot.
Details:
No cookie, CORS related errors
API: https://abc123.api.api-domain.com/
App: http://www.localhost.com/ (set in hosts file, it's actually 127.0.0.1/localhost)
Response headers:
OPTIONS:
Access-Control-Max-Age: '600'
Access-Control-Allow-Headers: 'Content-Type, Cookie'
Access-Control-Allow-Origin: 'http://www.localhost.com'
Access-Control-Allow-Credentials: 'true'
Access-Control-Allow-Methods: 'OPTIONS, POST'
POST:
Access-Control-Allow-Origin: 'http://www.localhost.com'
Access-Control-Allow-Credentials: 'true'
Set-Cookie: 'customCookie=somehash; domain=.localhost.com;'
Fetch function:
return fetch('https://abc123.api.api-domain.com/', {
method: 'POST',
credentials: 'include', // to allow cookies
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(someData),
}).then(res => {
return res.json();
});
Request headers:
Host: "abc123.api.api-domain.com"
Origin: "http://www.localhost.com"
Referer: "http://www.localhost.com/page"
Related
I'm trying to get data from an API of mine and I'm getting this error message in Chrome:
Access to fetch at 'https://myapi.amazonaws.com/accounts' from origin 'http://localhost:3000'
has been blocked by CORS policy: Request header field authorization is not allowed by
Access-Control-Allow-Headers in preflight response.
Since it's CORS, Chrome is doing a OPTIONS preflight request, which gets a 204 response with the following headers back:
access-control-allow-credentials: true
access-control-allow-origin: *
access-control-max-age: 3600
access-control-request-headers: *
access-control-request-method: GET, POST, PUT, PATCH, OPTIONS, DELETE
apigw-requestid: R64AgjukPHcEJWQ=
charset: utf-8
date: Tue, 10 May 2022 17:27:05 GMT
Then it makes the desired POST request with the following headers:
accept: application/json
authorization: Bearer some.very.long.string
Referer: http://localhost:3000/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36
And finally, here is the base code for the request (JS Fetch API):
const result = await fetch(`${process.env.MY_API_URL}/accounts`, {
method: 'POST',
mode: 'cors',
headers: new Headers(
Accept: 'application/json',
'Accept-Encoding': 'gzip, deflate, br',
Connection: 'keep-alive',
Authorization: `Bearer ${accessToken}`,
),
body: JSON.stringify({
accountId,
name,
}),
})
if (!result.ok || result.status !== 200)
throw new Error("Couldn't get data")
const jsonResponse = await result.json()
return jsonResponse
Any thoughts on what might be going on?
You need to set access-control-allow-headers in the preflight response, e.g.:
access-control-allow-headers: *
You can read more about Access-Control-Request-Headers and Access-Control-Allow-Headers
The headers
access-control-request-headers: *
access-control-request-method: GET, POST, PUT, PATCH, OPTIONS, DELETE
belong into the request, not into the response. You probably also need to set access-control-allow-methods in the preflight response, e.g.:
access-control-allow-methods: GET, POST, PUT, PATCH, OPTIONS, DELETE
I am sending POST request like this from browser and it is a cross platform request:
var reg_data = {"name": "John"};
fetch(url, {
method: 'POST',
mode: 'no-cors',
headers: new Headers({
'Content-Type': 'application/json',
'token': 'value'
}),
body: JSON.stringify(reg_data)
})
By the time the request reaches my back-end it does not contain token nor body.
Following is my backend ruby code -
before_action :cors_preflight_check
def cors_preflight_check
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Accept, Content-Type, token'
end
I checked some articles it says it happens as the mode is set to "no-cors" the headers and body is restricted. It works fine with postman, but fails with browser. How do I solve this issue as I want to serve a cross platform request and also access the request headers and body?
I am having a weird problem where when I make a fetch request from the client in development it is not sending the cookies to my server (legacy server that does not run on localhost).
Here is my code for the fetch request:
get( url ) {
return fetch(`${API_URL}${url}`, {
method: 'GET',
headers: headers(),
credentials: 'include'
}).then( parseResponse );
},
Headers is a function that returns the following object:
{
'Accept': 'application/json',
'Content-Type': 'application/json',
'mobile': 'false'
}
Here are the CORS headers I have set on the server (Access-Control-Allow-Origin is dynamic because fetch has issues with *)
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: mobile, Content-Type
Access-Control-Allow-Origin: http://localhost:3000
If I print out $_COOKIE I get back an empty array and when I look at the request I get Provisional headers are shown with no cookies.
Any ideas where I messed up?
Thanks In Advance :-)
I'm using chrome 53.0.2785.116 m (64-bit).
I got the following headers on devtools. The problem is marked with a "//" comment. content type is really not allowing us to set it to application/json, I have tried a 100 different ways.
import fetch from 'isomorphic-fetch';
const option = {
method: 'POST',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({'aa':'bb'})
}
fetch('/books', opts)
.then(check401)
.then(check404)
.then(jsonParse)
.then(errorMessageParse);
Request Headers
accept:application/json
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Content-Length:97
content-type:text/plain;charset=UTF-8 //What happen?
Host:127.0.0.1:8989
Origin:http://127.0.0.1:8989
Referer:http://127.0.0.1:8989/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36
The problem is that when you work in 'mode' 'no-cors', the Headers become an immutable and you will not be able to change some of its entries. One of the heads you can't change is the Content-Type. When you set 'mode' to 'no-cors' you will be able to change only these headers:
Accept
Accept-Language
Content-Language
Content-Type and whose value, once parsed, has a MIME type (ignoring parameters) that is application/x-www-form-urlencoded, multipart/form-data, or text/plain
In another words, in 'mode' '-no-'cors' you can only set application/x-www-form-urlencoded, multipart/form-data, or text/plain to the Content-Type.
So the solution is stop using fetch or changing it to 'cors' 'mode'. Of course this will only works if your server also accepts 'cors' requests.
Here is an example of how you could enable CORS in an Apache Server
SetEnvIfNoCase Access-Control-Request-Method "(GET|POST|PUT|DELETE|OPTIONS)" IsPreflight=1
SetEnvIfNoCase Origin ".*" AccessControlAllowOrigin=$0
SetEnvIfNoCase Origin "https://(url1.com|url2.com)$" AccessControlAllowOrigin=$0
Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" env=IsPreflight
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, Accept, Accept-Language" env=IsPreflight
Header always set Access-Control-Max-Age "7200" env=IsPreflight
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteCond %{ENV:IsPreflight} 1
RewriteRule ^(.*)$ $1 [R=204,L]
The above code will inject the CORS headers in the response when its necessary.
With this code your server will allow CORS only from the the domains "url1.com" or "url2.com".
Here are some references
https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
https://fetch.spec.whatwg.org/#simple-header
Thanks a lot! More than 6 hours to solve this.
In my nodejs server
npm install --save cors
at app.js I inserted the lines:
var cors = require('cors');
var app = express();
app.use(cors());
and in my react client:
var shape_for_db = JSON.stringify(layer.geometry);
const trechoRede = {
method: "POST",
mode: "cors",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: shape_for_db
};
The mode:"no-cors" options appears to be the issue. Remove that option and the Content-Type should be set to "application/json"
I would like to add some headers to Ajax.Request. I created requestHeader object:
requestHeaders: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS',
'Access-Control-Allow-Headers': 'Access-Control-Allow-Origin'
}
but cannot see those headers in my request (checking in browser). In console I see the error:
"XMLHttpRequest cannot load http://my_domain.com?some_parameters. Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers."
How to solve this problem?
Based on this github Pull Request with the latest version (1.7.2) you should be able to remove the extra X-* headers that Prototype adds to Ajax requests.
I think that will fix the problem you are having as there are 2 headers that cause problems with CORS requests, X-Requested-With and X-Prototype-Version
so using your same headers object
requestHeaders: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS',
'Access-Control-Allow-Headers': 'Access-Control-Allow-Origin',
'X-Requested-With': null,
'X-Prototype-Version': null
}