For example, suppose I'm using AJAX to send a request to a server like so:
$.ajax(
{
url: url,
beforeSend: function (request) { request.setRequestHeader('X-Test', 'one'); },
});
The documentation for $.ajax contains the following:
contentType (default: 'application/x-www-form-urlencoded;
charset=UTF-8') Type: String
When sending data to the server, use this
content type. Default is "application/x-www-form-urlencoded;
charset=UTF-8", which is fine for most cases. If you explicitly pass
in a content-type to $.ajax(), then it is always sent to the server
(even if no data is sent). The W3C XMLHttpRequest specification
dictates that the charset is always UTF-8; specifying another charset
will not force the browser to change the encoding.
According to this, the default is UTF-8, but I'm not clear from the description if the contentType header affects only the encoding of the request's body or the encoding of the other headers as well (if the latter can even be changed).
contentType only affects the body/document.
According to this you can use any ISO-8859-1 characters in the header.
You have to remember that AJAX render part of the HTML body, so when you send data in a AJAX request with some content type, for example iso-8859-1, the data is setting with that content type only in the AJAX request life cycle.
I hope my answer be useful for you.
Good lucky.
Related
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()
I am sending an AJAX POST request using jQuery on a chrome extension but the data doesn't arrive as expected, accented characters turn out malformed.
The text "HÄGERSTEN" becomes "HÄGERSTEN".
The text appears fine in the console etc, only via AJAX to this other page it appears as mentioned. My AJAX call is basic, I send a data-object via jQuery $.ajax. I've tried both with and without contentType, UTF-8 and ISO-8859-1. No difference.
This is how I make my AJAX call:
var newValues = {name: 'HÄGERSTEN'}
$.ajax({
url: POST_URL,
type: 'POST',
data: newValues,
success: function() ...
});
The newValues object has more values but I retrieve them from a form. However, I have tried to specify these values manually as newValues['name'] = 'ÄÄÄÄ'; and still would cause the same problem.
The original form element of the page that I am sending the AJAX to contains attribute accept-charset="iso-8859-1". Maybe this matters.
The target website is using Servlet/2.5 JSP/2.1. Just incase it might make a difference.
I assume this is an encoding issue and as I've understood it should be because Chrome extensions require the script files to be UTF-8 encoded which probably conflicts with the website the plugin is running on and the target AJAX page (same website) which is using an ISO-8859-1 encoding, however I have no idea how to deal with it. I have tried several methods of decoding/encoding it to and from UTF-8 to ISO-8859-1 and other tricks with no success.
I have tried using encodeURIComponent on my values which only makes them show that way exactly on the form that displays the values I have sent via POST, as e.g. H%C3%84GERSTEN.
I have no access to the websites server and cannot tell you whether this is a problem from their side, however I would not suppose so.
UPDATE
Now I have understood POST data must be sent as UTF-8! So a conversion is not the issue?
Seems like the data is UTF-8 encoded when it is sent and not properly decoded on the server side. It has to be decoded on the server side. Test it out with the following encode and decode functions:
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
function decode_utf8(s) {
return decodeURIComponent(escape(s));
}
var encoded_string = encode_utf8("HÄGERSTEN");
var decoded_string = decode_utf8(encoded_string);
document.getElementById("encoded").innerText = encoded_string;
document.getElementById("decoded").innerText = decoded_string;
<div>
Encoded string: <span id="encoded"></span>
</div>
<div>
Decoded string: <span id="decoded"></span>
</div>
We too faced the same situation but in our case we always sent the parameters using JSON.stringify.
For this you have to make changes, 1) While making call to the page via AJAX you have to add content-type tag defining in which encoding data is sent
$.ajax
({
type: "POST",
url: POST_URL,
dataType: 'json',//In our case the datatype is JSON
contentType: "application/json; charset=utf-8",
data: JSON.stringify(newValues),//I always use parameters to be sent in JSON format
EDIT
After reading your question more clearly I came to know that your server side JSP uses ISO-8859-1 encoding and reading some posts, I came to know that all POST method data will be transmitted using UTF-8 as mentioned.
POST data will always be transmitted to the server using UTF-8 charset, per the W3C XMLHTTPRequest standard
But while reading post jquery-ignores-encoding-iso-8859-1 there was a workaround posted by iappwebdev which might be useful and help you,
$.ajax({
url: '...',
contentType: 'Content-type: text/plain; charset=iso-8859-1',
// This is the imporant part!!!
beforeSend: function(jqXHR) {
jqXHR.overrideMimeType('text/html;charset=iso-8859-1');
}
});
Above code is taken from Code Posted by iappwebdev
I don't know if it could have been solved using POST-data and AJAX. Perhaps if I made a pure JavaScript XHR AJAX call, I might be able to send POST-data encoded the way I like. I have no idea.
However, in my desperation I tried my final option (or what seemed like it); send the request as GET-data. I was lucky and the target page accepted GET-data.
Obviously the problem still persisted as I was sending data the same way, being UTF-8 encoded. So instead of sending the data as an object I parsed the data into a URL friendly string with my own function using escape, making sure they are ISO-8859-1 friendly (as encodeURIComponent encodes the URI as UTF-8 while escape encodes strings making them compatible with ISO-8859-1).
The simple function that cured my headaches:
function URLEncodeISO(values) {
var params = [];
for(var k in values) params[params.length] = escape(k) + '=' + escape(values[k]);
return params.join('&');
}
The client side character coding is not completely up to you (immagine the usage of the page from different users all around the world: chinese, italian...) while on the server side you need to handle the coding for your purposes.
So, the data in the Ajax-POST can continue to be UTF8-encoded, but in your server side you coan to do the following:
PHP:
$name = utf8_decode($_POST['name']);
JSP:
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
$.ajax({
url: Settings.get('serverURL') + 'PlaylistItem/CreateMultiple',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(newItems)
});
I'm explicitly setting the contentType of the AJAX request to indicate JSON is being sent across the wire. However, I seem to be inconsistent in my application of contentType across my code and all AJAX requests are working properly.
Is it necessary or beneficial to be explicit with the JSON contentType or should I omit it?
According to the JQuery documentation
contentType (default: 'application/x-www-form-urlencoded;
charset=UTF-8') Type: String When sending data to the server, use this
content type. Default is "application/x-www-form-urlencoded;
charset=UTF-8", which is fine for most cases. If you explicitly pass
in a content-type to $.ajax(), then it is always sent to the server
(even if no data is sent). The W3C XMLHttpRequest specification
dictates that the charset is always UTF-8; specifying another charset
will not force the browser to change the encoding.
In practice I have found it beneficial to explicitly state it either in $.ajax or through
$.ajaxSetup({
contentType: "application/json; charset=utf-8"
});
as application/x-www-form-urlencoded has caused me the occasional null value in MVC action parameters as per this article
http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx/
I need to send data to the server using the character set Big-5, however the browser seems to only encode the data in UTF-8. If I were to make a form, then it can be achieveable with the following attribute:
<form accept-charset="Big5">
However, I want to send the data through XHR. Some answers suggest that contentType can let me change it. But according to jQuery's documentation, the encoding cannot be overridden: (at least this is true in Chrome.)
The W3C XMLHttpRequest specification dictates that the charset is always UTF-8; specifying another charset will not force the browser to change the encoding.
$.ajax({
url: "dummy url",
type: "GET",
data: {
q: "Test"
},
contentType: "application/x-www-form-urlencoded;charset=Big5"
}, function(){});
//This won't work.
Is there any way to get around it?
I'm using the third party jsonp library for jquery. In the call to it, you can set cache to true.
However, upon checking in a HTTP sniffer, it appears that all requests are still being sent to the server..
This with the picasa, flickr, and youtube API.
What could be causing this behavior? It does not appear to be browser-specific as I have tested it in multiple browsers and all behave the same (not caching).
The URLs called don't change from one request to the other and the call looks like this:
$.jsonp({
url: url,
cache: true,
async: false,
dataType: 'jsonp',
data: $.extend({ url: options.dataUrl, method: lookupData.method }, fixedOptions),
callbackParameter: "jsoncallback",
success: function(data)
{
$.extend(datasourceOptions, lookupData.onData(data));
getData();
}
});
The only "weird" thing about my setup is that the script that will call the .jsonp is included via a .ajax call itself.. Could that be the issue here? Sounds far fetched but...
Thanks,
Wesley
Edit: Ok, 3 out of the 4 have Expires headers set..
However, the fourth does not and only has these:
Cache-Control: private
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Connection: close
(this is flickr)
What's going on there?
Also, is it not possible to override the header caching directives via jquery somehow?
Cache Headers
First off the server responding to your jsonp calls must have some an expiration date in the response headers. As you mentioned you are not in control of how youtube, flickr, etc answer the jsonp calls.
Browser Cache
The browser is caching the calls with acceptable headers for each unique url.
jQuery JSONP Callback and Identifier
jQuery sends two pieces of data that make your URLs unique. If you do do not change these two options, your jsonp calls will never cache. Read more here
The actual callback= param value that your json data is padded with. Looks something like this: callback=jQuery_123971236127631276.
A unique identifier that makes every URL unique and hence non-cachable. Looks something like this: _=123918712387612398.
Disable unique JSONP Callback
The get param called callback is given a random name generated by jQuery so that many jsonp calls can be fired at once and the responses would not interfere with each other. None the less this must be changed if you wish to cache a certain jsonp call. The attribute jsonpCallback is used to overwrite this feature.
$.jsonp({
url: url,
dataType: 'jsonp',
data: $.extend({ url: options.dataUrl, method: lookupData.method }, fixedOptions),
// Note: using success : function(){ ... } will not be
// called if 'jsonpCallback' attribute is set.
jsonpCallback : 'myCallback',
});
Disable unique URL Identifer
This URL Identifier is set in the param list so that each call is unique, looks like: ...&_=1231981238712. Removing this feature can be done by adding attribute cache : true to your options.
$.jsonp({
url: url,
dataType: 'jsonp',
data: $.extend({ url: options.dataUrl, method: lookupData.method }, fixedOptions),
// Note: using success : function(){ ... } will not be
// called if 'jsonpCallback' attribute is set.
jsonpCallback : 'myCallback',
// Disables: ... &_=1231829812386
cache : true
});
I expect that the services you're calling are returning cache control headers that tell the browser not to cache the response / to expire the cached response very quickly. You should be able to see them in the HTTP messages. Look for Cache-Control and/or Expires, that sort of thing.
Re your edit:
Also, is it not possible to override the header caching directives via jquery somehow?
I don't think so, no, certainly not with JSON-P, which is at its heart a script element being added to the page, so programmatic control over that is going to be extremely limited. Even if it were XHR, frankly, I don't think there's a way to tell the browser to use a cached version that's stale according to its source.
If this is happening within the page lifecycle, you could cache the result yourself in an object on the page, but I'm guessing you're talking about caching between visits to the page (though I can't immediately see why you want to defeat the origin's definition of fresh/stale).