I am performing an Ajax request to a server that accepts cross-domain requests but for which I have no control over the server code. My desire is to extract an HTTP Link header from the response. As an example:
$.ajax({
url: theURL
}).done(function(data,textStatus,xhr){});
hits a server that responds with the following (as observable when the URL is queried with curl):
HTTP/1.1 302 Found
Link: <http://thedataIwant.com>;rel="foo"
Location: http://someothersite.com
The browser follows the HTTP 3XX code and I get the contents of the HTTP headers from http://someothersite.com in the done() handler; however, I would like to first extract the contents of the Link header for the initial HTTP response with the 3XX code.
How do I go about extracting the contents of the HTTP Link header from an HTTP response with 3XX status code?
I was intrigued by your question and though to search around for a solution. Unfortunately, there isn't a direct one. According to all posts I read so far (How to manage a redirect request after a jQuery Ajax call and many similar ones) you can't simply catch the 301 redirect because browsers usually fetch the content and give the endpoint to the user, which is why you get the 200 status code instead of the 302. As a workaround, people are suggesting to use a custom header. When you receive the header after doing an ajax request, you could do your own manipulation i.e. save the Link header and then make a second ajax request to get the content from MyRedirectLocationHeader: http://someothersite.com.
The code would look something similar to this:
$.ajax({
url: theURL,
success: function(response, status, xhr) {
var link = xhr.getResponseHeader('Link');
if(link != null) {
// my second ajax request to the link in the MyRedirectLocationHeader
}
}
});
This is an awful looking hack, but that's the only workaround I've found so far which actually works. Another way might be for you to create a proxy script/service using PHP,Java or another similar language, that would get the request without following the redirects and would print out only the Link and Location as JSON or XML. Afterwards your javascript would parse the response and proceed to someothersite.com
What is interesting to me, though, is that the official jQuery ajax documentation page implies there is support for the 3xx redirects (near the documentation for the statusCode) but that doesn't seem to be working.
Related
I'm using axios in my application, but I'm having a hard time setting the content of the request.
There's currently a call to a URL using $.ajax like this:
$.ajax({
method: 'POST',
data: { 'accountId': accountId },
url: serverUrl,
/* success: ... */
});
And when I look at this request in Chrome dev tools, at the end I see something like this:
Now, I'm trying to do the same thing with axios:
axios.post(serverUrl, { accountId: accountId })
.then(/* ... */);
But, when I look at the request in Chrome dev tools, I have this:
How can I get axios to do the same formatting as jQuery? And maybe the question is that: are they different or it's just the representation?
Also, I noticed that the jQuery call is somehow adding this header: x-requested-with: XMLHttpRequest, but to have the same header in axios, I have to set it manually. Is it normal? Am I missing an axios configuration to add this header?
Thank you
Some frameworks use this header to detect XHR requests, for example. Grails Spring uses this header to identify the query XHR and gives the JSON response or the HTML response as a response.
Most Ajax libraries (Prototype, JQuery and Dojo from version 2.1) include the X-Requested-With header, which indicates that the query was made using XMLHttpRequest instead of running by clicking a regular hyperlink or submitting a form button.
A good reason for security is that it can prevent CSRF attacks, because this header can not be added to the cross domain of the AJAX request without the server's consent through CORS.
Only the following headers are allowed:
To accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
any others call the "before flight" request in the browsers supported by CORS.
Without CORS, X-Requested-With can not be added to an XHR request with a cross domain.
If the server checks the presence of this header, it knows that the request did not initiate an attempt to make a request on behalf of the user from the attacker's domain using JavaScript.
It also checks that the request was not sent from the usual HTML form, from which it is more difficult to verify that it is not a cross domain without the use of tokens. (However, checking the Origin header can be an option in supported browsers although you leave old browsers vulnerable.)
See also: https://markitzeroday.com/x-requested-with/cors/2017/06/29/csrf-mitigation-for-ajax-requests.html
So also read for greater understanding:
FormData()
https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData
Request Payload
What's the difference between "Request Payload" vs "Form Data" as seen in Chrome dev tools Network tab
As documented here, You can use the URLSearchParams API to send data in the application/x-www-form-urlencoded format using axios.
Example from offical docs:
var params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
I am working on twitter login using Jquery and Plain Java Script.
I have completed most of work, I am trying to get request_token from https://api.twitter.com/oauth/request_token URL. Request goes from my page as well but everytime it send me error of:
jquery.js:9536 OPTIONS https://api.twitter.com/oauth/request_token 400 ()send # jquery.js:9536ajax # jquery.js:9143clickToCalculate # twt.html:71onclick # twt.html:423
twt.html:1
XMLHttpRequest cannot load
https://api.twitter.com/oauth/request_token. Response for preflight has invalid HTTP status code 400
twt.html:82
Object {readyState: 0, status: 0, statusText: "error"}
My request URL page is http://kurbhatt.github.io/twt.html, you can check it's page source as well from https://github.com/kurbhatt/kurbhatt.github.io/blob/master/twt.html source page.
I have put valid and enough data from twitter apps to this page.
Can anyone tell me why I am facing this issue ?
Since last 3-4 days I am working on this issue, still not get solution for the issue.
And sometimes it gave me another type of error:
XMLHttpRequest cannot load https://api.twitter.com/oauth/request_token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://kurbhatt.github.io' is therefore not allowed access. The response had HTTP status code 400.
You are making a "GET" request to the api.
twitter api for request_token accepts only POST.
Fix your ajax request to make a POST request. The option is method not type
$.ajax({
method: "POST",
...
well, i would like to reply your comment in the comment, but that would be too tiring.
what you need to do to get the request token is do an HTTP POST to api.twitter.com/oauth/request_token with addtional headers, that is Authorization header, as stated in this twitter docs.
you can easily do that by creating a cURL POST request from your web server to the url above, let's say you have that cURL page in yourdomain.com/twittercurl, therefore you can make your jQuery call to that page instead of the twitter request token URL.
as I don't know which server side programming language you are using, you need to find the appropriate cURL call.
but, aside from that, here are some links to read, maybe you can find usefull informations from it:
adding request header to jQuery ajax call
cross domain ajax call
and don't forget the twitter docs mentioned above
lastly, you can also read this PHP library for the server side cURL request
I have an endpoint that will either return a JSON response or a redirect to a different html page depending on the parameters passed to it. JSON is returned for only some cases, so there are cases that will lead to a new html page. I was wondering if there is a way to get the content of the endpoint with an ajax request and then to either modify the existing page if it's a JSON response or otherwise if it's a html page to make it appear as if the page redirected to that page without calling the endpoint twice.
Yes, you just have to call endpoint and look at the response. If it's meant to be a redirect, it will likely return a 302 response code and contain the redirect URL. You can then set window.location to that URL and the page will redirect there. If you get the normal 200 response and the datatype is JSON, then you just process the JSON.
If you just log the response code, the headers and the response itself for each type of endpoint call, you should be able to clearly tell the difference so your code can branch accordingly.
For example, here's what a redirect response might look like:
HTTP/1.1 302 Found
Location: http://www.iana.org/domains/example/
Check this (Two Methods for Handling Cross-Domain Ajax Calls)
http://devproconnections.com/aspnet/two-methods-handling-cross-domain-ajax-calls
when I send requests to a certain server, a 303 response will come, followed by the requested response in combination with a 200 status code.
Funny thing is that I only see this on my developer console's network view. When checking the statuscode and response of my $.ajax() request, there will be the response of the second request, as well as a 200 http status code.
The problem is that it seems that the second request is being cached (though 200 status code), and I really need it to be non-cachable.
Therefore I'd really like to intervene into the forwarding process that occurs with a http 303 status code. I'd like my jquery function to check for the status code, then send the get request with explicit headers, that tell the server not to cache the response.
Well, I just don't know how to do this, since (as mentioned above) the jQuery.ajax method will respond with the forwarded request's response and status code (200).
Can you help me?
edit
10.3.4 303 See Other
The response to the request can be found under a different URI and
SHOULD be retrieved using a GET method on that resource. This method
exists primarily to allow the output of a POST-activated script to
redirect the user agent to a selected resource. The new URI is not a
substitute reference for the originally requested resource. The 303
response MUST NOT be cached, but the response to the second
(redirected) request might be cacheable.
maybe I need to somehow prevent the user agent from redirecting himself, so I can do the redirect?
Or is there a way to simply tell the server/browser not to cache the second request from client-side? or to prevent it from redirecting my request? or at least modify the second request before redirecting?
Responses in the 300 range are meant to be transparent. AFAIK, web browsers don't expose any of them to javascript. Thus, handling the 303 is not an option.
Have you tried setting the cache property to false in the ajaxSetup? It will append a timestamp to the request, preventing the browser from caching the response. You can also do that manually yourself. The browser should match the first request url to the 2nd response
You cannot stop the browser from following the 303 redirect. It sounds like that's not what you want, anyway. Whatever you would do in the browser to prevent the original request from being cached should work equally well for preventing the redirected 200 from being cached. That said, there is little you can do on the browser side other than using a unique URL for each request. This is done for you automatically by jQuery when you set cache: false.
$.ajax({
url: "example.html",
cache: false
}
}).done(function( html ) {
$("#results").append(html);
});
This is old post, but maybe someone will find this useful.
I have the same issue, and in my case the problem was in the method that was called out using the ajax. The problem was in the redirection that was set in the method. So, based on this, you can't use both ajax and redirect(server side), and i removed redirect() function from method, i everything works as expected.
Btw, i am using codeigniter.
See statusCode property of your .ajax() call
Example :
$.ajax({
statusCode: {
303: function() {
alert("page not found");
}
}
});
I swear I saw an article about this at one point but can not find it...
How can I perform a jQuery ajax request of type POST on another domain? Must be accomplished without a proxy. Is this possible?
Yes you can POST all you want, even $.post() works...but you won't get a response back.
This works, the other domain will get the POST:
$.post("http://othersite.com/somePage.php", { thing: "value" }, function(data) {
//data will always be null
});
But the response, data in the above example, will be null due to the same-origin policy.
All the options I've experimented with:
1) PORK: http://www.schizofreend.nl/Pork.Iframe/Examples/ Creates an iframe and submits the post there, then reads the response. Still requires same base domain per
request (i.e. www.foo.com can request
data from www2.foo.com, but not from
www.google.com) . Also requires you to
fiddle with the document.domain
property, which causes adverse side
effects. And there's a pervasive problem in all the major browsers where reloading the page basically shuffles the cached contents of all iframes on the page if any of them are dynamically written. Your response data will show up in the box where an ad is supposed to be.
2) flxhr: http://flxhr.flensed.com/ Can even be used to mask jQuery's built-in ajax so you don't even notice it. Requires flash though, so iPhone is out
3) jsonp: Doesn't work if you're posting a lot of data. boo.
4) chunked jsonp: When your jsonp request is too big, break the query string up into manageable chunks and send multiple get requests. Reconstruct them on the server. This is helpful but breaks down if you're load balancing users between servers.
5) CORS: http://www.w3.org/TR/cors/ doesn't work in older browsers (IE7, IE6, Firefox 2, etc)
So we currently do the following algorithm:
If request is small enough, use JSONP
If not small enough, but user has flash, use FlXHR
Else use chunked JSONP
Spend one afternoon writing that up and you'll be able to use it for good. Adding CORS to our algorithm might be good for faster iPhone support.
If you have control over the code running at the other domain, just let it return an appropriate Access-Control-Allow-Origin header in the response. See also HTTP Access-Control at MDC.
If you want a fire and forget POST where you don't care about the response then just submit a form to a hidden iframe. This requires a Transitional Doctype.
<form method="POST" action="http://example.com/" target="name_of_iframe">
If you want to parse the response, then using a proxy if the only real option.
If you are desperate, and control the remote site, then you can:
Submit a form as above
Set a cookie in the response (which might be blocked before the iframe could cause the cookie to be considered '3rd party' (i.e. likely to be advertising tracking).
Wait long enough for the response to come back
Dynamically generate a script element with the src pointing to the remote site
Use JSON-P in the response and take advantage of the data previously stored in the cookie
This approach is subject to race conditions and generally ugly. Proxing the data through the current domain is a much better approach.
If you need to know that the POST was successful, and don't have control over the remote server:
$.ajax({
type:"POST",
url:"http://www.somesite.com/submit",
data:'firstname=test&lastname=person&email=test#test.com',
complete: function(response){
if(response.status == 0 && response.statusText == "success")
{
/* CORS POST was successful */
}
else
{
/* Show error message */
}
}
});
If there was a problem with the submission then response.statusText should equal "error".
Note: some remote servers will send the HTTP header Access-Control-Allow-Origin: *, which will result in a 200 OK HTTP status code response. In that case, ajax will execute the success handler, and this method is not needed. To look at the response just do console.log(JSON.stringify(response)); or use FireBug's 'Net' panel.