Cross Domain Error in post request [duplicate] - javascript

How do I send a cross-domain POST request via JavaScript?
Notes - it shouldn't refresh the page, and I need to grab and parse the response afterwards.

Update: Before continuing everyone should read and understand the web.dev tutorial on CORS. It is easy to understand and very clear.
If you control the server being POSTed, simply leverage the "Cross-Origin Resource Sharing standard" by setting response headers on the server. This answer is discussed in other answers in this thread, but not very clearly in my opinion.
In short here is how you accomplish the cross domain POST from from.com/1.html to to.com/postHere.php (using PHP as an example). Note: you only need to set Access-Control-Allow-Origin for NON OPTIONS requests - this example always sets all headers for a smaller code snippet.
In postHere.php setup the following:
switch ($_SERVER['HTTP_ORIGIN']) {
case 'http://from.com': case 'https://from.com':
header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
break;
}
This allows your script to make cross domain POST, GET and OPTIONS. This will become clear as you continue to read...
Setup your cross domain POST from JS (jQuery example):
$.ajax({
type: 'POST',
url: 'https://to.com/postHere.php',
crossDomain: true,
data: '{"some":"json"}',
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
alert('POST failed.');
}
});
When you do the POST in step 2, your browser will send a "OPTIONS" method to the server. This is a "sniff" by the browser to see if the server is cool with you POSTing to it. The server responds with an "Access-Control-Allow-Origin" telling the browser its OK to POST|GET|ORIGIN if request originated from "http://from.com" or "https://from.com". Since the server is OK with it, the browser will make a 2nd request (this time a POST). It is good practice to have your client set the content type it is sending - so you'll need to allow that as well.
MDN has a great write-up about HTTP access control, that goes into detail of how the entire flow works. According to their docs, it should "work in browsers that support cross-site XMLHttpRequest". This is a bit misleading however, as I THINK only modern browsers allow cross domain POST. I have only verified this works with safari,chrome,FF 3.6.
Keep in mind the following if you do this:
Your server will have to handle 2 requests per operation
You will have to think about the security implications. Be careful before doing something like 'Access-Control-Allow-Origin: *'
This wont work on mobile browsers. In my experience they do not allow cross domain POST at all. I've tested android, iPad, iPhone
There is a pretty big bug in FF < 3.6 where if the server returns a non 400 response code AND there is a response body (validation errors for example), FF 3.6 wont get the response body. This is a huge pain in the ass, since you cant use good REST practices. See bug here (its filed under jQuery, but my guess is its a FF bug - seems to be fixed in FF4).
Always return the headers above, not just on OPTION requests. FF needs it in the response from the POST.

If you control the remote server, you should probably use CORS, as described in this answer; it's supported in IE8 and up, and all recent versions of FF, GC, and Safari. (But in IE8 and 9, CORS won't allow you to send cookies in the request.)
So, if you don't control the remote server, or if you have to support IE7, or if you need cookies and you have to support IE8/9, you'll probably want to use an iframe technique.
Create an iframe with a unique name. (iframes use a global namespace for the entire browser, so pick a name that no other website will use.)
Construct a form with hidden inputs, targeting the iframe.
Submit the form.
Here's sample code; I tested it on IE6, IE7, IE8, IE9, FF4, GC11, S5.
function crossDomainPost() {
// Add the iframe with a unique name
var iframe = document.createElement("iframe");
var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
document.body.appendChild(iframe);
iframe.style.display = "none";
iframe.contentWindow.name = uniqueString;
// construct a form with hidden inputs, targeting the iframe
var form = document.createElement("form");
form.target = uniqueString;
form.action = "http://INSERT_YOUR_URL_HERE";
form.method = "POST";
// repeat for each parameter
var input = document.createElement("input");
input.type = "hidden";
input.name = "INSERT_YOUR_PARAMETER_NAME_HERE";
input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}
Beware! You won't be able to directly read the response of the POST, since the iframe exists on a separate domain. Frames aren't allowed to communicate with each other from different domains; this is the same-origin policy.
If you control the remote server but you can't use CORS (e.g. because you're on IE8/IE9 and you need to use cookies), there are ways to work around the same-origin policy, for example by using window.postMessage and/or one of a number of libraries allowing you to send cross-domain cross-frame messages in older browsers:
Porthole
XSSInterface
EasyXDM
jQuery PostMessage Plugin
If you don't control the remote server, then you can't read the response of the POST, period. It would cause security problems otherwise.

