I have problem with CORS. I already search many time in google to solve this problem, but doesn't work.
I make a popup dialog procedure with external popup.js file. This js file can show popup dialog when I call that file from any page in same project(myweb.com).
But the problem is when I call this js file from another website like this,
<script type="text/javascript" src="http://www.myweb.com/admin/popup.js"></script>
<script> document.addEventListener("DOMContentLoaded", function(event) {
create_popup();
});
</script>
I get this error,
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://www.myweb.com/admin/get_data.php?t=0.4987759219367701.
(Reason: missing token 'access-control-allow-methods' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel).
In my js file I run get_data.php file by using ajax. Here is my js file,
function create_popup() {
var xmlhttp = new XMLHttpRequest();
if("withCredentials" in xmlhttp){
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var arr = JSON.parse(xmlhttp.responseText);
alert(arr);
}
xmlhttp.open("GET","http://www.myweb.com/admin/get_data.php?t="+Math.random(),true);
xmlhttp.setRequestHeader( "Pragma", "no-cache" );
xmlhttp.setRequestHeader( "Cache-Control", "no-cache" );
xmlhttp.setRequestHeader("Access-Control-Allow-Origin","*");
xmlhttp.setRequestHeader("Access-Control-Allow-Credentials", "true");
xmlhttp.setRequestHeader("Access-Control-Allow-Methods", "GET");
xmlhttp.setRequestHeader("Access-Control-Allow-Headers", "Content-Type");
xmlhttp.send();
}else{
alert("error");
console.log("error");
}
}
This js file is only work in myweb.com. But when I try to call this js from another website I get CORS error.
And I also add header for CORS in get_data.php file like this,
header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods:GET");
header("Access-Control-Allow-Headers:Content-Type");
header("Access-Control-Allow-Credentials:true");
But it doesn't work. I'm not sure about header declaration is ok or not in js and php file. I try a lot but I don't know how to solve.
And I already try in chrome browser with Allow-Control-Allow-Origin extensions. But I can't see popup and error. I don't know which part is wrong. I very appreciate for your suggestion.
(Reason: missing token 'access-control-allow-methods' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel).
This shows that the preflight is failing
preflight only occurs under certain conditions, one of which is when you add "custom" headers to the request
as you are incorrectly adding headers to your request (headers which only make sense as response headers anyway)
xmlhttp.setRequestHeader("Access-Control-Allow-Origin","*");
xmlhttp.setRequestHeader("Access-Control-Allow-Credentials", "true");
xmlhttp.setRequestHeader("Access-Control-Allow-Methods", "GET");
xmlhttp.setRequestHeader("Access-Control-Allow-Headers", "Content-Type");
a preflight is triggered (as they are custom headers) - your server doesn't handle (doesn't even ALLOW) preflight, hence the preflight error
Remove those setRequestHeader lines, and it should work
Related
We’re making a request for an API from one of our online-distributors.
However, we get a CORS-Error.
Access to XMLHttpRequest at 'https://api.cloud.im/marketplace/eu/products' from origin 'http://www.im-cmp.ch' 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.
We did the request in Postman and it worked. I tried to set the requestHeaders the exact same way they are set in Postman (including the hidden headers), however, there is an Error since the hidden headers can’t be set.
Refused to set unsafe header "Host"
Is this a client or a server problem? Am I maybe missing a requestHeader?
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://api.cloud.im/marketplace/eu/products");
xhr.setRequestHeader("X-Subscription-Key", "OUR PERSONAL SUBSCRIPTION KEY");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "OUR BEARER TOKEN");
// xhr.setRequestHeader("Host", "http://www.im-cmp.ch/");
xhr.setRequestHeader("accept", "*/*");
// xhr.setRequestHeader("Accept-Encoding", "gzip, deflate, br");
// xhr.setRequestHeader("Connection", "keep-alive");
xhr.send();
This is definitely a server problem.
The server has to send the Access-Control-Allow-Origin-header: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS.
Also, the error states that this happened during a preflight-request, meaning there was a OPTIONS request made beforehand, which would also need the response-header(s) needed for CORS.
The request works in Postman, since CORS is a feature only really relevant in browsers, to protect users.
Edit:
Also it is important that the server allows the request-headers you are sending using the Access-Control-Allow-Headers-header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
I'm trying to do an AJAX request to https://developers.zomato.com/api/v2.1/search referring to Zomato API
The server has headers:
"access-control-allow-methods": "GET, POST, DELETE, PUT, PATCH, OPTIONS",
"access-control-allow-origin": "*"
The problem is that the API requires additional headers set for user-key. But whenever I set custom headers then chrome would do a pre-flight request by sending an OPTIONS request to the above URL which is failing, and thus the AJAX request is failing as well.
If I don't set the headers, then I don't get a CORS error, but rather a forbidden error from server since I'm not setting user-key header.
Any way to go about this catch-22 situation?
Both Jquery and JavaScript way are failing:
$(document).ready(function () {
$.ajax({
url: 'https://developers.zomato.com/api/v2.1/search',
headers: {
'Accept': 'application/json',
'user_key': 'XXXXX'
},
success: function (data) {
console.log(data);
}
});
});
var xhr = new XMLHttpRequest();
var url = 'https://developers.zomato.com/api/v2.1/search';
xhr.open('GET', url, false);
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('user_key', 'XXXXXX');
xhr.send(null);
if (xhr.status == 200) {
console.log(xhr.responseText);
}
Error I'm getting:
OPTIONS https://developers.zomato.com/api/v2.1/search
XMLHttpRequest cannot load https://developers.zomato.com/api/v2.1/search. 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:8000' is therefore not allowed access. The response had HTTP status code 501.
If somebody wants to reproduce you can get a free user-key here:
https://developers.zomato.com/api
There does not appear to be a work-around for this issue from a browser. The CORS specification requires a browser to preflight the request with the OPTIONS request if any custom headers are required. And, when it does the OPTIONS preflight, it does not include your custom headers because part of what the OPTIONS request is for is to find out what custom headers are allowed to be sent on the request. So, the server is not supposed to require custom headers on the OPTIONS request if it wants this to work from a browser.
So, if the server is requiring the custom headers to be on the OPTIONS request, then the server is just expecting something that will not happen from a browser.
See related answers that describe more about this here:
jQuery CORS Content-type OPTIONS
Cross Domain AJAX preflighting failing Origin check
How do you send a custom header in a cross-domain (CORS) XMLHttpRequest?
Using CORS for Cross-Domain Ajax Requests
And, another user with the same issue here:
Zomato api with angular
It appears the Zomato is not browser friendly, but requires access from a server where you don't have CORS restrictions.
FYI, the error coming back from Zomato is 501 which means NOT IMPLEMENTED for the OPTIONS command. So, it looks like it's not only that the key is not being sent with the OPTIONS command, but that Zomato does not support the OPTIONS command, but that is required for the use of custom headers on a cross-origin request from a browser.
You can't bypass Access-Control-Allow-Headers in preflight response.
However as mentioned by #Jaromanda X in comments, Zomato sends:
Access-Control-Allow-Headers:X-Zomato-API-Key
...meaning you can only send this non-standard header from browser. Also don't go too low-level in request definition when jQuery has pretty and prepared shorthands ...
TL;DR Working example:
$.ajax({
type: "GET", //it's a GET request API
headers: {
'X-Zomato-API-Key': 'YOUR_API_KEY' //only allowed non-standard header
},
url: 'https://developers.zomato.com/api/v2.1/dailymenu', //what do you want
dataType: 'json', //wanted response data type - let jQuery handle the rest...
data: {
//could be directly in URL, but this is more pretty, clear and easier to edit
res_id: 'YOUR_RESTAURANT_OR_PLACE_ID',
},
processData: true, //data is an object => tells jQuery to construct URL params from it
success: function(data) {
console.log(data); //what to do with response data on success
}
});
I am trying to make request with XMLHttpRequest from file://example.html to http://localhost/index.php. I read a lot about CORS(in this case origin is null, this is OK.) and i have no idea what i am doing wrong.
My request finishes well but the $_POST is empty! Except if i set "Content-type: application/x-www-form-urlencoded". But "text/plain" or "application/json" gives no result in $_POST... Why?
xhr.open("POST", "http://localhost/index.php", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = handler;
xhr.send({'a':'12'});
You are probably doing one of these two things wrong:
If the content-type is not application/x-www-form-urlencoded, CORS must send a preflight request. That means that the browser will send before doing the POST request an OPTIONS request, which is used to determine if the POST request is allowed. Take a look here how this works.
Secondly, if you use xhr.setRequestHeader("Content-Type", "application/json"), the $_POST parameters will not be filled with parameters, this is only the case for application/x-www-form-urlencoded. To get the JSON you send, you will have to do:
<?php
$input = json_decode(file_get_contents("php://input"), true);
echo $input['a']; //echoes: 12
For more info, see this question.
Furthermore, if you go into the debugging facilities of any decent browser, it will create an error message if the CORS request is not allowed, please be sure to check if the CORS request was actually made by the browser.
I hope this helps you.
complementing #user23127 response
server side should have something like this to respond to the OPTIONS preflight request:
if (request.method === 'OPTIONS') {
htmlRes = HttpResponse()
htmlRes['Access-Control-Allow-Origin']='*' // or your not origin domain
htmlRes['Access-Control-Allow-Methods']='*' // or POST, GET, PUT, DELETE
htmlRes['Access-Control-Allow-Headers']='*' // Content-Type, X-REQUEST
}
// the rest of the code as if it was not a CORS request
Hi I'm working on connecting to an API that is using Layer 7 as an IP authorizer and eGalaxy as a credentials authorizer, when the curl request is sent a line of xml is sent back to me. I'm currently working on localhost, I've implemented the Access-Control-Allow-Origin chrome extension.
My curl request looks as such:
curl https://client-url/eGalaxy.aspx -H 'Content-Type:text/html' --data '<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header><SourceID>0</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password*</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>' --insecure
When I tried to create an ajax request I receive an "Invalid HTTP status code 500" error and "OPTIONS url" which drops down to show:
n.ajaxTransport.k.cors.a.crossDomain.send # jquery-2.1.3.js:4
n.extend.ajax # jquery-2.1.3.js:4
(anonymous function) # VM947:2
InjectedScript._evaluateOn # VM899:895
InjectedScript._evaluateAndWrap # VM899:828
InjectedScript.evaluate # VM899:694
My ajax code is as follows:
$.ajax({
url:'https://client-url/eGalaxy.aspx',
data:'<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header>
<SourceID>0</SourceID><MessageID>131</MessageID>
<MessageType>Authenticate</MessageType></Header><Body>
<Authenticate><Username>*username*</Username>
<Password>*password*</Password>
<PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body>
</Envelope>',
type:'POST',
contentType:'text/xml',
dataType:'xml',
success: function(data){
},
error: function(){
}
});
Any help with translating into a proper AJAX request would be appreciated!
EDIT: If this makes a difference these are the headers that are returned with the client's xml when the curl is complete(client information deleted)
This application will be made into a widget as well, so it will not be running off of a hosting site.
UPDATE 1: I'm using #KevinB's suggestion that the CORS headers were still not properly added.
Here is my updated JS code, copied from this link:
var url = 'https://client-url/eGalaxy.aspx';
var data = '<?xml version="1.0" encoding="UTF-8"?><Envelope><Header><SourceID>1</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>';
var xhr = createCORSRequest('POST', url);
xhr.send(data);
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHTTPRequest2 objects.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
When run with the CORS Chrome extension off I receive an Access-Control-Allow-Origin =! 'null' error. Knowing that CORS needs Access-Control-Allow-Origin header to =! 'null' will this cause problems in the future with making this into a widget that will be put into a Content Manager system?
With it on the origin is set to 'www.evil.com', with the only error in the code being that it says the xhr.send() is an anonymous method. Using breakpoints I can see the xhr in xhr.send() is set to an empty request:
> XMLHttpRequest {response: "", responseText: ""}
Inside the createCORSRequest this line is undefined. I've tested using 'GET' and 'POST' as the method.
xhr.open(method, url, true)
EDIT 2:
Using #Fabiano's approach I've changed the web.config for two versions of what I suspect is my server(?). I'm attaching screenshots of what I've gone through
No luck, so far. Decided to use xhr.AppendHeader:
I decided to use xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
The Network tab Headers for eGalaxy.aspx
There is an error in your XML. You put version:"1.0", and this makes the XML invalid.
Change to version="1.0" and try to make your request. It should work.
This may be the cause for the "Bad request" error.
You can validate your XML here: enter link description here
EDIT: After some research, the problem may be with the headers sent by your server. Your server (or page, .aspx in this case) seems to skip the header you need, the "Access-Control-Allow-Origin: *".
Look at this link: http://enable-cors.org/server.html
This site shows you how to implement it for your server. Since the page you are requesting is called eGalaxy.aspx, then you have 2 ways to implement the headers:
1- Put the line Response.AppendHeader("Access-Control-Allow-Origin", "*"); if the page is a simple ASP.NET application. If it uses Web API 2, you need to implement a different way as it is shown here: http://enable-cors.org/server_aspnet.html
2- Edit the web.config file on the root of your server and add these lines inside the tag:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
For a ASP.NET application, these are the ways you have. The link I mentioned has solutions for other applications, take a look and choose the right one. :)
Note that the value * tells you that your server will accept any cross-origin request. This may lead to a security issue, so the best you can do is to put your domain address instead of *.
I hope it helps!
I am trying to access a public web service provided by USGS. According to the web page, they support CORS, and even provided a JQuery example (one thing worth to mention is that the example sets no header), but I tried everything and so far have no luck. There are lots of posts about cross-domain ajax and CORS on stackoverflow, but none has helped so far.
I tried both plain XMLHttpRequest and JQuery, with and without various headers, nothing worked. The plain one give back status code 0, which I believe it is an indicator that the request was blocked somewhere.
Anybody had successful experience with javascript CORS, either plain or with jquery?
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
function callWebService() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
alert(xmlhttp.responseText);
} else {
alert(xmlhttp.status);
}
}
};
xmlhttp.open("GET", "http://waterservices.usgs.gov/nwis/iv/?format=json&sites=01646500¶meterCd=00060", true);
//xmlhttp.setRequestHeader("Accept","text/plain");
xmlhttp.setRequestHeader("Access-Control-Allow-Headers", "x-requested-with, x-requested-by, Content-Type");
xmlhttp.setRequestHeader("Access-Control-Allow-Origin", "*");
xmlhttp.setRequestHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
xmlhttp.setRequestHeader("Access-Control-Max-Age", "604800");
xmlhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xmlhttp.send();
}
function callWebServiceWithJQuery() {
$(document).ajaxError(
function (event, jqXHR, ajaxSettings, thrownError) {
alert('[event:' + objToString(event) + '], [jqXHR:' + objToString(jqXHR) + '], [ajaxSettings:' + objToString(ajaxSettings) + '], [thrownError:' + objToString(thrownError) + '])');
});
$.ajax({
/*beforeSend: function (request) {
request.setRequestHeader("Access-Control-Allow-Headers", "x-requested-with, x-requested-by, Content-Type");
request.setRequestHeader("Access-Control-Allow-Origin", "*");
request.setRequestHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
request.setRequestHeader("Access-Control-Max-Age", "604800");
},*/
url: "http://waterservices.usgs.gov/nwis/iv/?format=json&sites=01646500¶meterCd=00060",
dataType:'json',
data:'',
success: function(response) {
alert("succ");
alert(response);
},
error: function(a,b,c) {
alert("err");
alert(a);
alert(b);
alert(c);
}
});
}
</script>
</head>
<body>
<form>
<button onclick="callWebService();">Click me</button>
</form>
</body>
</html>
You have two problems.
Leaving the page
You are triggering the Ajax request in response to a submit button being clicked.
Immediately after sending the request, the form submits and you leave the page, which causes the browser to abort the Ajax request.
The usual way to prevent the form from submitting when you are using an onclick attribute is to return false; from it. Now we are in the 21st century, however, I urge you to learn about addEventListener and move on from onclick.
Making a non-simple request
You are setting a bunch of custom request headers. These all require that the browser makes a pre-flight OPTIONS request to ask permission to make a cross-domain Ajax request with custom headers. The server doesn't grant permission for that. Don't set the custom request headers.
X-Requested-With is a non-standard (albeit common) hack to let a server send different content based on if the request is from Ajax or not (typically switching between JSON and an HTML document, something better suited to the Accept header). It isn't needed here. Don't set it.
Access-Control-Allow-etc are response headers. The server you are making the request to must respond with them to tell the browser that your site is allowed to use Ajax to access it. You can't set them on the client, it would be ridiculous for a site to grant itself permission to access a different site. Don't try to set these.