I have called third party API using Jquery AJAX. I am getting following error in console:
Cross-Origin Read Blocking (CORB) blocked cross-origin response MY URL with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
I have used following code for Ajax call :
$.ajax({
type: 'GET',
url: My Url,
contentType: 'application/json',
dataType:'jsonp',
responseType:'application/json',
xhrFields: {
withCredentials: false
},
headers: {
'Access-Control-Allow-Credentials' : true,
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'GET',
'Access-Control-Allow-Headers':'application/json',
},
success: function(data) {
console.log(data);
},
error: function(error) {
console.log("FAIL....=================");
}
});
When I checked in Fiddler, I have got the data in response but not in Ajax success method.
Please help me out.
dataType:'jsonp',
You are making a JSONP request, but the server is responding with JSON.
The browser is refusing to try to treat the JSON as JSONP because it would be a security risk. (If the browser did try to treat the JSON as JSONP then it would, at best, fail).
See this question for more details on what JSONP is. Note that is a nasty hack to work around the Same Origin Policy that was used before CORS was available. CORS is a much cleaner, safer, and more powerful solution to the problem.
It looks like you are trying to make a cross-origin request and are throwing everything you can think of at it in one massive pile of conflicting instructions.
You need to understand how the Same Origin policy works.
See this question for an in-depth guide.
Now a few notes about your code:
contentType: 'application/json',
This is ignored when you use JSONP
You are making a GET request. There is no request body to describe the type of.
This will make a cross-origin request non-simple, meaning that as well as basic CORS permissions, you also need to deal with a pre-flight.
Remove that.
dataType:'jsonp',
The server is not responding with JSONP.
Remove this. (You could make the server respond with JSONP instead, but CORS is better).
responseType:'application/json',
This is not an option supported by jQuery.ajax. Remove this.
xhrFields: {
withCredentials: false },
This is the default. Unless you are setting it to true with ajaxSetup, remove this.
headers: {
'Access-Control-Allow-Credentials' : true,
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'GET',
'Access-Control-Allow-Headers':'application/json',
},
These are response headers. They belong on the response, not the request.
This will make a cross-origin request non-simple, meaning that as well as basic CORS permissions, you also need to deal with a pre-flight.
In most cases, the blocked response should not affect the web page's behavior and the CORB error message can be safely ignored. For example, the warning may occur in cases when the body of the blocked response was empty already, or when the response was going to be delivered to a context that can't handle it (e.g., a HTML document such as a 404 error page being delivered to an tag).
https://www.chromium.org/Home/chromium-security/corb-for-developers
I had to clean my browser's cache, I was reading in this link, that, if the request get a empty response, we get this warning error. I was getting some CORS on my request, and so the response of this request got empty, All I had to do was clear the browser's cache, and the CORS got away. I was receiving CORS because the chrome had saved the PORT number on the cache, The server would just accept localhost:3010 and I was doing localhost:3002, because of the cache.
Return response with header 'Access-Control-Allow-Origin:*'
Check below code for the Php server response.
<?php header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
echo json_encode($phparray);
You have to add CORS on the server side:
If you are using nodeJS then:
First you need to install cors by using below command :
npm install cors --save
Now add the following code to your app starting file like ( app.js or server.js)
var express = require('express');
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser');
//enables cors
app.use(cors({
'allowedHeaders': ['sessionId', 'Content-Type'],
'exposedHeaders': ['sessionId'],
'origin': '*',
'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'preflightContinue': false
}));
require('./router/index')(app);
It's not clear from the question, but assuming this is something happening on a development or test client, and given that you are already using Fiddler you can have Fiddler respond with an allow response:
Select the problem request in Fiddler
Open the AutoResponder tab
Click Add Rule and edit the rule to:
Method:OPTIONS server url here, e.g. Method:OPTIONS http://localhost
*CORSPreflightAllow
Check Unmatched requests passthrough
Check Enable Rules
A couple notes:
Obviously this is only a solution for development/testing where it isn't possible/practical to modify the API service
Check that any agreements you have with the third-party API provider allow you to do this
As others have noted, this is part of how CORS works, and eventually the header will need to be set on the API server. If you control that server, you can set the headers yourself. In this case since it is a third party service, I can only assume they have some mechanism via which you are able to provide them with the URL of the originating site and they will update their service accordingly to respond with the correct headers.
If you are working on localhost, try this, this one the only extension and method that worked for me (Angular, only javascript, no php)
https://chrome.google.com/webstore/detail/moesif-orign-cors-changer/digfbfaphojjndkpccljibejjbppifbc/related?hl=en
In a Chrome extension, you can use
chrome.webRequest.onHeadersReceived.addListener
to rewrite the server response headers. You can either replace an existing header or add an additional header. This is the header you want:
Access-Control-Allow-Origin: *
https://developers.chrome.com/extensions/webRequest#event-onHeadersReceived
I was stuck on CORB issues, and this fixed it for me.
have you tried changing the dataType in your ajax request from jsonp to json? that fixed it in my case.
There is an edge case worth mentioning in this context: Chrome (some versions, at least) checks CORS preflights using the algorithm set up for CORB. IMO, this is a bit silly because preflights don't seem to affect the CORB threat model, and CORB seems designed to be orthogonal to CORS. Also, the body of a CORS preflight is not accessible, so there is no negative consequence just an irritating warning.
Anyway, check that your CORS preflight responses (OPTIONS method responses) don't have a body (204). An empty 200 with content type application/octet-stream and length zero worked well here too.
You can confirm if this is the case you are hitting by counting CORB warnings vs. OPTIONS responses with a message body.
It seems that this warning occured when sending an empty response with a 200.
This configuration in my .htaccess display the warning on Chrome:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST,GET,HEAD,OPTIONS,PUT,DELETE"
Header always set Access-Control-Allow-Headers "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]
But changing the last line to
RewriteRule .* / [R=204,L]
resolve the issue!
I have a similar problem. My case is because the contentType of server response is application/json, rather than text/javascript.
So, I solve it from my server (spring mvc):
// http://127.0.0.1:8080/jsonp/test?callback=json_123456
#GetMapping(value = "/test")
public void testJsonp(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
#RequestParam(value = "callback", required = false) String callback) throws IOException {
JSONObject json = new JSONObject();
json.put("a", 1);
json.put("b", "test");
String dataString = json.toJSONString();
if (StringUtils.isBlank(callback)) {
httpServletResponse.setContentType("application/json; charset=UTF-8");
httpServletResponse.getWriter().print(dataString);
} else {
// important: contentType must be text/javascript
httpServletResponse.setContentType("text/javascript; charset=UTF-8");
dataString = callback + "(" + dataString + ")";
httpServletResponse.getWriter().print(dataString);
}
}
Response headers are generally set on the server. Set 'Access-Control-Allow-Headers' to 'Content-Type' on server side
I had the same problem with my Chrome extension. When I tried to add to my manifest "content_scripts" option this part:
//{
// "matches": [ "<all_urls>" ],
// "css": [ "myStyles.css" ],
// "js": [ "test.js" ]
//}
And I remove the other part from my manifest "permissons":
"https://*/"
Only when I delete it CORB on one of my XHR reqest disappare.
Worst of all that there are few XHR reqest in my code and only one of them start to get CORB error (why CORB do not appare on other XHR I do not know; why manifest changes coused this error I do not know). That's why I inspected the entire code again and again by few hours and lost a lot of time.
I encountered this problem because the format of the jsonp response from the server is wrong. The incorrect response is as follows.
callback(["apple", "peach"])
The problem is, the object inside callback should be a correct json object, instead of a json array. So I modified some server code and changed its format:
callback({"fruit": ["apple", "peach"]})
The browser happily accepted the response after the modification.
Try to install "Moesif CORS" extension if you are facing issue in google chrome. As it is cross origin request, so chrome is not accepting a response even when the response status code is 200
Related
I was trying to get the data from a json file (which is on the remote server) from localhost and I am getting error 'from origin 'http://localhost:5000' 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.'
Below is the code I used to send the get request.
$.ajax({
url: 'http://abc/some.json',
type: "GET",
dataType: "json",
headers: {
"Access-Control-Request-Headers": "*",
"Access-Control-Request-Method": "*",
'Content-Type':'application/json'
},
success: function (data) {
alert(data);
chatbotConfig = data;
console.log(chatbotConfig);
}
})
I am able to get the data using postman. I understand that postman is not a browser so it is not limited by CORS policy. But I am able to download the content from json file directly from the browser. Nit able to understand why I am facing issue when I tried to access from localhost. Can any one please help me to resolve this issue.
Well, the CORS error may lie in different layers of your application. Usually, by allowing all (*) origins and headers in the server-side, your problem should be fixed. But sometimes it won't and it lies somewhere else like your HTTP request header or body, DNS settings (Making sure there are no third-party DNS set in your network by yourself through the OS), or browser settings. So I will describe all of the possible solutions here shortly.
NOTE: You can read more about CORS policy here.
How to solve CORS error
If you have access to your server-side settings and/or options you need to make sure (Or if you don't you need to ask your backend developer) that everything set correctly there or not. So the steps will be as follows:
First of all, you need to make sure your server configs for CORS are set correctly.
So for example, if you are using Apache you can set the CORS policy in your .htaccess file like this (or simply check if it exists):
// This will allow all origins to access your server
Header set Access-Control-Allow-Origin "*" // You can set * to whatever domain
Header add Access-Control-Allow-Methods "*"
If you are using nodeJS you can check or set it like this:
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
If you are using Nginx you can check or set it in nginx.conf like this:
server {
location / {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "*";
}
}
If you use any other service for your server-side you should read the documentation about it, but all of them are actually same.
If you checked the above step and CORS policy was set correctly in your server-side, you may need to check your HTTP request and make sure everything is set correctly there. For example, there is no need to add these two headers
"Access-Control-Request-Headers": "*",
"Access-Control-Request-Method": "*",
in your request, because they do not exist as a header in the client-side. Wrong HTTP request API end-point address or options (like dataType), wrong HTTP request body or headers may also cause the CORS error for your here. So you need to check them all and make sure you are set them correctly.
If none of the above was the problem you can try two other approaches. I mostly encourage to use the second one if none of the above solves your problem.
Mapping your localhost to a URL using your hosts file (Usually lies under etc folder in each operating system). You can do that like this (But it's better to read the documentation for each OS).
127.0.0.1 www.test.com ## map 127.0.0.1 to www.test.com
## or
localhost www.test.com
NOTE: Usually it is better to avoid this approach.
Use browser plugins like Allow CORS.
Basically if you clearly look into the issue logs:
'from origin 'http://localhost:5000' 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
It's saying CORS not enabled at resource. which means it need to be fixed or allowed at server side.
I can't execute the 'GET' request with the getTasks() function.
$(document).ready(function(){
getTasks();
});
const apiKey = 'xxxxxxx';
function getTasks(){
$.ajax({
type: 'GET',
url: 'https://api.mlab.com/api/1/databases/taskmanager/collections/tasks?apiKey='+apiKey,
contentType: 'application/json',
xhrFields: {
withCredentials: true
},
success: function(data){
console.log(data);
},
error: function(){
console.log('FAIL')
}
})
}
The error that I get is:
api.mlab.com/api/1/databases/taskmanager/collections/tasks?apiKey=xxxxxxx
Failed to load resource: the server responded with a status of 400
(Bad Request)
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access. The response
had HTTP status code 400.
I understand that Google-Chrome on Windows is CORS enabled, and will not (by default) allow communication with a different domain. I'm not sure what a preflight request is. Regardless, I tried to implement what I saw from Using CORS - HTML5 Rocks (from the CORS from jQuery section), but to no avail.
At a guess, the remote API simply does not respond to pre-flight requests for GET calls (because it shouldn't have to).
Your code is triggering a pre-flight request because it is non-simple. This is due to your adding a Content-type: application/json header. A request Content-type header is used to indicate the request payload format. As it is a GET, there is no payload.
Try this instead...
$.getJSON('https://api.mlab.com/api/1/databases/taskmanager/collections/tasks', {
apiKey: apiKey
}).done(function(data) {
console.log(data)
}).fail(function() {
console.log('FAIL')
})
CORS is there to protect you. If you want some more info on it, wikipedia has a good entry on it.
It appears the issue here is that you're trying to access your mongodb hosted by mlab directly from your web app. As you can see in your code, you're providing credentials/api keys to make that request.
My guess is that mlab's intent of not allowing CORS is to prevent you from doing this. You should never put your private API keys in html to be hosted on a web page, as it's easily accessible by reading source code. Then someone would have direct access to your mongodb.
Instead, you should create a server-side application (node, or... ** Whatever **) that exposes an api you control on the same domain (or a domain you give permission to via CORS).
As far as the "preflight" request, if you look in your chrome debugging tools, you should see an additional request go out with the "OPTIONS" method. This is the request that chrome (and most other http clients) send out first to a server hosted on a different domain. it's looking for the Access-Control-Allow-Origin header to find out whether it's allowed to make the request. Pretty interesting stuff if you ever have some time to dig into it.
I can access the (secure) website without problems when I run the HTTP.get and HTTP.post commands from the server, using headers to identify myself via a cookie and with the required credentials. I'm using the HTTP package.
However I want the same to happen from the client itself. Here's the code on the client side:
HTTP.get('https://www.securewebsite.com/login1.php', {
timeout: 30000,
headers: {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Upgrade-Insecure-Requests": "1",
// "DNT": "1",
"Accept-Language": "en-US,en;q=0.8,de;q=0.6"
// 'Accept-Charset' : 'utf-8',
// "Cookie": cookie
}
}, function (err, res) {
if (err) {
// some error handling code
} else {
// doing something with res
}
});
I had to comment out the Accept-Charset, DNT and cookie headers as they were flagged as insecure. Error message eg for DNT: Refused to set unsafe header "DNT" (same for other headers)
However even then I get OPTIONS shown in the browser inspector (Chrome) and the following error message shows up:
XMLHttpRequest cannot load https://www.securewebsite.com/login1.php. 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:3000' is therefore not allowed access. The response had HTTP status code 501.
Please note than https://www.securewebsite.com/login1.php is just an example, not the real website I'm calling. You can try http://www.awest.de/ as a real example. As seen from the error message I'm currently calling it from local.
Any idea how I can achieve this? Am I missing some specific header? I've tried other URL's as well (including my own webspace) but I get the same error message, so it doesn't has anything to do with the URL I'm trying to GET from. It seems more a browser issue where it wants to stop some x-script execution (if I understand it correctly from what I read).
To explain why I want to access it from the browser: I don't want to violate the server's policy and thus requests should come from the clients IP-address and not my servers IP-address. I'm using two apps, one is just hosting the client side code and a second one is hosting only server side code.
Thanks for your help in advance, appreciated!
Looks like problem with cors.
Try the headers inside php/js script (back-end/cors):
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
I'm developing a phonegap App with html5, css, js and jQuery Mobile and I need to connect to a webservice which is already done and fully working. The problem is the Access Control Allow Origin and the Cross Domain. As if it wasn't hard enough I have to think about the authentication too, essential to connect to the web service. I already done my research, read a lot of tuts, tried a lot of solutions, some of them using jsonP which looked to me the closest one to work. The thing is I'm new at this and no tutorial looked good, so hopefully someone here could lead me the way. The webService was build in asp.net and I have full access to it if it's needed. I'm using AJAX to make the "call" but I can't pass the ForeFront authentication .
Here's the JS+AJAX code:
function conteudoProg() {
var webMethod = "myURL";
var credentials = {
username : "myUser",
password : "myPass"
};
$.ajax({
type : "GET",
url : webMethod,
//data: credentials,
contentType : "application/json; charset=utf-8",
dataType : "jsonp",
success : function(msg) {
alert(msg);
},
error : function(e) {
alert(e.status + " " + e.statusText );
}
});
}
If I change my dataType from jsonp to json, I get this error:
OPTIONS https://myURL 440 (Login Timeout)
XMLHttpRequest cannot load https://myURL Origin http://127.0.0.1:8020 is not allowed by Access-Control-Allow-Origin.
With jsonp, the error looks like this:
Resource interpreted as Script but transferred with MIME type text/html: "https://myURL/CookieAuth.dll?GetLogon?curl=Z2FWSInqueritosZ2FServ…1820135927463_1359737732559Z26_Z3D1359737732605&reason=0&formdir=3". jquery-1.8.2.min.js:2
Uncaught SyntaxError: Unexpected token <
Requests to another domain will cause a pre-flight OPTIONS request to see whether the requesting domain can make calls to this domain.
The receiving end needs to emit the correct headers or your browser will block the request and give you the error you posted.
Say you are requesting from mydomain.com to webservice.com
Then webservice.com/api should emit these headers:
Access-Control-Allow-Origin: http[s]://mydomain.com
Access-Control-Allow-Credentials: true # if you want cookies
Access-Control-Allow-Headers: Content-Type, X-Custom-Header # any extra headers you want to send
Make sure the webservice knows about OPTIONS requests. It really only needs to emit some CORS headers, it doesn't need to do anything else (like process a request to it's API).
You don't need to change anything in your AJAX handler, it will pass as any other request. If you want cookies make sure to set http_request.withCredentials = true;
Keep in mind that an HTTPS URL is considered to be different from an HTTP domain and make sure your HTTPS certificate is valid, if it's not valid the request may fail silently. If you're using a self-signed certificate (for testing) add it to your browser or OS whitelist.
Cross domain request from HTTP to HTTPS aborts immediately
As for compatibility. Earlier versions of Internet Explorer (8 and lower) use ActiveXObject, this API is very bad at CORS. It doesn't support authentication/cookies or custom headers (such as Content-Type: application/JSON). I would recommend a JSONp fallback.
The code does not work because when you tell jQuery that the .ajax method expects a dataType json, that's what's trying to parse the response into. If the response is html then you should use a dataType html (or none, to let the default intelligent guess do it's work). See jQuery.ajax() dataType for more info.
I have two domains. I'm trying to access a JSON object from one domain through a page on another. I've read everything I could find regarding this issue, and still can't figure this out.
The domain serving the JSON has the following settings:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, OPTIONS"
Header set Access-Control-Allow-Headers "origin, authorization, accept"
From my other domain, I'm calling the following:
$.ajax({
type:'get',
beforeSend: function(xhr) {
var auth = // authentication;
xhr.setRequestHeader("Authorization", "Basic " + auth);
}
url:myUrl,
dataType:'json',
error: function(xhr, textStatus, errorThrown) { console.log(textStatus, errorThrown); }
})
I know that 'auth' is initialized properly (logged and checked). However, this does not work. In Firefox's Console, I get
Request URL: ...
Request Method:
OPTIONS
Status Code:
HTTP/1.1 401 Authorization Required
If I get rid of the beforeSend:... part, I see the following
Request Method:
GET
Status Code:
HTTP/1.1 401 Authorization Required
However, the domain serving JSON also can serve JSONP. I don't want to use this, mainly because the application will be running constantly on a dedicated browser, and I'm worried about this issue. More importantly, I would really like to know what is actually wrong with what I am doing. I know that for practical purposes there are various ways to overcome the JSONP memory leak (such as not using jQuery).
At any rate, when I did use JSONP, my code looked like this:
$.ajax({
url:newUrl,
dataType:'jsonp',
jsonp:'jsonp'
}).done(function(d){console.log(d)})
This gets the following
Request Method:
GET
Status Code:
HTTP/1.1 200 OK
after it prompts me with an alert box for a username and password.
Is there a fundamental difference in the way jQuery handles JSONP requests as opposed to JSON requests? And if so, how can I fix this?
Thanks.
Edit: Here's what I did find.
Basically, because I need authentication, the GET request is sending an Authorization header. However, this is not a "simple" header, and so the browser is sending a pre-flight request (the OPTIONS). This preflight request doesn't have any authentication, though, and so the server was rejecting it. The "solution" was to set the server to let OPTIONS request not require authentication, and report an HTTP status of 200 to it.
Reference: http://www.kinvey.com/blog/item/61-kinvey-adds-cross-origin-resource-sharing-cors
mail-archive[.com]/c-user#axis.apache.org/msg00790.html (not allowed to post more links)
Unfortunately, the "solution" is only working on Firefox and not Chrome. Chrome simply shows the request in red, but doesn't give me any more info on why it failed.
Edit 2: Fixed on Chrome: The server I was trying to get data from had a security certificate which was not trusted. The preflight request on Chrome failed because of this. Solution
superuser[.com]/questions/27268/how-do-i-disable-the-warning-chrome-gives-if-a-security-certificate-is-not-trust (not allowed to post more links)
Welp, now that I have enough rep a while later, I might as well answer this question and accept it.
When you attempt to send a GET json request to a server with headers, the browser first sends an OPTION request to make sure that you can access it. Unfortunately, this OPTION request cannot carry with it any authentication. This means that if you want to send a GET with auth, the server must allow an OPTION without auth. Once I did this, things started working.
Some examples available here may illustrate further how access control can be combined with CORS. Specifically the credentialed GET example. Access control requires that the request set the withCredentials flag to true on the XMLHttpRequest, and for the server handling the OPTIONS method to do two things:
Set Access-Control-Allow-Credentials: true
Not use a wildcard * in the Access-Control-Allow-Origin header. This has to be set to the origin exactly according to the MDN docs on HTTP access control (CORS).
Essentially, the thing processing the OPTIONS request needs to send back appropriate response headers so you can make that credentialed request.
In your question you stated that the service you are interacting with is returning Access-Control-Allow-Origin: *, which is not compatible with a credentialed cross-domain request. This needs to return the origin specifically.
The aforementioned MDN Http Access Control (CORS) documentation also links to the Server-Side Access Control documentation outlining how a server would potentially respond to various cross domain requests - including handling a cross domain credentialed POST request that requires you to send back the correct headers in response to the OPTIONS method. You can find that example here.
Why don't you try typing the URL you are fetching the JSON from into your browser and seeing what happens. It sounds like you literally just need to authenticate into this other website to access it.
If your site needs to work in other browsers like IE, you WILL need JSONP, by the way. The security won't allow the cross site request to work. The headers won't change that. I believe you will also need to add a security policy in your headers.