Im trying to make a request from one application to another. So i created some headers which are required by my application and filled them in for the Ajax Request. Here is my code:
$.ajax({
method: 'GET',
url: 'http://my-domain.com/apps/filters/get-filters',
beforeSend: function(request){
request.setRequestHeader("X-Webshop-Domain", window.location.host);
request.setRequestHeader("X-Language", $('html').attr('lang'));
request.setRequestHeader("X-Request-Protocol", window.location.protocol);
request.setRequestHeader("X-Api-Version", '2');
},
headers: {
"X-Webshop-Domain": window.location.host,
"X-Language": $('html').attr('lang'),
"X-Request-Protocol": window.location.protocol,
"X-Api-Version": '2',
},
data: {}, success: function ( response )
{
}
});
Now when i load a page, this method is called but no response given. It gives me the "Header not allowed" issue. But when i check in my network tab (developer tools Chrome) i see my request, i see some headers but none of those. Does anybody has a idea how this is possible or what im doing wrong?
In case of CORS (cross domain requests), only basic headers are allowed. You will need to add the headers you wish to send to the server's response header:
Access-Control-Allow-Headers: X-Webshop-Domain, ...
Here's a related question you may find useful: Ajax Request header field Key is not allowed by Access-Control-Allow-Headers
Related
I am working on an internal web application at work. In IE10 the requests work fine, but in Chrome all the AJAX requests (which there are many) are sent using OPTIONS instead of whatever defined method I give it. Technically my requests are "cross domain." The site is served on localhost:6120 and the service I'm making AJAX requests to is on 57124. This closed jquery bug defines the issue, but not a real fix.
What can I do to use the proper http method in ajax requests?
Edit:
This is in the document load of every page:
jQuery.support.cors = true;
And every AJAX is built similarly:
var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
url: url,
dataType: "json",
data: json,
async: true,
cache: false,
timeout: 30000,
headers: { "x-li-format": "json", "X-UserName": userName },
success: function (data) {
// my success stuff
},
error: function (request, status, error) {
// my error stuff
},
type: "POST"
});
Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. If you're doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain. This is why the jQuery bug was closed as won't-fix. This is by design.
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than
application/x-www-form-urlencoded, multipart/form-data, or text/plain,
e.g. if the POST request sends an XML payload to the server using
application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
Based on the fact that the request isn't sent on the default port 80/443 this Ajax call is automatically considered a cross-origin resource (CORS) request, which in other words means that the request automatically issues an OPTIONS request which checks for CORS headers on the server's/servlet's side.
This happens even if you set
crossOrigin: false;
or even if you ommit it.
The reason is simply that localhost != localhost:57124. Try sending it only to localhost without the port - it will fail, because the requested target won't be reachable, however notice that if the domain names are equal the request is sent without the OPTIONS request before POST.
I agree with Kevin B, the bug report says it all. It sounds like you are trying to make cross-domain ajax calls. If you're not familiar with the same origin policy you can start here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript.
If this is not intended to be a cross-domain ajax call, try making your target url relative and see if the problem goes away. If you're really desperate look into the JSONP, but beware, mayhem lurks. There really isn't much more we can do to help you.
If it is possible pass the params through regular GET/POST with a different name and let your server side code handles it.
I had a similar issue with my own proxy to bypass CORS and I got the same error of POST->OPTION in Chrome. It was the Authorization header in my case ("x-li-format" and "X-UserName" here in your case.) I ended up passing it in a dummy format (e.g. AuthorizatinJack in GET) and I changed the code for my proxy to turn that into a header when making the call to the destination. Here it is in PHP:
if (isset($_GET['AuthorizationJack'])) {
$request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}
In my case I'm calling an API hosted by AWS (API Gateway). The error happened when I tried to call the API from a domain other than the API own domain. Since I'm the API owner I enabled CORS for the test environment, as described in the Amazon Documentation.
In production this error will not happen, since the request and the api will be in the same domain.
I hope it helps!
As answered by #Dark Falcon, I simply dealt with it.
In my case, I am using node.js server, and creating a session if it does not exist. Since the OPTIONS method does not have the session details in it, it ended up creating a new session for every POST method request.
So in my app routine to create-session-if-not-exist, I just added a check to see if method is OPTIONS, and if so, just skip session creating part:
app.use(function(req, res, next) {
if (req.method !== "OPTIONS") {
if (req.session && req.session.id) {
// Session exists
next();
}else{
// Create session
next();
}
} else {
// If request method is OPTIONS, just skip this part and move to the next method.
next();
}
}
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Consider using axios
axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {
if(res.data.error) {
} else {
doAnything( res.data )
}
}).catch(function (error) {
doAnythingError(error)
});
I had this issue using fetch and axios worked perfectly.
I've encountered a very similar issue. I spent almost half a day to understand why everything works correctly in Firefox and fails in Chrome. In my case it was because of duplicated (or maybe mistyped) fields in my request header.
Use fetch instead of XHR,then the request will not be prelighted even it's cross-domained.
$.ajax({
url: '###',
contentType: 'text/plain; charset=utf-8',
async: false,
xhrFields: {
withCredentials: true,
crossDomain: true,
Authorization: "Bearer ...."
},
method: 'POST',
data: JSON.stringify( request ),
success: function (data) {
console.log(data);
}
});
the contentType: 'text/plain; charset=utf-8', or just contentType: 'text/plain', works for me!
regards!!
I'm trying to send a POST request from my website to my remote server but I encounter some CORS issues.
I searched in the internet but didn't find a solution to my specific problem.
This is my ajax request params:
var params = {
url: url,
method: 'POST',
data: JSON.stringify(data),
contentType: 'json',
headers: {
'Access-Control-Request-Origin': '*',
'Access-Control-Request-Methods': 'POST'
}
On the backend side in this is my code in python:
#app.route(SETTINGS_NAMESPACE + '/<string:product_name>', methods=['POST', 'OPTIONS'])
#graphs.time_method()
def get_settings(product_name):
settings_data = helper.param_validate_and_extract(request, None, required=True, type=dict, post_data=True)
settings_data = json.dumps(settings_data)
response = self._get_settings(product_name, settings_data)
return output_json(response, requests.codes.ok, headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
})
I get an error on my console:
XMLHttpRequest cannot load [http://path-to-my-server]. Request header field
Access-Control-Request-Methods is not allowed by
Access-Control-Allow-Headers in preflight response
I did notice that I can add also 'Access-Control-Request-Headers' but I wasn't sure if it necessary and it cause me more problems so I removed it.
Does anyone know how to solve this problem?
Your ajax request shouldn't send Access-Control headers, only the server sends those headers to allow the servers to describe the set of origins that are permitted to read that information using a web browser.
The same-origin policy generally doesn't apply outside browsers, so the server has to send CORS headers or JSONP data if the browser is going to be able to get the data.
The browser doesn't send those headers to the server, it doesn't have to, it's the server that decides whether or not the data is available to a specific origin.
Remove the header option from the params object, and it should work
I'm trying to make a REST call (POST) using AJAX. This is my AJAX code
<script>
var settings = {
"async": true,
"crossDomain": true,
"dataType": "json",
"url": "http://localhost:port/service/myservice",
"method": "POST",
"data": '{jsondata}',
"headers": {
"accept": "application/json",
"Authorization": "authValue"
}
}
$.ajax(settings)
.done(function (response) {
console.log(response);
});
</script>
Initially I got this error: XMLHttpRequest cannot load http://localhost:port/service/myservice. 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.
To resolve this issue I added the following code in my dropwizard application
Dynamic filter = env.servlets().addFilter("CORS", CrossOriginFilter.class);
filter.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,PUT,POST,DELETE,OPTIONS");
filter.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
filter.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
filter.setInitParameter("allowedHeaders", "Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
filter.setInitParameter("allowCredentials", "true");
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
After adding this my initial exception went away, but I'm getting the following exception: XMLHttpRequest cannot load http://localhost:port/service/myservice. Response for preflight has invalid HTTP status code 400
Is this issue related to CORS? What am I doing wrong here?
UPDATE
After doing more debugging I found this behavior. When sending the request without the Authorization header I'm getting 415 (Unsupported Media Type) error.
I think something wrong with my AJAX code, can someone please help me find the issue? Thanks.
You may try here mentioned as complete answer in this thread.
$.ajax({
type:"POST",
beforeSend: function (request)
{
request.setRequestHeader("Authority", authValue);
},
url: "http://localhost:port/service/myservice",
data: "json=" + escape(JSON.stringify(createRequestObject)),
processData: false,
success: function(msg) {
$("#results").append("The result =" + StringifyPretty(msg));
}
});
try to add the following to your settings?
xhrFields: { withCredentials: true }
if you need to pass JSON data in the AJAX call, you need to specify content-type as json/application, so the server knows you are trying to send JSON data. But that will change the default content-type of the call and the call will qualify for pre-flight checking, which need proper CORS enabled client & server request.
For easier use case, do not use JSON.stringify() when you pass data, just make a simple string with {key:value, key:value, ...} format, and pass the string as the data. The Ajax call serializes the data by default and does the right thing, and the call stays as a single POST call to the server, where as the pre-flight mode is two calls.
I've tried the following basic Reddit API morechildren request using mootools:
var moreChildren = new Request({
async: true,
url: 'http://www.reddit.com/api/morechildren',
method: 'post',
data: {
api_type: "json",
children: "cl2vjlp",
link_id: "2ijczu",
sort: "top"
},
onSuccess: function(response){
commentData = JSON.parse(response);
console.log(commentData);
}
});
// tried above request with and without the following line
delete moreChildren.headers["X-Requested-With"];
moreChildren.send();
And I'm receiving a XMLHttpRequest cannot load http://www.reddit.com/api/morechildren.json. 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 403. in Google Chrome.
Observations:
Adding .json to reddit/api/morechildren(.json) does not resolve
deleting "X-Requested-With" header does not resolve
Any help is greatly appreciated. :)
This is because of same origin policy - CORS.
you do well to remove this:
// tried above request with and without the following line
delete moreChildren.headers["X-Requested-With"];
but if the reddit site does not support it, it won't work.
you have 2 options:
local proxy, ajax call to local, local server-side to reddit, back and output to browser
use JSONP where available.
can't test your case as it needs oauth but via info.json which is GET, you can:
http://jsfiddle.net/dimitar/zy3rwpjs/
new Request.JSONP({
url: 'http://www.reddit.com/api/info.json',
callbackKey: 'jsonp',
data: {
url: 'http://www.reddit.com/buttons'
},
onSuccess: function(response){
console.log(response.data, response.kind);
}
}).send();
obviously, when it expects POST, things get more complex... JSONP works as GET.
if all you care about is your own project and google chrome, you can start with with --disable-web-security flag, which will allow the call.
How can i insert the parsed html content into my webpage if i have only a link of the another webpage(get the html content from this webpage). I am using ajax call and i am getting the error i write the code below. And browser is not the issue
I want it as in Facebook but not in php
<script>
jQuery.support.cors = true;
$.ajax({
type:"GET",
url:"http://www.hotscripts.com/forums/javascript/3875-how-read-web-page-content-variable.html",
dataType:"html",
crossDomain:true,
beforeSend: function(xhr)
{
xhr.overrideMimeType('text/plain; charset=UTF-8');
},
success:function(data) {
alert(data);
$("body").html(data);
},
error:function(errorStatus,xhr) {
alert("Error",errorStatus,xhr);
}
});
</script>
May be your browser don't support cors.
http://caniuse.com/cors or another domain don't send back Access-Control-Allow-Origin header.
Thanks for the comments made by Quentin.
Another option is to use jSONP.
<script>
var query = "http://query.yahooapis.com/v1/public/yql?q=" +
encodeURIComponent("SELECT * FROM html WHERE url = 'http://www.hotscripts.com/forums/javascript/3875-how-read-web-page-content-variable.html'") +
"&format=json";
$.ajax({
type:"GET",
url: query,
crossDomain:true,
beforeSend: function(xhr)
{
xhr.overrideMimeType('text/plain; charset=UTF-8');
},
success:function(data) {
alert(data);
},
error:function(errorStatus,xhr) {
alert("Error",errorStatus,xhr);
}
});
</script>
Third option is to make a request through a proxy script located on your domain.
In reply to:
"i have used jQuery.support.cors=true; still there is a prob"
As I have said the server should return you the necessary headers.
If the other side does not allow it to become nothing can be done.
Check this:
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
To initiate a cross-origin request, a browser sends the request with an Origin HTTP header. The value of this header is the domain that served the page. For example, suppose a page from http://www.example-social-network.com attempts to access a user's data in online-personal-calendar.com. If the user's browser implements CORS, the following request header would be sent to online-personal-calendar.com:
Origin: http://www.example-social-network.com
If online-personal-calendar.com allows the request, it sends an Access-Control-Allow-Origin header in its response. The value of the header indicates what origin sites are allowed. For example, a response to the previous request would contain the following:
Access-Control-Allow-Origin: http://www.example-social-network.com
If the server does not allow the cross-origin request, the browser will deliver an error to example-social-network.com page instead of the online-personal-calendar.com response.
To allow access from all domains, a server can send the following response header:
Access-Control-Allow-Origin: *
This is generally not appropriate. The only case where this is appropriate is when a page or API response is considered completely public content and it is intended to be accessible to everyone, including any code on any site.
The value of "*" is special in that it does not allow requests to supply credentials, meaning HTTP authentication, client-side SSL certificates, nor does it allow cookies to be sent