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).
Related
I have a web service that expects POST requests carrying a JSON string in the body. I'm trying to use this web service using jQuery, but I have two problems :
1) jQuery seems to always use the GET method, no matter what I do ;
2) jQuery seems to append weird things into the URL.
The relevant pice of my code :
var WEB_SERVICE_URL = 'http://localhost/XXXX/';
// ...
$.post({
url: WEB_SERVICE_URL + 'GetConfigLabels/',
contentType: 'application/json; charset=utf-8',
dataType: 'jsonp',
data: JSON.stringify(data),
processData: false,
success: function(response) {
// Whatever
},
error: function(xhr, message) {
// Whatever
}
});
The developper tools of the browser (Firefox Quantum 60.0.2) shows me a weird URL :
http://localhost/XXXX/GetConfigLabels/?callback=jQuery331012146934861340841_1530707758905&{}&_=1530707758906
While the following was expected :
http://localhost/XXXX/GetConfigLabels/
Also the HTML file is openned as a file (using file:///) through the file system, hence the use of JSONP for cross domain.
I failed to find existing questions related to this issue. What could be causing this ? Thank you !
Please refer to the dataType : json section at http://api.jquery.com/jquery.ajax/ :
"json": Evaluates the response as JSON and returns a JavaScript
object. Cross-domain "json" requests that have a callback placeholder,
e.g. ?callback=?, are performed using JSONP unless the request
includes jsonp: false in its request options. The JSON data is parsed
in a strict manner; any malformed JSON is rejected and a parse error
is thrown. As of jQuery 1.9, an empty response is also rejected; the
server should return a response of null or {} instead. (See json.org
for more information on proper JSON format
overrding random name of callback using jsonpCallback :
jsonpCallback Type: String or Function() Specify the callback function
name for a JSONP request. This value will be used instead of the
random name automatically generated by jQuery. It is preferable to let
jQuery generate a unique name as it'll make it easier to manage the
requests and provide callbacks and error handling. You may want to
specify the callback when you want to enable better browser caching of
GET requests. As of jQuery 1.5, you can also use a function for this
setting, in which case the value of jsonpCallback is set to the return
value of that function.
$.getJSON('http://robloxplus.com:2052/inventory?username=itracking', function(data){
$.each(data, function(item){
console.log(item['id'])
});
});`
returns undefined when attempting to run it on an external website. It is supposed to output each id of every item in that list (http://robloxplus.com:2052/inventory?username=itracking)
How do I fix this?
Edits>
I want to iterate over each individual id, each of these numbers "168167114": and "135470963": etc. etc. and fetch the data that follows that (i.e. the name:"", totalSerial:"")
is the request being made on the same domain as robloxplus.com ?
I'm new to this.. I don't understand much about JavaScript and/or
JQuery. #Pedro Lobito no, it's not. –
Explanation:
HTTP requests from Javascript are traditionally bound by the Same
Origin Policy, which means that your ajax requests must have the same
domain and port. The common ways to get around this are JSON-P,
Proxying and message passing via s. These all have their
quirks, but the thing they generally have in common is legacy browser
support.
Solution
1 - If robloxplus.com is yours, you can enable CORS
2 - If not, you can use YQL (Yahoo! Query Language) to bypass CORS
When one of the above options is fulfilled, you can make your json request, i.e.:
$.ajax({
url: 'http://robloxplus.com:2052/inventory?username=itracking',
type: 'get',
dataType: 'json',
success: function(data) {
$.each(data.id, function(item) {
console.log(item);
});
},
error: function(e) {
console.log(e.message);
}
});
I want to send an ajax request using sortable from jquery-ui. When I re-sort a list, for some reason, the ajax call isn't appending timestamp onto the querystring to avoid caching. Why won't this code work?
$('#categorylist').sortable({
placeholder: "ui-state-highlight",
update:function(e, ui){
var categorylist = $('#categorylist').sortable('serialize', {attribute:'data-id'});
$.ajax({
url:'actions_category.php?action=rank',
method:'post',
data:categorylist,
cache:false
});
}
});
It will only append the time stamp for GET and HEAD requests. It should not be needed for other types of requests except in IE8 for POST requests where you have already issued a GET request against the URL.
http://api.jquery.com/jQuery.ajax/
Note the supported HTTP Methods
http://api.jquery.com/jQuery.ajax/
cache (default: true, false for dataType 'script' and 'jsonp')
Type: Boolean
If set to false, it will force requested pages not to be cached by the browser. Note: Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters. The parameter is not needed for other types of requests, except in IE8 when a POST is made to a URL that has already been requested by a GET.
I have the following code
function exista(word) {
alert(word);
var exists = 1;
jQuery.ajax({
async: false,
url: "http://api.wordreference.com/0.8/key/json/roen/" + word,
dataType: 'json',
method: "GET",
success: function(transport) {
if (transport.Error || transport.Response)
exists = 0;
}
});
return exists;
}
which verifies if a word exists or not in a dictionary. Problem is it gives an Access-Control-Allow-Origin error. From what I gathered it seems I must use JSONP but I can't really figure out how (sorry, I am just beginning to learn JavaScript and all that). So, got any idea on how to modify the above code?
Thank you.
Your dataType should be jsonp, not 'json`.
UPDATE
According to http://www.wordreference.com/docs/api.aspx:
Additionally, for JSPONp, the JSON API can take an optional callback
function in the query string; simply add "?callback={yourCallback}" to
the end of the URL.
so the API does support JSONP.
Additionally, JSONP means "JSON with padding", so you will get a JSON response. JSONP merely allows use of CORS.
By changing your dataType to jsonp:
"jsonp": Loads in a JSON block using JSONP. Adds an extra
"?callback=?" to the end of your URL to specify the callback. Disables
caching by appending a query string parameter, "_=[TIMESTAMP]", to the
URL unless the cache option is set to true.
You can override the default callback by specifying one with the jsonpCallback setting.
Finally, you should also add an error handler and set async to true:
jQuery.ajax({
"async": true, //cannot be false for JSONP
"url": "http://api.wordreference.com/0.8/key/json/roen/" + word,
"dataType": 'jsonp',
"method": "GET",
"error": function (jqXHR, textStatus, errorThrown) {
//included so you can see any errors
console.log(textStatus + ': ' + errorThrown);
},
"success": function (data, textStatus, jqXHR) {
//According to API documentation
//data will not likely contain either Error, or Response
//so, exists will likely not change to 0
if (data.Error || data.Response) {
exists = 0;
}
}
});
UPDATE:
The solution to both the error and the "need to be synchronous" is going to be what Pointy pointed out earlier. You'll have to create a server-side proxy that runs on the same domain as your script.
The server-side proxy can return JSONP, but frankly simply returning JSON or XML is simpler since CORS is not an issue, and the proxy can be synchronous. For a PHP example script, the Yahoo! Developer Network hosts source code for a simple proxy.
For anything else regarding a server-side web service proxy, you'd need to specify which server language you're using (and it would probably be better suited as a different question).
For JSONP to work, you not only have to code for it on your side, but the site you're targeting has to expect to be used that way as well, and respond to requests accordingly.
If the other site does not have a JSONP API already, and you have no control over it, then JSONP is not an answer. You'll have to create a server-side proxy of your own.
edit — according to the site, they do support JSONP. You just need to add "?callback=?" to the end of the URL.
I want to get live currency rates from an external source, so I found this great webservice:
Currency Convertor
This service is working like a charm, the only downside is that it does not provide JSONP results, only XML. Therefore we have a cross browser problem while trying to consume this webservice using jQuery $.ajax().
So I found Yahoo Query Language which returns results as JSONP and also mangae to consume other webservices and return me the results. This is also working, here is an example URL:
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fwww.webservicex.net%2FCurrencyConvertor.asmx%2FConversionRate%3FFromCurrency%3DNOK%26ToCurrency%3DEUR'&format=json&diagnostics=true&callback=cbfunc
This URL return JSONP result and is working like a charm, but the problem appears when I use this in my code:
$.ajax({
type: "GET",
url: urlToWebservice,
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
success: function(data) {
$("#status").html("OK: " + data.text);
},
error: function(xhr, textStatus, errorThrown) {
$("#status").html("Unavailable: " + textStatus);
}
});
When I try to run this code nothing happens, and I can see this error message in my Firebug javascript debugger:
cbfunc is not defined
cbfunc is the name of the container which surrounds the JSON response, but why does it say not defined?
EDIT:
This is my new code, but I still get the cbfunc is not defined
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fwww.webservicex.net%2FCurrencyConvertor.asmx%2FConversionRate%3FFromCurrency%3DNOK%26ToCurrency%3DEUR'&format=json&callback=cbfunc",
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'cbfunc'
});
function cbfunc(data) {
alert("OK");
}
And the "OK" message is never fired...
If available, use the jsonpCallback parameter in the call to $.ajax like:
jsonpCallback: "cbfunc",
Its description, from the jQuery API docs reads:
Specify the callback function name for a jsonp request. This value will be used instead of the random name automatically generated by jQuery.
The docs later go on to say:
It is preferable to let jQuery generate a unique name as it'll make it easier to manage the requests and provide callbacks and error handling. You may want to specify the callback when you want to enable better browser caching of GET requests.
However it is not advised to make use of this "preferable" behaviour when making use of YQL. Precisely why that approach is not ideal might make this answer far too verbose, so here is a link (from the YQL blog) detailing the problems with jQuery's preferred approach, making use of jsonpCallback and so on: Avoiding rate limits and getting banned in YQL and Pipes: Caching is your friend
You should let jQuery handle the callback by changing urlToWebservice to end in callback=?
The reason it's not working is because by specifying callback=cbfunc in the querystring generates a URL of the type:
http://query.yahooapis.com/...&callback=cbfunc&callback=jsonp1277417828303
Stripped out all uninteresting parts, but the URL contains two callback parameters. One of them is managed by jQuery, and the other one not. YQL only looks at the first callback parameter and returns a response wrapped around that.
cbfunc({"query":{...}});
However, there is no function named cbfunc in your script, so that's why you are getting the undefined error. jQuery created an implicit function named jsonp1277417828303 in the above example, and the response from YQL should instead have been:
jsonp1277417828303({"query":{...}});
for jQuery to act upon it, and return the response to your success callback which it never got to do.
So, as #SLaks suggested, remove the &callback=cbfuncfrom your URL, or replace it with &callback=? to let jQuery handle things.
See a working example.
You definitely should give jQuery-JSONP a try: http://code.google.com/p/jquery-jsonp/
Simplifies everything :)