Create an iFrame,
put a form in it with Hidden inputs,
set the form's action to the URL,
Add iframe to document
submit the form
Pseudocode
var ifr = document.createElement('iframe');
var frm = document.createElement('form');
frm.setAttribute("action", "yoururl");
frm.setAttribute("method", "post");
// create hidden inputs, add them
// not shown, but similar (create, setAttribute, appendChild)
ifr.appendChild(frm);
document.body.appendChild(ifr);
frm.submit();
You probably want to style the iframe, to be hidden and absolutely positioned. Not sure cross site posting will be allowed by the browser, but if so, this is how to do it.

Keep it simple:
cross-domain POST:
use crossDomain: true,
shouldn't refresh the page:
No, it will not refresh the page as the success or error async callback will be called when the server send back the response.
Example script:
$.ajax({
type: "POST",
url: "http://www.yoururl.com/",
crossDomain: true,
data: 'param1=value1&param2=value2',
success: function (data) {
// do something with server response data
},
error: function (err) {
// handle your error logic here
}
});

If you have access to all servers involved, put the following in the header of the reply for the page being requested in the other domain:
PHP:
header('Access-Control-Allow-Origin: *');
For example, in Drupal's xmlrpc.php code you would do this:
function xmlrpc_server_output($xml) {
$xml = '<?xml version="1.0"?>'."\n". $xml;
header('Connection: close');
header('Content-Length: '. strlen($xml));
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/x-www-form-urlencoded');
header('Date: '. date('r'));
// $xml = str_replace("\n", " ", $xml);
echo $xml;
exit;
}
This probably creates a security problem, and you should make sure that you take the appropriate measures to verify the request.

Check the post_method function in http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - a good example for the iframe method described above.

