How to get status response from fetch URL [duplicate] - reactjs

Mod note: This question is about why XMLHttpRequest/fetch/etc. on the browser are subject to the Same Access Policy restrictions (you get errors mentioning CORB or CORS) while Postman is not. This question is not about how to fix a "No 'Access-Control-Allow-Origin'..." error. It's about why they happen.
Please stop posting:
CORS configurations for every language/framework under the sun. Instead find your relevant language/framework's question.
3rd party services that allow a request to circumvent CORS
Command line options for turning off CORS for various browsers
I am trying to do authorization using JavaScript by connecting to the RESTful API built-in Flask. However, when I make the request, I get the following error:
XMLHttpRequest cannot load http://myApiUrl/login.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'null' is therefore not allowed access.
I know that the API or remote resource must set the header, but why did it work when I made the request via the Chrome extension Postman?
This is the request code:
$.ajax({
type: 'POST',
dataType: 'text',
url: api,
username: 'user',
password: 'pass',
crossDomain: true,
xhrFields: {
withCredentials: true,
},
})
.done(function (data) {
console.log('done');
})
.fail(function (xhr, textStatus, errorThrown) {
alert(xhr.responseText);
alert(textStatus);
});

If I understood it right you are doing an XMLHttpRequest to a different domain than your page is on. So the browser is blocking it as it usually allows a request in the same origin for security reasons. You need to do something different when you want to do a cross-domain request.
When you are using Postman they are not restricted by this policy. Quoted from Cross-Origin XMLHttpRequest:
Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers, but they're limited by the same origin policy. Extensions aren't so limited. An extension can talk to remote servers outside of its origin, as long as it first requests cross-origin permissions.

WARNING: Using Access-Control-Allow-Origin: * can make your API/website vulnerable to cross-site request forgery (CSRF) attacks. Make certain you understand the risks before using this code.
It's very simple to solve if you are using PHP. Just add the following script in the beginning of your PHP page which handles the request:
<?php header('Access-Control-Allow-Origin: *'); ?>
If you are using Node-red you have to allow CORS in the node-red/settings.js file by un-commenting the following lines:
// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
origin: "*",
methods: "GET,PUT,POST,DELETE"
},
If you are using Flask same as the question; you have first to install flask-cors
pip install -U flask-cors
Then include the Flask cors package in your application.
from flask_cors import CORS
A simple application will look like:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
#app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
For more details, you can check the Flask documentation.

