I've got a situation where I'm sending ajax requests from iframe, to same domain as original page, this Iframe loaded from same domain. Say, original page address is http://server/client and iframe src is http://server/client/addin1/view.html
From Iframe I make initial xhr request to api: POST http://server/api/connect which returns 201 with token in response header and a cookie.
Now I make next call to different api method, say, GET http://server/api/status, but in this case I add the token header, and I assume the received cookie will be included by browser - it's HttpOnly, my xhr has withCredentials: true.
The magic is: in FF it works ok, both token and cookie are set and sent, in chrome the token header is not added and cookie is not sent. I've verified that in both cases xhr.setRequestHeader(...) gets called, and just to be 100% sure I've verified with wireshark what gets actually sent.
Any idea why chrome, behaves differently from FF? Maybe I'm missing sth simple.
thanks,
Ćukasz
I had a similar problem to yours and I was able to fix my CORS issue following this MDN article CORS (MDN), see the section on Requests with credentials. There you'll find that you have to set the xhr options withCredentials. Here's the example they use:
var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';
function callOtherDomain(){
if(invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler; // Needs to be implemented
invocation.send();
}
}
Hope that helps!
Related
I'm trying to download a file in client-side Javascript using the Box API, which redirects the request to a temporary download link once the file has been found. The browser is blocking the redirect, though, throwing the following error:
XMLHttpRequest cannot load https://api.box.com/2.0/files/file-id/content. The request was redirected to 'https://dl.boxcloud.com/d/1/some-big-hash/download', which is disallowed for cross-origin requests that require preflight.
In the Network console I see three requests, the first is an OPTIONS (which must be the pre-flight because the actual code sends a GET) with a 200 response, and the second two are identical GET requests which both get 302'd (the expected response for that API call). Here's the code that makes the request:
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.setRequestHeader('Authorization', 'Bearer '+MyToken);
xhr.onload = function()
{
//some stuff
}
xhr.onerror = function()
{
//some other stuff
}
xhr.send();
My question is (a): Why are two GETs being sent after the preflight comes back?
And (b): Is there any way I can format the request to allow following the redirect? And (c) if not, can I at least retrieve the redirect URL from the response and follow it with another explicit request? Every response in the console has the 'Access-Control-Allow-Origin' header set with the correct origin.
Thanks
I don't understand why you get three rather than two requests, but the way CORS has worked thus far is that a request with a preflight cannot be redirected. This has changed in the Fetch Standard, but user agents have not yet picked up the change.
I have a content script in my Chrome extension which runs on some HTTPS page. It is trying to send a POST request to an HTTP page (by means of a background script) which is a route for an API that I have set up. I am trying to send JSON data over. However I am getting status 0, even though the ready state is 4. I used Postman to perform the same post and it worked. This leads me to believe it is a HTTPS protocol issue, however I am performing a GET on an HTTP page in the same background script and that is working fine. What might be the issue then? Here is my POST code:
var string = json;
xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var json = JSON.parse(xhr.responseText);
}
};
xhr.send(string);
Thanks!
UPDATE:
I used the chrome developer tools to debug the background script and I found the error, which was "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.". I guess background script errors do not print to the main console.
UPDATE:
I had to add the site I was posting to to the permissions field in my manifest. It works now.
I have a similar issue and, after debugging it for days, the only solution I found was to make the XMLHttpRequest synchronous by setting set the async param in the XMLHttpRequest open method to false.
The readyState value of 4 means the operation completed successfully or failed. The status property is initialized to 0 and will remain at 0 if an error occurs. Assign an event handler to the xhr.onerror property and I bet you'll see that handler fire. Unfortunately, the error event doesn't give any useful information about what caused the error.
To find out what caused the error, I would use the debug tools found in Chrome. Menu => More tools => Developer Tools. Then go to the "Network" tab. There you can see all the HTTP requests your webpage has made. It will show better details on any errors there.
What did you do?
I had to add the site I was posting to the permissions field in my manifest. It works now.
XMLHttpRequest.setRequestHeader("Access-Control-Allow-Origin", "the api website"); ?
I'm developing a sort of user-tracking system, that works as follows:
1) A webmaster adds a js script in his website:
<script src="http://example.com/in/tracking.js"></script>
2) When a user loads the page, the javascript request send back a cookie in response:
Set-Cookie:trackid=c1d7fde9cf87a9501cea57cedde97998;Version=1;Comment=;Domain=example.com;Path=/;Max-Age=31556926
(it's basically a simple cookie that lasts for 1 year)
3) The tracking.js makes a POST XMLHttpRequest, to the same example.com domain, passing some parameters:
theAjaxRequest.open("POST","http://example.com/in",true);
theAjaxRequest.setRequestHeader("Content-type", "multipart/form-data");
theAjaxRequest.send(parameters);
4) The backend of example.com should then read the previously set "trackid" cookie, but, instead, I get no cookies on request... By analyzing the POST request via Chrome inspector, I noted that no cookies are passed in request headers (while the first GET request for tracking.js sets correctly the cookie via Set-Cookie).
How come? At first I assumed it may be a problem related to same-origin-policy; so I enabled CORS headers on back-end web server. No results. So, I tried to load tracking.js on a website under same domain of example.com (say web.example.com). Anyway, no results again...
Am I missing something?
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';
function callOtherDomain(){
if(invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler;
invocation.send();
}
Line 7 shows the flag on XMLHttpRequest that has to be set in order to make the invocation with Cookies, namely the withCredentials boolean value. By default, the invocation is made without Cookies. Since this is a simple GET request, it is not preflighted, but the browser will reject any response that does not have the Access-Control-Allow-Credentials: true header, and not make the response available to the invoking web content.
I'm trying to send an AJAX request from a secure page, but the XMLHttpRequest object doesn't properly resolve the protocol portion of the URL. This behavior is identical in Safari, Chrome, and Canary.
Here's my JavaScript:
function sendGETRequest(url, params, callback) {
"use strict";
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState === 4) {
if (req.status !== 200) {
callback({ajaxError: true, status: req.status});
} else {
callback(req);
}
}
};
req.open("GET", url + "?" + params, true);
req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
req.send();
}
Here are some different URLs passed to sendGETRequest(), along with their results:
url = "ajax/";
GET https://mydomain/mypage/ajax/?params 404 (NOT FOUND)
The above is the expected behavior: the relative url is correctly resolved with protocol intact.
url = "/ajax/";
The page at https://mydomain/mypage/ displayed insecure content from http://mydomain/ajax/?params.
Here, the realtive url is correctly appended to the domain root, but with the wrong protocol.
url = "https://mydomain/ajax/";
The page at https://mydomain/mypage/ displayed insecure content from http://mydomain/ajax/?params.
Here, the protocol is just ignored.
To be clear, I'm not trying to work around the same origin policy; I want to send an AJAX request from a secure page to a resource with the same (secure) origin. How can I accomplish this simple task?
There is a conversation here about this topic: http://bytes.com/topic/javascript/answers/459071-ajax-https
One of the last posts states "Just to be absolutely unambiguous; XML HTTP requests work over https
exactly as they do over http. If they did not our QA department would
have said something by now as they test over https almost exclusively"
Perhaps the server is not using Https (ssl) at the point where the request is being made: mydomain/ajax/.
This has nothing to do with HTTP and HTTPS. As you mentioned in a comment, the request is never being sent due to same-origin policy. How can the request be using the wrong policy if the request is never sent? What is confusing you is that whatever program/add-on/tool/etc that is generating the error message is showing "HTTP" instead of "HTTPS". The request IS and ALWAYS respects HTTPS when HTTPS is set.
Your real issue is quite simply that you are violating cross-origin policy. See this:
https://developer.mozilla.org/en-US/docs/Same-origin_policy_for_file:_URIs
You cannot go UP the directory tree, only down. In the first example, you are requesting a subfolder. That's fine. In the second and third examples, you are requesting a page from a parent directory (ie, instead of https://mydomain/mypage/ajax/ you are asking for https://mydomain/ajax/. You cannot make a request up a directory tree like that.
Either move your index page up to the root of the domain, or change the same-origin policy header being sent on the files, or make a sub directory on the server handle the request (you can use something like PHP's include to just include the parent file).
This is a bug in WebKit. It's been fixed in Safari 5 for Lion but not Snow Leopard, and it's been fixed in Chrome but not Canary,... helluva a bug.
i have a problem with a http post call in firefox. I know that when there are a cross origin, firefox first do a OPTIONS before the POST to know the access-control-allow headers.
With this code i dont have any problem:
Net.requestSpeech.prototype.post = function(url, data) {
if(this.xhr != null) {
this.xhr.open("POST", url);
this.xhr.onreadystatechange = Net.requestSpeech.eventFunction;
this.xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
this.xhr.send(data);
}
}
I test this code with a simple html that invokes this function.
Everything is ok and i have the response of the OPTIONS and POST, and i process the response. But, i'm trying to integrate this code with an existen application with uses jquery (i dont know if this is a problem), when the send(data) executes in this case, the browser (firefox) do the same, first do a OPTION request, but in this case dont receive the response of the server and puts this message in console:
[18:48:13.529] OPTIONS http://localhost:8111/ [undefined 31ms]
Undefined... the undefined is because dont receive the response, but the code is the same, i dont know why in this case the option dont receive the response, someone have an idea?
i debug my server app and the OPTIONS arrive ok to the server, but it seems like the browser dont wait to the response.
edit more later: ok i think that the problem is when i run with a simple html with a SCRIPT tag that invokes the method who do the request run ok, but in this app that dont receive the response, i have a form that do a onsubmit event, i think that the submit event returns very fast and the browser dont have time to get the OPTIONS request.
edit more later later: WTF, i resolve the problem make the POST request to sync:
this.xhr.open("POST", url, false);
The submit reponse very quickly and can't wait to the OPTION response of the browser, any idea to this?
Due to the same origin policy, you can't send cross origin post,
you can workaround it by include sites in iframes (if have access to the domain) original site contains iframe to the outer site, the inner direction is legal.