Create two hidden iframes (add "display: none;" to the css style). Make your second iframe point to something on your own domain.
Create a hidden form, set its method to "post" with target = your first iframe, and optionally set enctype to "multipart/form-data" (I'm thinking you want to do POST because you want to send multipart data like pictures?)
When ready, make the form submit() the POST.
If you can get the other domain to return javascript that will do Cross-Domain Communication With Iframes (http://softwareas.com/cross-domain-communication-with-iframes) then you are in luck, and you can capture the response as well.
Of course, if you want to use your server as a proxy, you can avoid all this. Simply submit the form to your own server, which will proxy the request to the other server (assuming the other server isn't set up to notice IP discrepancies), get the response, and return whatever you like.

One more important thing to note!!!
In example above it's described how to use
$.ajax({
type : 'POST',
dataType : 'json',
url : 'another-remote-server',
...
});
JQuery 1.6 and lower has a bug with cross-domain XHR.
According to Firebug no requests except OPTIONS were sent. No POST. At all.
Spent 5 hours testing/tuning my code. Adding a lot of headers on the remote server (script). Without any effect.
But later, I've updated JQuery lib to 1.6.4, and everything works like a charm.

If you want to do this in ASP.net MVC environment with JQuery AJAX, follow these steps:
(this is a summary of the solution offered at this thread)
Assume that "caller.com"(can be any website) needs to post to "server.com"(an ASP.net MVC application)
On the "server.com" app's Web.config add the following section:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
</customHeaders>
</httpProtocol>
On the "server.com", we'll have the following action on the controller(called "Home") to which we will be posting:
[HttpPost]
public JsonResult Save()
{
//Handle the post data...
return Json(
new
{
IsSuccess = true
});
}
Then from the "caller.com", post data from a form(with the html id "formId") to "server.com" as follow:
$.ajax({
type: "POST",
url: "http://www.server.com/home/save",
dataType: 'json',
crossDomain: true,
data: $(formId).serialize(),
success: function (jsonResult) {
//do what ever with the reply
},
error: function (jqXHR, textStatus) {
//handle error
}
});

There is one more way (using html5 feature). You can use proxy iframe hosted on that other domain, you send message using postMessage to that iframe, then that iframe can do POST request (on same domain) and postMessage back with reposnse to the parent window.
parent on sender.com
var win = $('iframe')[0].contentWindow
function get(event) {
if (event.origin === "http://reciver.com") {
// event.data is response from POST
}
}
if (window.addEventListener){
addEventListener("message", get, false)
} else {
attachEvent("onmessage", get)
}
win.postMessage(JSON.stringify({url: "URL", data: {}}),"http://reciver.com");
iframe on reciver.com
function listener(event) {
if (event.origin === "http://sender.com") {
var data = JSON.parse(event.data);
$.post(data.url, data.data, function(reponse) {
window.parent.postMessage(reponse, "*");
});
}
}
// don't know if we can use jQuery here
if (window.addEventListener){
addEventListener("message", listener, false)
} else {
attachEvent("onmessage", listener)
}

High level.... You need to have a cname setup on your server so that other-serve.your-server.com points to other-server.com.
Your page dynamically creates an invisible iframe, which acts as your transport to other-server.com. You then have to communicate via JS from your page to the other-server.com and have call backs that return the data back to your page.
Possible but requires coordination from your-server.com and other-server.com

I think the best way is to use XMLHttpRequest (e.g. $.ajax(), $.post() in jQuery) with one of Cross-Origin Resource Sharing polyfills https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#wiki-CORS

This is an old question, but some new technology might help someone out.
If you have administrative access to the other server then you can use the opensource Forge project to accomplish your cross-domain POST. Forge provides a cross-domain JavaScript XmlHttpRequest wrapper that takes advantage of Flash's raw socket API. The POST can even be done over TLS.
The reason you need administrative access to the server you are POSTing to is because you must provide a cross-domain policy that permits access from your domain.
http://github.com/digitalbazaar/forge

I know this is an old question, but I wanted to share my approach. I use cURL as a proxy, very easy and consistent. Create a php page called submit.php, and add the following code:
<?
function post($url, $data) {
$header = array("User-Agent: " . $_SERVER["HTTP_USER_AGENT"], "Content-Type: application/x-www-form-urlencoded");
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
$url = "your cross domain request here";
$data = $_SERVER["QUERY_STRING"];
echo(post($url, $data));
Then, in your js (jQuery here):
$.ajax({
type: 'POST',
url: 'submit.php',
crossDomain: true,
data: '{"some":"json"}',
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
alert('POST failed.');
}
});

Should be possible with a YQL custom table + JS XHR, take a look at:
http://developer.yahoo.com/yql/guide/index.html
I use it to do some client side (js) html scraping, works fine
(I have a full audio player, with search on internet/playlists/lyrics/last fm informations, all client js + YQL)

CORS is for you.
CORS is "Cross Origin Resource Sharing", is a way to send cross domain request.Now the XMLHttpRequest2 and Fetch API both support CORS, and it can send both POST and GET request
But it has its limits.Server need to specific claim the Access-Control-Allow-Origin, and it can not be set to '*'.
And if you want any origin can send request to you, you need JSONP (also need to set Access-Control-Allow-Origin, but can be '*')
For lots of request way if you don't know how to choice, I think you need a full functional component to do that.Let me introduce a simple component https://github.com/Joker-Jelly/catta
If you are using modern browser (> IE9, Chrome, FF, Edge, etc.), Very Recommend you to use a simple but beauty component https://github.com/Joker-Jelly/catta.It have no dependence, Less than 3KB, and it support Fetch, AJAX and JSONP with same deadly sample syntax and options.
catta('./data/simple.json').then(function (res) {
console.log(res);
});
It also it support all the way to import to your project, like ES6 module, CommonJS and even <script> in HTML.

If you have access to the cross domain server and don't want to make any code changes on server side, you can use a library called - 'xdomain'.
How it works:
Step 1:
server 1: include the xdomain library and configure the cross domain as a slave:
<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
Step 2:
on cross domain server, create a proxy.html file and include server 1 as a master:
proxy.html:
<!DOCTYPE HTML>
<script src="js/xdomain.min.js"></script>
<script>
xdomain.masters({
"https://server1" : '*'
});
</script>
Step 3:
Now, you can make an AJAX call to the proxy.html as endpoint from server1. This is bypass the CORS request. The library internally uses iframe solution which works with Credentials and all possible methods: GET, POST etc.
Query ajax code:
$.ajax({
url: 'https://crossdomain_server/proxy.html',
type: "POST",
data: JSON.stringify(_data),
dataType: "json",
contentType: "application/json; charset=utf-8"
})
.done(_success)
.fail(_failed)

Related

A very basic approach to the double submit cookie patterns for ajax requests in (partly) stateless web applications

My self-coded very basic approach to implement the double submit cookie pattern (detailed information: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie) in a partly stateless web application without framework written in PHP and JavaScript (jQuery) would be like this:
PHP - for each request:
setcookie(
"meow_csrf",
$value = "some_securly_generated_random_string",
0,
"/",
"mydomain.com",
true,
false
);
JavaScript - for ajax requests:
// JS
$.ajax({
type: "POST",
url: '/ajax.php?action=update_user_details&meow_csrf=' . $.cookie('meow_csrf'),
error: function() {
// blabla
},
success: function(data){
// blabla
}
});
PHP - server side check:
function tokenCheck(): bool
{
return $_COOKIE["meow_csrf"]) === urldecode($_GET["meow_csrf"]);
}
Please note how setcookie in PHP works: https://www.php.net/manual/en/function.setcookie.php
Is this already a basic protection against CSRF attacks or did I misunderstand something? Please note that the cookie may only be transferred via HTTPS, it can therefore not be easily read over a network. It is not HTTPOnly though.
Note that there could be some problems when you renew the cookie for EVERY request. Let's say a user fills out a form and opens another tab in the meantime (maybe to look something up). When he finally sends the form the cookie already changed due to the requests in the meantime. This will also happen with any call in general between first initializing the page and finally send the request.
I think once the CRSF Token is set you don't need to change it for the current session. And yes, I would call that a basic approach against CRSF attacks.

How to choose the right dataType and contentType value for AJAX request?

I have written some jQuery + PHP code that takes the HTML from an element on a webpage and saves it on server. Here is the code that I am using:
var page = {
'html': document.querySelector("article").innerHTML,
'url': 'path/current/webpage.php' or (<?php echo "'$current_page'"; ?>)
// Both give same 'url' value. This is not an issue.
};
$.ajax({
url:'https://example.com/update.php',
type:'post',
data: page,
success:function(data){
window.location.reload();
}
});
Here is my code for update.php:
$content = $_REQUEST['html'];
$page = $_REQUEST['url'];
file_put_contents($page, $content, LOCK_EX);
I am not very comfortable with dataType and contentType so I skipped them initially. However the request succeeded sometimes but gave 403() error other times.I did a little research and found that this might be due to lack of dataType and contentType. So, I used the following values:
contentType: 'text/plain; charset=utf-8',
dataType: 'html'
I no longer get any errors but the pages are not actually updating. I also tried setting the values to:
contentType:'application/json',
dataType: 'html'
This time too, I did not get any 403() errors but the page would not actually update.
Does the post data needs to be accessed differently based on the value of contentType like 'application/json' or 'text/plain; charset=utf-8'? Because the updates don't seem to show up on the webpage even with a 200 response code.
Using application/x-www-form-urlencoded; charset=UTF-8 updates some pages but gives 403() error for others.
As Rory said (as did I, in an answer I wrote then deleted when I saw his comment; he was right to comment instead), a 403 response code probably doesn't mean there's a problem with either dataType or contentType. You should look for other reasons the server would refuse to satisfy the request. For instance, as you're posting HTML, perhaps you (or your web host) has some kind of anti-script-injection protection going on. You'll have to track that down, perhaps with your hosting company.
But two things: Some info for completeness, and a potential workaround:
dataType is the type you expect back from the server. contentType is the type of data you're sending to the server.
For the request you're sending, leaving off contentType is correct, because the default jQuery will use is what PHP will expect to see.
You shouldn't have to specify dataType at all; instead, you should ensure the response carries the correct Content-Type header. That means ensuring that your server is configured correctly (for static content) and that your PHP code sets the correct header if necessary via header("Content-Type: data/type-here") The only reason for specifying dataType is if you don't control the server and you know it sends back the wrong type.
If you need to try to work around it, first ask: What if someone sends me malicious HTML directly, not through my web page? The answer is: You need to be careful with what you do with the HTML. For example: If you are going to store this HTML and then display it (as HTML) to a user, that's a Cross-Site Scripting vulnerability and you have to rigorously sanitize that HTML before doing that.
Do not proceed with any workaround until you've answered that question for yourself.
Okay, so in terms of working around it (once you have robust safeguards in place): You might send JSON rather than a standard form, in hopes that whatever is rejecting the forms won't look at it. To do that, you'd change your ajax call:
var page = {
html: document.querySelector("article").innerHTML,
url: <?php echo "'$current_page'"; ?>
};
$.ajax({
url:'https://example.com/update.php',
type:'post',
data: JSON.stringify(page),
contentType: 'application/json; charset=UTF8',
success:function(data){
window.location.reload();
}
});
Then on the PHP side, you'd read that JSON and parse it (reading code below taken from this answer):
$entityBody = json_decode(stream_get_contents(STDIN));
$content = $entityBody['html'];
$page = $entityBody['url'];
file_put_contents($page, $content, LOCK_EX);
Again: Please do not use this unless you have robust anti-XSS safeguards in place. And again, if you do haev robust anti-XSS safeguards in place, you might be able to just use a normal form by changing your server config.

express.js res.header doesn't work after ajax call [duplicate]

So I've got this jQuery AJAX call, and the response comes from the server in the form of a 302 redirect. I'd like to take this redirect and load it in an iframe, but when I try to view the header info with a javascript alert, it comes up null, even though firebug sees it correctly.
Here's the code, if it'll help:
$j.ajax({
type: 'POST',
url:'url.do',
data: formData,
complete: function(resp){
alert(resp.getAllResponseHeaders());
}
});
I don't really have access to the server-side stuff in order to move the URL to the response body, which I know would be the easiest solution, so any help with the parsing of the header would be fantastic.
cballou's solution will work if you are using an old version of jquery. In newer versions you can also try:
$.ajax({
type: 'POST',
url:'url.do',
data: formData,
success: function(data, textStatus, request){
alert(request.getResponseHeader('some_header'));
},
error: function (request, textStatus, errorThrown) {
alert(request.getResponseHeader('some_header'));
}
});
According to docs the XMLHttpRequest object is available as of jQuery 1.4.
If this is a CORS request, you may see all headers in debug tools (such as Chrome->Inspect Element->Network), but the xHR object will only retrieve the header (via xhr.getResponseHeader('Header')) if such a header is a simple response header:
Content-Type
Last-modified
Content-Language
Cache-Control
Expires
Pragma
If it is not in this set, it must be present in the Access-Control-Expose-Headers header returned by the server.
About the case in question, if it is a CORS request, one will only be able to retrieve the Location header through the XMLHttpRequest object if, and only if, the header below is also present:
Access-Control-Expose-Headers: Location
If its not a CORS request, XMLHttpRequest will have no problem retrieving it.
var geturl;
geturl = $.ajax({
type: "GET",
url: 'http://....',
success: function () {
alert("done!"+ geturl.getAllResponseHeaders());
}
});
The unfortunate truth about AJAX and the 302 redirect is that you can't get the headers from the return because the browser never gives them to the XHR. When a browser sees a 302 it automatically applies the redirect. In this case, you would see the header in firebug because the browser got it, but you would not see it in ajax, because the browser did not pass it. This is why the success and the error handlers never get called. Only the complete handler is called.
http://www.checkupdown.com/status/E302.html
The 302 response from the Web server should always include an alternative URL to which redirection should occur. If it does, a Web browser will immediately retry the alternative URL. So you never actually see a 302 error in a Web browser
Here are some stackoverflow posts on the subject. Some of the posts describe hacks to get around this issue.
How to manage a redirect request after a jQuery Ajax call
Catching 302 FOUND in JavaScript
HTTP redirect: 301 (permanent) vs. 302 (temporary)
The underlying XMLHttpRequest object used by jQuery will always silently follow redirects rather than return a 302 status code. Therefore, you can't use jQuery's AJAX request functionality to get the returned URL. Instead, you need to put all the data into a form and submit the form with the target attribute set to the value of the name attribute of the iframe:
$('#myIframe').attr('name', 'myIframe');
var form = $('<form method="POST" action="url.do"></form>').attr('target', 'myIframe');
$('<input type="hidden" />').attr({name: 'search', value: 'test'}).appendTo(form);
form.appendTo(document.body);
form.submit();
The server's url.do page will be loaded in the iframe, but when its 302 status arrives, the iframe will be redirected to the final destination.
UPDATE 2018 FOR JQUERY 3 AND LATER
I know this is an old question but none of the above solutions worked for me. Here is the solution that worked:
//I only created this function as I am making many ajax calls with different urls and appending the result to different divs
function makeAjaxCall(requestType, urlTo, resultAreaId){
var jqxhr = $.ajax({
type: requestType,
url: urlTo
});
//this section is executed when the server responds with no error
jqxhr.done(function(){
});
//this section is executed when the server responds with error
jqxhr.fail(function(){
})
//this section is always executed
jqxhr.always(function(){
console.log("getting header " + jqxhr.getResponseHeader('testHeader'));
});
}
try this:
type: "GET",
async: false,
complete: function (XMLHttpRequest, textStatus) {
var headers = XMLHttpRequest.getAllResponseHeaders();
}
+1 to PleaseStand
and here is my other hack:
after searching and found that the "cross ajax request" could not get response headers from XHR object, I gave up. and use iframe instead.
1. <iframe style="display:none"></iframe>
2. $("iframe").attr("src", "http://the_url_you_want_to_access")
//this is my aim!!!
3. $("iframe").contents().find('#someID').html()

X-Forecast-API-Calls http response header inclusion and usage [duplicate]

So I've got this jQuery AJAX call, and the response comes from the server in the form of a 302 redirect. I'd like to take this redirect and load it in an iframe, but when I try to view the header info with a javascript alert, it comes up null, even though firebug sees it correctly.
Here's the code, if it'll help:
$j.ajax({
type: 'POST',
url:'url.do',
data: formData,
complete: function(resp){
alert(resp.getAllResponseHeaders());
}
});
I don't really have access to the server-side stuff in order to move the URL to the response body, which I know would be the easiest solution, so any help with the parsing of the header would be fantastic.
cballou's solution will work if you are using an old version of jquery. In newer versions you can also try:
$.ajax({
type: 'POST',
url:'url.do',
data: formData,
success: function(data, textStatus, request){
alert(request.getResponseHeader('some_header'));
},
error: function (request, textStatus, errorThrown) {
alert(request.getResponseHeader('some_header'));
}
});
According to docs the XMLHttpRequest object is available as of jQuery 1.4.
If this is a CORS request, you may see all headers in debug tools (such as Chrome->Inspect Element->Network), but the xHR object will only retrieve the header (via xhr.getResponseHeader('Header')) if such a header is a simple response header:
Content-Type
Last-modified
Content-Language
Cache-Control
Expires
Pragma
If it is not in this set, it must be present in the Access-Control-Expose-Headers header returned by the server.
About the case in question, if it is a CORS request, one will only be able to retrieve the Location header through the XMLHttpRequest object if, and only if, the header below is also present:
Access-Control-Expose-Headers: Location
If its not a CORS request, XMLHttpRequest will have no problem retrieving it.
var geturl;
geturl = $.ajax({
type: "GET",
url: 'http://....',
success: function () {
alert("done!"+ geturl.getAllResponseHeaders());
}
});
The unfortunate truth about AJAX and the 302 redirect is that you can't get the headers from the return because the browser never gives them to the XHR. When a browser sees a 302 it automatically applies the redirect. In this case, you would see the header in firebug because the browser got it, but you would not see it in ajax, because the browser did not pass it. This is why the success and the error handlers never get called. Only the complete handler is called.
http://www.checkupdown.com/status/E302.html
The 302 response from the Web server should always include an alternative URL to which redirection should occur. If it does, a Web browser will immediately retry the alternative URL. So you never actually see a 302 error in a Web browser
Here are some stackoverflow posts on the subject. Some of the posts describe hacks to get around this issue.
How to manage a redirect request after a jQuery Ajax call
Catching 302 FOUND in JavaScript
HTTP redirect: 301 (permanent) vs. 302 (temporary)
The underlying XMLHttpRequest object used by jQuery will always silently follow redirects rather than return a 302 status code. Therefore, you can't use jQuery's AJAX request functionality to get the returned URL. Instead, you need to put all the data into a form and submit the form with the target attribute set to the value of the name attribute of the iframe:
$('#myIframe').attr('name', 'myIframe');
var form = $('<form method="POST" action="url.do"></form>').attr('target', 'myIframe');
$('<input type="hidden" />').attr({name: 'search', value: 'test'}).appendTo(form);
form.appendTo(document.body);
form.submit();
The server's url.do page will be loaded in the iframe, but when its 302 status arrives, the iframe will be redirected to the final destination.
UPDATE 2018 FOR JQUERY 3 AND LATER
I know this is an old question but none of the above solutions worked for me. Here is the solution that worked:
//I only created this function as I am making many ajax calls with different urls and appending the result to different divs
function makeAjaxCall(requestType, urlTo, resultAreaId){
var jqxhr = $.ajax({
type: requestType,
url: urlTo
});
//this section is executed when the server responds with no error
jqxhr.done(function(){
});
//this section is executed when the server responds with error
jqxhr.fail(function(){
})
//this section is always executed
jqxhr.always(function(){
console.log("getting header " + jqxhr.getResponseHeader('testHeader'));
});
}
try this:
type: "GET",
async: false,
complete: function (XMLHttpRequest, textStatus) {
var headers = XMLHttpRequest.getAllResponseHeaders();
}
+1 to PleaseStand
and here is my other hack:
after searching and found that the "cross ajax request" could not get response headers from XHR object, I gave up. and use iframe instead.
1. <iframe style="display:none"></iframe>
2. $("iframe").attr("src", "http://the_url_you_want_to_access")
//this is my aim!!!
3. $("iframe").contents().find('#someID').html()

How to print content that is returned in http response using javascript

I want to print in console content that are returned in http response. For example when I go to https://google.com and in the tab Network I can see content such as scripts, text, document, png. I want to print names of all .png files.
I tried to use something like that:
function hand () {
console.log(this.getResponseHeader('content-type'));
}
var x = new XMLHttpRequest();
x.open('GET', 'https://google.com', true);
x.onreadystatechange = hand;
x.send();
But it doesn't work for me. This action below is assigned for the button on me page.
Cross-origin requests simply are not allowed by default. The remote server may provide permission to your application through CORS or by supporting Ajax alternatives like JSONP.
Edited:
The only (easy) way to get cross-domain data using AJAX is to use a server side language as the proxy as Andy E noted. Here's a small sample how to implement that using jQuery:
The jQuery part:
$.ajax({
url: 'proxy.php',
type: 'POST',
data: {
address: 'http://www.google.com'
},
success: function(response) {
// response now contains full HTML of google.com
}
});
Simple as that. Just be aware of what you can or cannot do with the scraped data and be very much aware that such a proxy is a severe security hole. At least make a list of acceptable addresses and don't just blindly accept any passed address. Have a look at a decent proxy script here: PHP Simple Proxy

Categories