Because
$.ajax({type: "POST" - calls OPTIONS
$.post( - calls POST
Both are different. Postman calls "POST" properly, but when we call it, it will be "OPTIONS".
For C# web services - Web API
Please add the following code in your web.config file under the <system.webServer> tag. This will work:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
Please make sure you are not doing any mistake in the Ajax call.
jQuery
$.ajax({
url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
type: "POST", /* or type:"GET" or type:"PUT" */
dataType: "json",
data: {
},
success: function (result) {
console.log(result);
},
error: function () {
console.log("error");
}
});
Note: If you are looking for downloading content from a third-party website then this will not help you. You can try the following code, but not JavaScript.
System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");

Deep
In the below investigation as API, I use http://example.com instead of http://myApiUrl/login from your question, because this first one working. I assume that your page is on http://my-site.local:8088.
NOTE: The API and your page have different domains!
The reason why you see different results is that Postman:
set header Host=example.com (your API)
NOT set header Origin
Postman actually not use your website url at all (you only type your API address into Postman) - he only send request to API, so he assume that website has same address as API (browser not assume this)
This is similar to browsers' way of sending requests when the site and API has the same domain (browsers also set the header item Referer=http://my-site.local:8088, however I don't see it in Postman). When Origin header is not set, usually servers allow such requests by default.
This is the standard way how Postman sends requests. But a browser sends requests differently when your site and API have different domains, and then CORS occurs and the browser automatically:
sets header Host=example.com (yours as API)
sets header Origin=http://my-site.local:8088 (your site)
(The header Referer has the same value as Origin). And now in Chrome's Console & Networks tab you will see:
When you have Host != Origin this is CORS, and when the server detects such a request, it usually blocks it by default.
Origin=null is set when you open HTML content from a local directory, and it sends a request. The same situation is when you send a request inside an <iframe>, like in the below snippet (but here the Host header is not set at all) - in general, everywhere the HTML specification says opaque origin, you can translate that to Origin=null. More information about this you can find here.
fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab
If you do not use a simple CORS request, usually the browser automatically also sends an OPTIONS request before sending the main request - more information is here. The snippet below shows it:
fetch('http://example.com/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)
You can change the configuration of your server to allow CORS requests.
Here is an example configuration which turns on CORS on nginx (nginx.conf file) - be very careful with setting always/"$http_origin" for nginx and "*" for Apache - this will unblock CORS from any domain (in production instead of stars use your concrete page adres which consume your api)
location ~ ^/index\.php(/|$) {
...
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}
Here is an example configuration which turns on CORS on Apache (.htaccess file)
# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests |
# ------------------------------------------------------------------------------
# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/
# <IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
# </IfModule>
# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"
Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

Applying a CORS restriction is a security feature defined by a server and implemented by a browser.
The browser looks at the CORS policy of the server and respects it.
However, the Postman tool does not bother about the CORS policy of the server.
That is why the CORS error appears in the browser, but not in Postman.

The error you get is due to the CORS standard, which sets some restrictions on how JavaScript can perform ajax requests.
The CORS standard is a client-side standard, implemented in the browser. So it is the browser which prevent the call from completing and generates the error message - not the server.
Postman does not implement the CORS restrictions, which is why you don't see the same error when making the same call from Postman.
Why doesn't Postman implement CORS? CORS defines the restrictions relative to the origin (URL domain) of the page which initiates the request. But in Postman the requests doesn't originate from a page with an URL so CORS does not apply.

Solution & Issue Origins
You are making a XMLHttpRequest to different domains, example:
Domain one: some-domain.com
Domain Two: some-different-domain.com
This difference in domain names triggers CORS (Cross-Origin Resource Sharing) policy called SOP (Same-Origin Policy) that enforces the use of same domains (hence Origin) in Ajax, XMLHttpRequest and other HTTP requests.
Why did it work when I made the request via the Chrome extension
Postman?
A client (most Browsers and Development Tools) has a choice to enforce the Same-Origin Policy.
Most browsers enforce the policy of Same-Origin Policy to prevent issues related to CSRF (Cross-Site Request Forgery) attack.
Postman as a development tool chooses not to enforce SOP while some browsers enforce, this is why you can send requests via Postman that you cannot send with XMLHttpRequest via JS using the browser.

For browser testing purposes:
Windows - Run:
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
The command above will disable chrome web security. So for example if you work on a local project and encounter CORS policy issue when trying to make a request, you can skip this type of error with the above command. Basically it will open a new chrome session.

You might also get this error if your gateway timeout is too short and the resource you are accessing takes longer to process than the timeout. This may be the case for complex database queries etc. Thus, the above error code can be disguishing this problem. Just check if the error code is 504 instead of 404 as in Kamil's answer or something else. If it is 504, then increasing the gateway timeout might fix the problem.
In my case the CORS error could be removed by disabling the same origin policy (CORS) in the Internet Explorer browser, see How to disable same origin policy Internet Explorer. After doing this, it was a pure 504 error in the log.

To resolve this issue, write this line of code in your doGet() or doPost() function whichever you are using in backend
response.setHeader("Access-Control-Allow-Origin", "*");
Instead of "*" you can type in the website or API URL endpoint which is accessing the website else it will be public.

Your IP address is not whitelisted, so you are getting this error.
Ask the backend staff to whitelist your IP address for the service you are accessing.
Access-Control-Allow-Headers

For me I got this issue for different reason, the remote domain was added to origins the deployed app works perfectly except one end point I got this issue:
Origin https://mai-frontend.vercel.app is not allowed by Access-Control-Allow-Origin. Status code: 500
and
Fetch API cannot load https://sciigo.herokuapp.com/recommendations/recommendationsByUser/8f1bb29e-8ce6-4df2-b138-ffe53650dbab due to access control checks.
I discovered that my Heroku database table does not contains all the columns of my local table after updating Heroku database table everything worked well.

It works for me by applying this middleware in globally:
<?php
namespace App\Http\Middleware;
use Closure;
class Cors {
public function handle($request, Closure $next) {
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', "Accept,authorization,Authorization, Content-Type");
}
}

Related

Response to preflight request doesn't pass access control check: It does not have HTTP ok status [duplicate]

I'm getting this error using ngResource to call a REST API on Amazon Web Services:
XMLHttpRequest cannot load
http://server.apiurl.com:8000/s/login?login=facebook. Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost' is therefore not allowed access.
Error 405
Service:
socialMarkt.factory('loginService', ['$resource', function ($resource) {
var apiAddress = "http://server.apiurl.com:8000/s/login/";
return $resource(apiAddress, {
login: "facebook",
access_token: "#access_token",
facebook_id: "#facebook_id"
}, {
getUser: {
method: 'POST'
}
});
}]);
Controller:
[...]
loginService.getUser(JSON.stringify(fbObj)),
function (data) {
console.log(data);
},
function (result) {
console.error('Error', result.status);
}
[...]
I'm using Chrome. What else can I do in order to fix this problem?
I've even configured the server to accept headers from origin localhost.
You are running into CORS issues.
There are several ways to fix or workaround this.
Turn off CORS. For example: How to turn off CORS in Chrome
Use a plugin for your browser
Use a proxy, such as nginx. Example of how to set up
Go through the necessary setup for your server. This is more a factor of the web server you have loaded on your EC2 instance (presuming this is what you mean by "Amazon web service"). For your specific server, you can refer to the enable CORS website.
More verbosely, you are trying to access api.serverurl.com from localhost. This is the exact definition of a cross-domain request.
By either turning it off just to get your work done (OK, but poor security for you if you visit other sites and just kicks the can down the road) or you can use a proxy which makes your browser think all requests come from the local host when really you have a local server that then calls the remote server.
So api.serverurl.com might become localhost:8000/api, and your local nginx or other proxy will send to the correct destination.
Now by popular demand, 100% more CORS information—the same great taste!
Bypassing CORS is exactly what is shown for those simply learning the front end.
HTTP Example with Promises
My "API Server" is a PHP application, so to solve this problem I found the below solution to work:
Place these lines in file index.php:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
In ASP.NET Core Web API, this issue got fixed by adding "Microsoft.AspNetCore.Cors" (ver 1.1.1) and adding the below changes in Startup.cs.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAllHeaders",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
.
.
.
}
and
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Shows UseCors with named policy.
app.UseCors("AllowAllHeaders");
.
.
.
}
And putting [EnableCors("AllowAllHeaders")] in the controller.
There are some caveats when it comes to CORS. First, it does not allow wildcards *, but don't hold me on this one. I've read it somewhere, and I can't find the article now.
If you are making requests from a different domain, you need to add the allow origin headers.
Access-Control-Allow-Origin: www.other.com
If you are making requests that affect server resources like POST/PUT/PATCH, and if the MIME type is different than the following application/x-www-form-urlencoded, multipart/form-data, or text/plain the browser will automatically make a pre-flight OPTIONS request to check with the server if it would allow it.
So your API/server needs to handle these OPTIONS requests accordingly, you need to respond with the appropriate access control headers and the http response status code needs to be 200.
The headers should be something like this, adjust them for your needs:
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
The max-age header is important, in my case, it wouldn't work without it, I guess the browser needs the info for how long the "access rights" are valid.
In addition, if you are making e.g. a POST request with application/json mime from a different domain you also need to add the previously mentioned allow origin header, so it would look like this:
Access-Control-Allow-Origin: www.other.com
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
When the pre-flight succeeds and gets all the needed information your actual request will be made.
Generally speaking, whatever Access-Control headers are requested in the initial or pre-flight request, should be given in the response in order for it to work.
There is a good example in the MDN documentation here on this link, and you should also check out this Stack Overflow post.
If you're writing a Chrome extension
In the manifest.json file, you have to add the permissions for your domain(s).
"permissions": [
"http://example.com/*",
"https://example.com/*",
"http://www.example.com/*",
"https://www.example.com/*"
]
JavaScript XMLHttpRequest and Fetch follow the same-origin policy. So,
a web application using XMLHttpRequest or Fetch could only make HTTP
requests to its own domain.
Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
You have to send the Access-Control-Allow-Origin: * HTTP header from your server side.
If you are using Apache as your HTTP server then you can add it to your Apache configuration file like this:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
Mod_headers is enabled by default in Apache, however, you may want to ensure it's enabled by running:
a2enmod headers
In PHP you can add the headers:
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Expose-Headers: Content-Length, X-JSON");
header("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: *");
...
To fix cross-origin-requests issues in a Node.js application:
npm i cors
And simply add the lines below to the app.js file:
let cors = require('cors')
app.use(cors())
If you are using the IIS server by chance, you can set the below headers in the HTTP request headers option.
Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';
With this all POST, GET, etc., will work fine.
In my Apache VirtualHost configuration file, I have added following lines:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
Our team occasionally sees this using Vue.js, Axios and a C# Web API. Adding a route attribute on the endpoint you're trying to hit fixes it for us.
[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
For a Python Flask server, you can use the flask-cors plugin to enable cross domain requests.
See: Flask-CORS
For anyone using API Gateway's HTTP API and the proxy route ANY /{proxy+}
You will need to explicitly define your route methods in order for CORS to work.
I wish this was more explicit in the AWS documentation for configuring CORS for an HTTP API
I was on a two-hour call with AWS support and they looped in one of their senior HTTP API developers, who made this recommendation.
For those who are using Lambda Integrated Proxy with API Gateway, you need configure your lambda function as if you are submitting your requests to it directly, meaning the function should set up the response headers properly. (If you are using custom lambda functions, this will be handled by the API Gateway.)
// In your lambda's index.handler():
exports.handler = (event, context, callback) => {
// On success:
callback(null, {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin" : "*"
}
}
}
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading of resources
From Cross-Origin Resource Sharing (CORS)
In short - the web server tells you (your browser) which sites you should trust for using that site.
Scammysite.bad tries to tell your browser to send a request to good-api-site.good
good-api-site.good tells your browser it should only trust other-good-site.good
Your browser says that you really should not trust scammysite.bad's request to good-api-site.good and goes CORS saved you.
If you are creating a site, and you really don't care who integrates with you. Plow on. Set * in your ACL.
However, if you are creating a site, and only site X, or even site X, Y and Z should be allowed, you use CORS to instruct the client's browser to only trust these sites to integrate with your site.
Browsers can of course choose to ignore this. Again, CORS protects your client - not you.
CORS allows * or one site defined. This can limit you, but you can get around this by adding some dynamic configuration to your web server - and help you being specific.
This is an example on how to configure CORS per site is in Apache:
# Save the entire "Origin" header in Apache environment variable "AccessControlAllowOrigin"
# Expand the regex to match your desired "good" sites / sites you trust
SetEnvIfNoCase Origin "^https://(other-good-site\.good|one-more-good.site)$" AccessControlAllowOrigin=$0
# Assuming you server multiple sites, ensure you apply only to this specific site
<If "%{HTTP_HOST} == 'good-api-site.com'">
# Remove headers to ensure that they are explicitly set
Header unset Access-Control-Allow-Origin env=AccessControlAllowOrigin
Header unset Access-Control-Allow-Methods env=AccessControlAllowOrigin
Header unset Access-Control-Allow-Headers env=AccessControlAllowOrigin
Header unset Access-Control-Expose-Headers env=AccessControlAllowOrigin
# Add headers "always" to ensure that they are explicitly set
# The value of the "Access-Control-Allow-Origin" header will be the contents saved in the "AccessControlAllowOrigin" environment variable
Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
# Adapt the below to your use case
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, PUT" env=AccessControlAllowOrigin
Header always set Access-Control-Allow-Headers "X-Requested-With,Authorization" env=AccessControlAllowOrigin
Header always set Access-Control-Expose-Headers "X-Requested-With,Authorization" env=AccessControlAllowOrigin
</If>
I think disabling CORS from Chrome is not good way, because if you are using it in Ionic, certainly in a mobile build the issue will raise again.
So better to fix in your backend.
First of all, in the header, you need to set-
header('Access-Control-Allow-Origin: *');
header('Header set Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');
And if the API is behaving as both GET and POST, then also set in your header-
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { if
(isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers:
{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); exit(0); }
A very common cause of this error could be that the host API had mapped the request to an HTTP method (e.g., PUT) and the API client is calling the API using a different http method (e.g., POST or GET).
Using the CORS option in the API gateway, I used the following settings shown above.
Also, note, that your function must return a HTTP status 200 in response to an OPTIONS request, or else CORS will also fail.
I am using AWS SDK for uploads, and after spending some time searching online, I stumbled upon this question. Thanks to #lsimoneau 45581857, it turns out the exact same thing was happening.
I simply pointed my request URL to the region on my bucket by attaching the region option and it worked.
const s3 = new AWS.S3({
accessKeyId: config.awsAccessKeyID,
secretAccessKey: config.awsSecretAccessKey,
region: 'eu-west-2' // add region here });
I have faced this problem when the DNS server was set to 8.8.8.8 (Google's). Actually, the problem was in the router. My application tried to connect with the server through Google, not locally (for my particular case).
I have removed 8.8.8.8 and this solved the issue. I know that this issues solved by CORS settings, but maybe someone will have the same trouble as me.
Check if request is going to correct endpoint. In my Node.js project, I mentioned incorrect endpoint, the request was going to /api/txn/12345, the endpoint was /api/txn instead of /api/txn/:txnId, that led to this error.
It's easy to solve this issue just with a few steps easily, without worrying about anything.
Kindly, follow the steps to solve it.
open (https://www.npmjs.com/package/cors#enabling-cors-pre-flight)
go to installation and copy the command npm install cors to install via Node.js in a terminal
go to Simple Usage (Enable All CORS Requests) by scrolling. Then copy and paste the complete declaration in your project and run it...that will work for sure...
copy the comment code and paste in your app.js or any other project and give a try...this will work. This will unlock every cross origin resource sharing...so we can switch between servers for your use
The stand-alone distributions of GeoServer include the Jetty application server. Enable cross-origin resource sharing (CORS) to allow JavaScript applications outside of your own domain to use GeoServer.
Uncomment the following <filter> and <filter-mapping> from webapps/geoserver/WEB-INF/web.xml:
<web-app>
<filter>
<filter-name>cross-origin</filter-name>
<filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cross-origin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
The "Response to preflight request doesn't pass access control check" is exactly what the problem is:
Before issuing the actual GET request, the browser is checking if the service is correctly configured for CORS. This is done by checking if the service accepts the methods and headers going to be used by the actual request. Therefore, it is not enough to allow the service to be accessed from a different origin, but also the additional requisites must be fulfilled.
Setting headers to
Header always set Access-Control-Allow-Origin: www.example.com
Header always set Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
Header always set Access-Control-Allow-Headers: Content-Type #etc...
will not suffice. You have to add a rewrite rule:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
A great read Response for preflight does not have HTTP ok status.
I made it work, adding the OPTIONS method to Access-Control-Allow-Methods:
Access-Control-Allow-Methods: GET, OPTIONS
But!, again, this works in Chrome and Firefox, but sadly not in Chromium.
Something that is very easy to miss...
In Solution Explorer, right-click api-project. In the properties window, set 'Anonymous Authentication' to Enabled!!!
Disable the Chrome security.
Create a Chrome shortcut: right click → Properties → Target. Paste this: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="c:/chromedev"

Access to XMLHttpRequest at ''API-URL" from origin localhost has been blocked by CORS policy [duplicate]

I'm trying to fetch some data from the REST API of HP Alm. It works pretty well with a small curl script—I get my data.
Now doing that with JavaScript, fetch and ES6 (more or less) seems to be a bigger issue. I keep getting this error message:
Fetch API cannot load . Response to preflight request doesn't
pass access control check: No 'Access-Control-Allow-Origin' header is
present on the requested resource. Origin 'http://127.0.0.1:3000' is
therefore not allowed access. The response had HTTP status code 501.
If an opaque response serves your needs, set the request's mode to
'no-cors' to fetch the resource with CORS disabled.
I understand that this is because I am trying to fetch that data from within my localhost and the solution should be using Cross-Origin Resource Sharing (CORS). I thought I actually did that, but somehow it either ignores what I write in the header or the problem is something else.
So, is there an implementation issue? Am I doing it wrong? I can't check the server logs unfortunately. I'm really a bit stuck here.
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('GET', 'POST', 'OPTIONS');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(sign_in, {
//mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
I am using Chrome. I also tried using that Chrome CORS Plugin, but then I am getting another error message:
The value of the 'Access-Control-Allow-Origin' header in the response
must not be the wildcard '*' when the request's credentials mode is
'include'. Origin 'http://127.0.0.1:3000' is therefore not allowed
access. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
This answer covers a lot of ground, so it’s divided into three parts:
How to use a CORS proxy to avoid “No Access-Control-Allow-Origin header” problems
How to avoid the CORS preflight
How to fix “Access-Control-Allow-Origin header must not be the wildcard” problems
How to use a CORS proxy to avoid “No Access-Control-Allow-Origin header” problems
If you don’t control the server your frontend code is sending a request to, and the problem with the response from that server is just the lack of the necessary Access-Control-Allow-Origin header, you can still get things to work—by making the request through a CORS proxy.
You can easily run your own proxy with code from https://github.com/Rob--W/cors-anywhere/.
You can also easily deploy your own proxy to Heroku in just 2-3 minutes, with 5 commands:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
After running those commands, you’ll end up with your own CORS Anywhere server running at, e.g., https://cryptic-headland-94862.herokuapp.com/.
Now, prefix your request URL with the URL for your proxy:
https://cryptic-headland-94862.herokuapp.com/https://example.com
Adding the proxy URL as a prefix causes the request to get made through your proxy, which:
Forwards the request to https://example.com.
Receives the response from https://example.com.
Adds the Access-Control-Allow-Origin header to the response.
Passes that response, with that added header, back to the requesting frontend code.
The browser then allows the frontend code to access the response, because that response with the Access-Control-Allow-Origin response header is what the browser sees.
This works even if the request is one that triggers browsers to do a CORS preflight OPTIONS request, because in that case, the proxy also sends the Access-Control-Allow-Headers and Access-Control-Allow-Methods headers needed to make the preflight succeed.
How to avoid the CORS preflight
The code in the question triggers a CORS preflight—since it sends an Authorization header.
https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Even without that, the Content-Type: application/json header will also trigger a preflight.
What “preflight” means: before the browser tries the POST in the code in the question, it first sends an OPTIONS request to the server, to determine if the server is opting-in to receiving a cross-origin POST that has Authorization and Content-Type: application/json headers.
It works pretty well with a small curl script - I get my data.
To properly test with curl, you must emulate the preflight OPTIONS the browser sends:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
…with https://the.sign_in.url replaced by whatever your actual sign_in URL is.
The response the browser needs from that OPTIONS request must have headers like this:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
If the OPTIONS response doesn’t include those headers, the browser will stop right there and never attempt to send the POST request. Also, the HTTP status code for the response must be a 2xx—typically 200 or 204. If it’s any other status code, the browser will stop right there.
The server in the question responds to the OPTIONS request with a 501 status code, which apparently means it’s trying to indicate it doesn’t implement support for OPTIONS requests. Other servers typically respond with a 405 “Method not allowed” status code in this case.
So you’ll never be able to make POST requests directly to that server from your frontend JavaScript code if the server responds to that OPTIONS request with a 405 or 501 or anything other than a 200 or 204 or if doesn’t respond with those necessary response headers.
The way to avoid triggering a preflight for the case in the question would be:
if the server didn’t require an Authorization request header but instead, e.g., relied on authentication data embedded in the body of the POST request or as a query param
if the server didn’t require the POST body to have a Content-Type: application/json media type but instead accepted the POST body as application/x-www-form-urlencoded with a parameter named json (or whatever) whose value is the JSON data
How to fix “Access-Control-Allow-Origin header must not be the wildcard” problems
I am getting another error message:
The value of the 'Access-Control-Allow-Origin' header in the response
must not be the wildcard '*' when the request's credentials mode is
'include'. Origin 'http://127.0.0.1:3000' is therefore not allowed
access. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
For requests that have credentials, browsers won’t let your frontend JavaScript code access the response if the value of the Access-Control-Allow-Origin header is *. Instead the value in that case must exactly match your frontend code’s origin, http://127.0.0.1:3000.
See Credentialed requests and wildcards in the MDN HTTP access control (CORS) article.
If you control the server you’re sending the request to, a common way to deal with this case is to configure the server to take the value of the Origin request header, and echo/reflect that back into the value of the Access-Control-Allow-Origin response header; e.g., with nginx:
add_header Access-Control-Allow-Origin $http_origin
But that’s just an example; other (web) server systems have similar ways to echo origin values.
I am using Chrome. I also tried using that Chrome CORS Plugin
That Chrome CORS plugin apparently just simplemindedly injects an Access-Control-Allow-Origin: * header into the response the browser sees. If the plugin were smarter, what it would be doing is setting the value of that fake Access-Control-Allow-Origin response header to the actual origin of your frontend JavaScript code, http://127.0.0.1:3000.
So avoid using that plugin, even for testing. It’s just a distraction. To test what responses you get from the server with no browser filtering them, you’re better off using curl -H as above.
As far as the frontend JavaScript code for the fetch(…) request in the question:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Remove those lines. The Access-Control-Allow-* headers are response headers. You never want to send them in requests. The only effect of that is to trigger a browser to do a preflight.
This error occurs when the client URL and server URL don't match, including the port number. In this case you need to enable your service for CORS which is cross origin resource sharing.
If you are hosting a Spring REST service then you can find it in the blog post CORS support in Spring Framework.
If you are hosting service using a Node.js server then
Stop the Node.js server.
npm install cors --save
Add following lines to your server.js
const cors=require("cors");
const corsOptions ={
origin:'*',
credentials:true, //access-control-allow-credentials:true
optionSuccessStatus:200,
}
app.use(cors(corsOptions)) // Use this after the variable declaration
The problem arose because you added the following code as the request header in your front-end:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Those headers belong to the response, not request. So remove them, including the line:
headers.append('GET', 'POST', 'OPTIONS');
Your request had 'Content-Type: application/json', hence triggered what is called CORS preflight. This caused the browser sent the request with the OPTIONS method. See CORS preflight for detailed information.
Therefore in your back-end, you have to handle this preflighted request by returning the response headers which include:
Access-Control-Allow-Origin : http://localhost:3000
Access-Control-Allow-Credentials : true
Access-Control-Allow-Methods : GET, POST, OPTIONS
Access-Control-Allow-Headers : Origin, Content-Type, Accept
Of course, the actual syntax depends on the programming language you use for your back-end.
In your front-end, it should be like so:
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
headers.append('Origin','http://localhost:3000');
fetch(sign_in, {
mode: 'cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed: ' + error.message));
}
In my case, I use the below solution.
Front-end or Angular
post(
this.serverUrl, dataObjToPost,
{
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
}
)
back-end (I use PHP)
header("Access-Control-Allow-Origin: http://localhost:4200");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header("Access-Control-Allow-Headers: Content-Type, Authorization");
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
print_r($request);
Using dataType: 'jsonp' worked for me.
async function get_ajax_data(){
var _reprojected_lat_lng = await $.ajax({
type: 'GET',
dataType: 'jsonp',
data: {},
url: _reprojection_url,
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR)
},
success: function (data) {
console.log(data);
// note: data is already json type, you
// just specify dataType: jsonp
return data;
}
});
} // function
Just my two cents... regarding How to use a CORS proxy to get around “No Access-Control-Allow-Origin header” problems
For those of you working with php at the backend, deploying a "CORS proxy" is as simple as:
create a file named 'no-cors.php' with the following content:
$URL = $_GET['url'];
echo json_encode(file_get_contents($URL));
die();
on your front end, do something like:
fetch('https://example.com/no-cors.php' + '?url=' + url)
.then(response=>{*/Handle Response/*})`
If your API is written in ASP.NET Core, then please follow the below steps:
Install the Microsoft.AspNetCore.Cors package.
Add the below line in the ConfigureServices method in file Startup.cs:
services.AddCors();
Add the below line in the Configure method in file startup.cs:
app.UseCors(options =>
options.WithOrigins("http://localhost:8080")
.AllowAnyHeader()
.AllowAnyMethod());
Make sure you add this after - app.UseRouting();
Refer to the below image(from MSDN) to see the middleware order:
https://i.stack.imgur.com/vQ4yT.png
Possible causes of CORS issues
Check your server-side access headers: Refer to this link
Check what request header is received from the server in the browser. The below image shows the headers
If you are using the fetch method and trying to access the cross-origin request make sure mode:cors is there. Refer to this link
Sometimes if there is an issue in the program also you are getting the CORS issue, so make sure your code is working properly.
Make sure to handle the OPTION method in your API.
Adding mode:no-cors can avoid CORS issues in the API.
fetch(sign_in, {
mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
In December 2021, Chrome 97, the Authorization: Bearer ... is not allowed unless it is in the Access-Control-Allow-Headers preflight response (ignores *). It produced this warning:
[Deprecation] authorization will not be covered by the wildcard symbol (*)
See: Chrome Enterprise release notes, Chrome 97
It also appears to enforce the same restriction on * on Access-Control-Allow-Origin. If you want to revive *-like behavior now that it is blocked, you'll likely have to read the requester's origin and return it as the allowed origin in the preflight response.
In some cases, a library may drop the Access-Control-Allow-Origin response header when there is some other invalid credential (example: an expired JWT). Then, the browser shows the "No 'Access-Control-Allow-Origin' header is present" error instead of the actual error (which in this example could be an expired JWT). Be sure that your library doesn't drop the header and confuse the client.
Faced this issue in my react/express app. Adding the below code in server.js (or your server file name) fixed the issue for me. Install cors and then
const cors = require('cors');
app.use(cors({
origin: 'http://example.com', // use your actual domain name (or localhost), using * is not recommended
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Origin', 'X-Requested-With', 'Accept', 'x-client-key', 'x-client-token', 'x-client-secret', 'Authorization'],
credentials: true
}))
Now you can make straightforward API calls from your front-end without having to pass any additional parameters.
With Node.js, if you are using routers, make sure to add CORS before the routers. Otherwise, you'll still get the CORS error. Like below:
const cors = require('cors');
const userRouter = require('./routers/user');
expressApp = express();
expressApp.use(cors());
expressApp.use(express.json());
expressApp.use(userRouter);
In case you are using Node.js and Express.js as the back-end and React & Axios as the front-end within a development environment in macOS, you need to run both sides under HTTPS. Below is what finally worked for me (after many hours of deep dive and testing):
Step 1: Create an SSL certificate
Just follow the steps from How to get HTTPS working on your local development environment in 5 minutes.
You will end up with a couple of files to be used as credentials to run the HTTPS server and React web:
server.key & server.crt
You need to copy them in the root folders of both the front and back ends (in a production environment, you might consider copying them in folder ./ssh for the back-end).
Step 2: Back-end setup
I read a lot of answers proposing the use of 'cors' package or even setting ('Access-Control-Allow-Origin', '*'), which is like saying: "Hackers are welcome to my website". Just do like this:
import express from 'express';
const emailRouter = require('./routes/email'); // in my case, I was sending an email through a form in React
const fs = require('fs');
const https = require('https');
const app = express();
const port = 8000;
// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('*', (req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://localhost:3000");
next();
});
// Routes definition
app.use('/email', emailRouter);
// HTTPS server
const credentials = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
};
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(port, () => {
console.log(`Back-end running on port ${port}`);
});
In case you want to test if the https is OK, you can replace the httpsServer constant by the one below:
https.createServer(credentials, (req: any, res: any) => {
res.writeHead(200);
res.end("hello world from SSL\n");
}).listen(port, () => {
console.log(`HTTPS server listening on port ${port}...`);
});
And then access it from a web browser: https://localhost:8000/
Step 3: Front-end setup
This is the Axios request from the React front-end:
await axios.get(`https://localhost:8000/email/send`, {
params: { /* Whatever data you want to send */ },
headers: {
'Content-Type': 'application/json',
}
})
And now, you need to launch your React web in HTTPS mode using the credentials for SSL we already created. Type this in your macOS terminal:
HTTPS=true SSL_CRT_FILE=server.crt SSL_KEY_FILE=server.key npm start
At this point, you are sending a request from an HTTPS connection at port 3000 from your front-end, to be received by an HTTPS connection at port 8000 by your back-end. CORS should be happy with this ;)
For those using ASP.NET Core:
In my case, I was using JavaScript to make a blob from an image stored on the API (the server), so the URL was pointing to that resource. In that API's program.cs class, I already had a CORS policy, but it didn't work.
After I read the Microsoft documentation (read the first paragraph) about this issue, it is said that if you want to access a resource on the server, by using JavaScript (which is what I was trying to do), then you must call the app.UseCors(); before the app.UseStaticFiles(); which is typically the opposite.
My program.cs file:
const string corsPolicyName = "ApiCORS";
builder.Services.AddCors(options =>
{
options.AddPolicy(corsPolicyName, policy =>
{
policy.WithOrigins("https://localhost:7212");
});
});
...
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(settings =>
{
settings.DisplayRequestDuration();
settings.EnableTryItOutByDefault();
});
app.UseHttpsRedirection();
app.UseCors(corsPolicyName); // 👈 This should be above the UseStaticFiles();
app.UseStaticFiles(); // 👈 Below the UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseApiCustomExceptionHandler();
app.MapControllers();
app.Run();
Remove this:
credentials: 'include',
For a Node.js and Express.js backend I use this :)
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "YOUR-DOMAIN.TLD"); // Update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
For more details: CORS on ExpressJS
I have encountered this error several times over the past few years -- seemingly showing up out of the blue in a previously functioning website.
I determined that Chrome (and possibly other browsers) can return this error when there is some unrelated error that occurs on the server that prevents it from processing the CORS request (and prior to returning an HTTP 500 error).
These all occurred in a .NET Core environment, and I am not sure if it would happen in other environments.
Anyway, if your code has functioned before, and seems correct, consider debugging to find if there is some other error that is firing before you go crazy trying to solve an error that isn't really there.
In my case, the web server prevented the "OPTIONS" method
Check your web server for the options method
Apache: https://www-01.ibm.com/support/docview.wss?uid=ibm10735209
web tier: 4.4.6 Disabling the Options Method https://docs.oracle.com/cd/E23943_01/web.1111/e10144/getstart.htm#HSADM174
nginx: https://medium.com/#hariomvashisth/cors-on-nginx-be38dd0e19df
I'm using "webtier"
/www/webtier/domains/[domainname]/config/fmwconfig/components/OHS/VCWeb1/httpd.conf
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^OPTIONS
RewriteRule .* . [F]
</IfModule>
change to
<IfModule mod_rewrite.c>
RewriteEngine off
RewriteCond %{REQUEST_METHOD} ^OPTIONS
RewriteRule .* . [F]
</IfModule>
In my case, the solution was dumb as hell... Your allowed origin shouldn't have a slash at the end.
E.g., https://example.com/ -> https://example.com
In my case, I had to add a custom header middleware below all the existing middleware. I think some middleware might conflict with the Access-Control-Allow-Origin Header and try to set it according to their needs.
So the code would be something like this:
app.use(cors());
....all other middleware here
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
...your routes
I make this mistake a lot of times, and because of it, I've made a "check-list" to all of you.
Enable CORS on your project: If you're using Node.js (by example) you can use:
npm install cors;
import cors from 'cors';
app.use(cors());
You can manually set the headers like this (if you want it):
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authortization');
res.setHeader('Acces-Control-Allow-Methods', 'GET, POST, PATCH, DELETE');
Remember to add http:// to your API link in your frontend project, some browsers like Chrome do not accept a request using CORS if the request URL isn't HTTP or HTTPS:
http://localhost:3000/api
Check if your project is using a proxy.config.js file. See Fixing CORS errors with Angular CLI proxy.
When the client used to call our backend service from his host username.companyname.com, he used to get the above error
Two things are required:
while sending back the response, send the header whose key is Access-Control-Allow-Origin and value is *:
context.Writer.Header()["Access-Control-Allow-Origin"] = []string{"*"} // Important to avoid a CORS error
Use the Go CORS library to set AllowCredentials to false and AllowAllOrigins to true.
Use the below npm module. This has virtually saved lives.
https://www.npmjs.com/package/local-cors-proxy
You're getting a CORS error, for example like the below URL
https://www.google.co.in/search/list
After successfully installed(local-cors-proxy) global npm install -g local-cors-proxy and set proxy URL that CORS URL.
For example, here the below CORS issue getting in localhost. So you need to add the domain name(https://www.google.co.in) and port(--port 8010) for the CORS issue domain.
For more please check the link
https://www.npmjs.com/package/local-cors-proxy
lcp --proxyUrl https://www.google.co.in --port 8010
After successfully set, it will generate the local proxy URL like below.
http://localhost:8010/proxy
Use that domain name in your project API URL.
API full URL:
http://localhost:8010/proxy/search/list
To get without a CORS issue response in your local project.
Using WebAPI build in .Net Core 6.0
None of the above worked for me... This did it
// global cors policy
app.UseCors(x => x
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(origin => true) // allow any origin
.AllowCredentials());
credit: https://stackoverflow.com/a/70660054/8767516
Try adding all these headers in this code below Before every route, you define in your app, not after the routes
app.use((req, res, next) =>{
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type,Accept, Authortization');
res.setHeader('Acces-Control-Allow-Methods','GET, POST, PATCH, DELETE');
If you are getting this error while deploying React app to netlify, use these steps.
step 1: Create netlify.toml file in the root folder of your react app.
step 2: Copy paste this code:
`[[redirects]]
from = "/cors-proxy/*"
to = ":splat"
status = 200
force = true`
step3: update your fetch/axios api this way:
It took me a while to figure this out.

Dreamhost + Drupal 8 + ReactJS + CORS

Dreamhost support wasn't able to help me much on this, and I've done a lot of googling but to no avail. My client's site has been down for at least 12 hours and I need help getting it back up. There are two levels to this problem because my development server is having a similar, but slightly different issue.
My setup is that I have Drupal 8 running at a subdomain and a ReactJS app being served from the main domain. I have the JSON:API module installed and I'm using the fetch api in React to get data from Drupal. No authentication or other Methods, just getting data for my app to use. Everything worked yesterday and I hadn't changed anything on hosting or deployed any new code.
The initial error I was getting in the browser javascript console was this:
Access to fetch at 'http://CMS_URL/jsonapi/node/person_page' from origin 'http://SITE_URL' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Dreamhost support suggested that I add the following code to my .htaccess file:
Header add Access-Control-Allow-Origin: "*"
Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"
Header add Access-Control-Allow-Headers: "Content-Type"
This is my services.yml file located at /sites/default:
parameters:
cors.config:
enabled: true
# Specify allowed headers, like 'x-allowed-header'.
allowedHeaders: ['x-csrf-token','authorization','content-type','accept','origin','x-requested-with', '*']
# Specify allowed request methods, specify ['*'] to allow all possible ones.
allowedMethods: ['GET']
# Configure requests allowed from specific origins.
allowedOrigins: ['*']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: true
# Sets the Access-Control-Max-Age header.
maxAge: 1000
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: false
When I visit the domain I just get a 403 (Forbidden) error, but on my development server (nodejs) I get the following errors:
Access to fetch at 'http://CMS_URL/jsonapi/node/slide_page/fe770c69-8d4d-489f-9ab9-8e6abce55bb4' from origin 'http://localhost:3000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:3000, *', but only one is allowed. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
AND
Cross-Origin Read Blocking (CORB) blocked cross-origin response http://CMS_URL/jsonapi/node/slide_page/fe770c69-8d4d-489f-9ab9-8e6abce55bb4 with MIME type application/vnd.api+json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
I suspect that there is some issue with these two files not playing well together, but I can't figure out what is causing the problems. I've tried variations on the settings for Access-Control-Allow-Origin and allowedOrigins on .htaccess and services.yml respectively and nothing seems to be changing anything.
Can anyone point me in the right direction?
edited to remove exact urls
After some work with Dreamhost support and some playing around we figured out a solution to this. For this particular configuration, CORS policy has to be correctly configured for the hosting AND Drupal. These are the settings that ended up working for us:
Added the following to the .htaccess file under the domain root of the CMS:
# enable CORS
Header add Access-Control-Allow-Origin: "*"
Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"
Header add Access-Control-Allow-Headers: "Content-Type"
Under the /sites/default directory, added a settings.yml file with the following content:
parameters:
cors.config:
enabled: false
# Specify allowed headers, like 'x-allowed-header'.
allowedHeaders: ['x-csrf-token','authorization','content-type','accept','origin','x-requested-with', '*']
# Specify allowed request methods, specify ['*'] to allow all possible ones.
allowedMethods: ['*']
# Configure requests allowed from specific origins.
allowedOrigins: ['*']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: true
# Sets the Access-Control-Max-Age header.
maxAge: 1000
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: false
The key thing that was tripping us up was how the file changes could be made to be effective. Changes to the .htaccess file were immediately effective, but changes to the settings.yml file required that we clear the cache in Drupal:
Configuration->Development->Performace->Clear cache

How can I get around CORS restrictions with my api calls? [duplicate]

This question already has answers here:
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 3 years ago.
I've been developing a personal fortnite stats web app. I you use two main API calls. One of them has CORS access policy enabled, so in develoment I can get around this by adding the domain as a proxy and adding the path within the fetch request.
When I build this I cannot call the API, so have tried sending the full URL in the fetch request plus adding headers, mode etc to try and meet the CORS policy. I have tried everything but its still not working.
Could anybody help please?
Thanks
app.js level
fetchFortniteData = username => {
return new Promise((resolve, reject) => {
fetch(`/v1/profile/pc/${username}`, {
headers: new Headers({
'TRN-Api-Key': process.env.REACT_APP_TRN
})
})
package.json
"proxy": "https://api.fortnitetracker.com",
The errors I receive from the console are:
Access to fetch at 'https://api.fortnitetracker.com//v1/profile/pc/popps01' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
2fortniteApi.js:57 OPTIONS https://api.fortnitetracker.com//v1/profile/pc/popps01 404
Which is what was happening in development, which is why I added a proxy.
I have also added mode: 'no-cors' and other allow origin keys to the header but it still doesnt work.
In the network tab:
Request URL: https://api.fortnitetracker.com//v1/profile/pc/popps01
Request Method: OPTIONS
Status Code: 404
Remote Address: [2606:4700:20::6819:9810]:443
Referrer Policy: no-referrer-when-downgrade
Provisional headers are shown
Access-Control-Request-Headers: trn-api-key
Access-Control-Request-Method: GET
Origin: http://localhost:3000
Referer: http://localhost:3000/
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1
For anybody that has this problem in the future, if you create an Express app backend and add no cors that will bypass the API cors policy. In development, all you need to do is add a proxy, however, when going into production that will not work so set up an Express backend, point your front-end endpoints to the backend REST requests.
I also hosted the backend on Elastic Beanstalk, the front end of s3 and CloudFront and it works.
Two methods:
Install a chrome extension to Access-control-allow-origin to allow cross-origin redirects.
extention will allow if your backend server is on your local machine
If the backend server is yours(your localhost), put access control allow origin to '*'.
This is the default django server settings (settings file) to allow cors:
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
'GET',
'POST',
'PUT',
'OPTIONS',
)
CORS_ORIGIN_WHITELIST = ('*', )
Do keep this in mind before making your server.

POST request with AngularJS fails with preflight OPTION status code = 404 with CodeIgniter ResetServer

My front-end application is running on a grunt live server on port 9100, while my PHP server is on the port 80. The host is the same, just the port differ.
When I send a POST request to http://dev.site.dev/api/gist with some JSON data, I got an error 404 on the preflight OPTIONS request.
I already added the CORS headers in apache configuration:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "X-Requested-With, accept, content-type"
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
```
and restart the server but still got the issue.
Should I add an index_option() method in my gist controller ? Or the problem is somewhere else ?
As I described in my answer on the CodeIgniter bug tracker for this "issue" #313, there is several solutions.
Application wide
I found a solution from HTTP OPTIONS error in Phil Sturgeon's Codeigniter Restserver and Backbone.js, which is to remove otpions from the list of value in $allowed_http_methods:
// protected $allowed_http_methods = array('get', 'delete', 'post', 'put', 'options', 'patch', 'head');
protected $allowed_http_methods = array('get', 'delete', 'post', 'put', 'patch', 'head');
Resource's focused
Another solution is to simply implement the index_options().
It didn't work for me the first time due to a typo (it's OPTIONS is plural ). And with this solution no more need to temper with applications/libraries/REST_Controller.php:
public function index_options() {
return $this->response(NULL, 200);
}
Now the preflight OPTION request is always true so the POST request is sent and everything works :)
Yes you have to add the index_options() method.
I had the same problem and it only worked when i added the OPTIONS method with the same arguments as my POST method.
in my case it was a routing problem.
What I did is overide the 404 routing. After that, the request got through the routing and the rest server did all the rest.
This is what I put in my routes.php:
$route['404_override'] = 'auth/options';

Resources