I want to use wikipedia API in my project to grab images of people, but fail. I use this url:https://en.wikipedia.org/w/api.php?action=query&prop=pageimages&titles=Albert%20Einstein&pithumbsize=100
When i console browser says the following
Refused to execute script from 'https://en.wikipedia.org/w/api.php?action=query&prop=pageimages&titles=Albe…Callback&callback=jQuery22409288979864744966_1470068280411&_=1470068280412' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
My code
var general = {
// The URL to the quote API
url: 'http://api.forismatic.com/api/1.0/',
// What to display as the author name if s/he's unknown
unknownAuthor: 'Uknown',
// Base URL for the tweet links generation
tweetURL: 'http://twitter.com/home?status=',
wikiURL:'https://en.wikipedia.org/w/api.php?action=query&prop=pageimages&titles=Albert Einstein&pithumbsize=100&callback=wikiCallback'
};
var wikirequest = function() {
$.ajax({
url:general.wikiURL,
dataType: 'jsonp',
success: function(wikData) {
console.log(wikData);
//var image = wikiData.
displayQuote(image);
} // end of success
});
}// wikirequest
wikirequest();
Pen
Has anyone met the same issue?
You are trying to load the data using JSONP, but you are making a request to a URL that returns an HTML document. JSONP requests have to be answered with JavaScript programs (since that is a fundamental feature of how they work … and also why they are dangerous and should be avoided in favour of plain JSON and CORS).
To make it return JSONP you need to provided two additional query string parameters:
format=json
callback=YourCallbackName
… where YourCallbackName is the name of the function that should be executed and passed the data you are fetching as an argument. Most Ajax libraries will generate that name (and the function itself) dynamically when you specify callback=?.
https://en.wikipedia.org/w/api.php?action=query&prop=pageimages&titles=Albert%20Einstein&pithumbsize=100&format=json
You are missing the &format=json on the URL - The page was displaying the data with the html header and you would have been attempting to decode this. The above answer is actually better.
Related
There can be different reasons for <img> load errors, such as network error response, bad image data...
error object received from onerror doesn't seems to specify the exact reason.
Is there a way to know if the error is because of a network error, say HTTP 500 or a network timeout?
EDIT:
I'm not looking for an alternative way to load a resource, such as AJAX request. I need an answer specifically for <img> tag with onerror event. The reason for that is that I'm using this method for pixel-tracking and I need a way to retry on upon network errors. I'm also not looking for alternative tracking methods such as JSONP.
Edit 16Nov16 2020GMT
Maybe you are pixel-tracking in emails or other clients limited in Javascript capabilities.
One idea that comes to mind is to use URL query paramters in your <img>'s src URL.
With regards to network timeouts, I will pose the idea that a user opens an email, loads the email entirely, then disconnects from the internet and somehow this does not give the tracker enough time to load.
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
I would suggest to use setTimeout() inside your onerror function.
This will continue attempting to set/load the <img>'s src URL. You could append the seconds it took until successful load to the URL of your src file as a query parameter like ?s=<sec>
As far as determining status 500 codes on image loads you might want to consider creating a custom 500 error file which would then create -- for example -- a MySQL database entry with all sorts of information you have access to and if you chose to use the query parameters mentioned before then you have slightly more information added to the error.
onerror for <img> gives limited information about the network
The information that is available from <img> can be found at
https://www.w3.org/TR/html/semantics-embedded-content.html#htmlimageelement-htmlimageelement
Older answer:
Perhaps a route you would like to try is to use AJAX to load the image data and set the <img> src to the base64 of the image data received. I hope this helps.
Edit 14Nov16 2018GMT
Alternatively use AJAX to determine if the image loads properly and then use the same URL sent to AJAX as the src for your <img>. It would of course be redundant but would avoid the issue of long "data" URLs.
Edit 15Nov16 0832GMT
Also regarding Network Timeout I found this thread to be useful JQuery Ajax - How to Detect Network Connection error when making Ajax call
Apparently you can specify a timeout to AJAX much like using error except you just provide the miliseconds manually.
Converting to Base64
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/btoa
var encodedData = window.btoa("Hello, world"); // encode a string
Or if you are concerened about older browsers able to use btoa() then you might be interested in Google's https://chromium.googlesource.com/chromiumos/platform/spigots/+/refs/heads/firmware-u-boot-v1/base64_encode.js
Status Code checks in jQuery's AJAX
jQuery: How to get the HTTP status code from within the $.ajax.error method?
$.ajax({
type: 'GET',
url: '/path-to-my/image.png',
data: null,
success: function(data){
alert('horray! 200 status code!');
// convert to base64; add to img.src # btoa(data)
document.querySelector("#hlogo img").src = "data:;base64,"+ data;
},
error:function (xhr, ajaxOptions, thrownError){
switch (xhr.status) {
case 400:
// Take action, referencing xhr.responseText as needed.
case 404:
// Take action, referencing xhr.responseText as needed.
case 500:
// Take action, referencing xhr.responseText as needed.
}
});
Notes
https://www.rfc-editor.org/rfc/rfc2397#section-3
dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
mediatype := [ type "/" subtype ] *( ";" parameter )
data := *urlchar
parameter := attribute "=" value
https://www.rfc-editor.org/rfc/rfc2046#section-4.2
Using of a generic-purpose image viewing application this way
inherits the security problems of the most dangerous type supported
by the application.
https://www.rfc-editor.org/rfc/rfc2397#page-4
The effect of using long "data" URLs in applications is currently
unknown; some software packages may exhibit unreasonable behavior
when confronted with data that exceeds its allocated buffer size.
Other References
Unknown file type MIME?
Asynchronously load images with jQuery
I've been on this for hours already, I've read tons of articles and still cant figure it out.
Here's the deal.
I am working with Chrome extensions and I want to do a call to my server that returns me a js object. I dont want to inject this into the page, but I want to be able to use it within my content script.
NOTE: I cannot use eval() (I have tried though) and I cannot use jsonp
I am using a framework so my headers arent set here, but they set to return application-type application/javascript utf-8;
my php side looks like this:
$refererObj = 'var refererObj = {
myFunc: function () {
console.log("hello");
}
};';
echo $refererObj;
my js looks like this
$.ajax({
url: myUrl,
crossDomain: true,
data: postData,
dataType: "json",
type: "POST",
}).done(function(data){
eval(data);
console.log(data);
console.log(refererObj);
});
The first console.log gives ["var refererObj = {↵ getProducts: function () {↵…(products);↵ console.log("hello");↵ }↵};"]
The second gives "Uncaught ReferenceError: refererObj is not defined"
I get the response as a string with the javascript object and everything is all good until I actually want to "convert" the string into a usable code.
Any help would be really great.
Thanks
You actually can use eval() if you relax the default Content Security Policy with unsafe-eval. But it's a big hammer that's best avoided.
You can use JSONP, again, if you can serve it off an https server and add it to script-src of the Content Security Policy. This is slightly less of a security risk.
I doubt there is any other solution: anything you load off an external server is to be considered tainted and if you find a way to execute it - congrats, you just bypassed CSP in Chrome and should go claim your bug bounty.
Please note that in case of simply JSON data it's all moot, you can just load it with XHR and JSON.parse it. But your example contains code.
What does the &callback parameter in a URL do? The reason I am asking is because I am running a query with jquery's $.ajax function and when I include &callback=? in the end of the url I get a 400 (bad request) error.
Here is my javascript code:
var energy_query_array = [];
var masterEnergyTable_tableid = '145TOXaanydD63tvgVMmCVH0hei0NXNCEK8ekZBg';
var current_date = 'Jan-12';
var energy_query = 'SELECT * FROM ' + masterEnergyTable_tableid;
var encoded_energy_query = encodeURIComponent(energy_query);
var energy_url = ['https://www.googleapis.com/fusiontables/v1/query'];
energy_url.push('?sql=' + encoded_energy_query);
energy_url.push('&key=' + apiKey);
//energy_url.push('&callback=?');
$.ajax({
url: energy_url.join(''),
datatype: 'jsonp',
success: function(data) {
var name_array = data['columns'];
var data_array = data['rows'][0];
for(var i = 1; i < data['columns'].length; i++) {
energy_query_array[name_array[i]] = data_array[i];
}
}
});
console.log(energy_query_array);
I have commented out the line where I add &callback=? to the url because when I leave it in the query returns the error:
"message":"Invalid value for parameter callback: ?"
However, earlier in the code I performed a similar query to google fusion tables using the same parameter for callback.
The console.log call at the end of the code displays an empty array to the console.
Callback is used for JSONP requests which is mean't to be used when doing a cross domain request to fetch JSON data. Instead of using the XHR wrapper, it uses a script tag which then passes a callback querystring parameter which points to the function that is used to execute passing in all the JSON data inside. This way you can have a datapoint which has no idea of how your application works, but when you pass in a callback then it will fire a function with the data. This allows you to use it's API from any browser.
Like any other piece of data in a query string (or anywhere else between the hostname and the fragment id), it provides some data to the server. The meaning is entirely determined by the software running on that server.
There is a convention to use callback as the key for a value that will be used as the name of the function to call in a JSON-P response in a RESTful API. JSON-P is a means to provide a web service accessible across origins for browsers which do not support CORS.
e.g.
http://example.com/foo?callback=asdf
would give you
asdf([1,2,3]);
JSON-P, obviously, requires that the server support the sending of JSON-P responses. If you try to perform a cross-origin request with jQuery it will (by default) modify the request on the assumption that the server will support JSON-P with the usual conventions.
Read about Query Strings
They start with a ?, and additional parameters get concatnated with &. The ? should never be anywhere but the beginning of the string unless it's encoded.
The key value pairs then are available to the server, as this is how a standard GET request is performed.
For example:
http://myserver.com?name=josh&age=24&state=il
Your web server is probably choking on the query string somewhere.
Why does this not work? anybody:
In my code I have:
$.getJSON("http://isp123.co.uk/cw/NorthWales/Test.txt?jsoncallback=?",
function(data){
//This never gets executed
alert('here');
});
The text file can be viewed here:
http://isp123.co.uk/cw/NorthWales/Test.txt
This is not a JSONP response:
({"name" : "hello world"});
If you had a proper JSONP response, then your code should work.
The question mark in the "callback=?" part of the URL is changed by jQuery before making the request, your JSONP server needs to be able to dynamically create the JSONP "function" in response to the unique jQuery request. If you can't dynamically create your JSONP, perhaps you could use YQL/Yahoo pipes to turn it into JSONP?
This pipe should do the trick, to see if it works, use this URL instead in your getJSON function: http://pipes.yahoo.com/pipes/pipe.run?u=http%3A%2F%2Fisp123.co.uk%2Fcw%2FNorthWales%2FTest.txt&_id=332d9216d8910ba39e6c2577fd321a6a&_render=json&_callback=?
I just tried this and it worked:
$.getJSON("http://pipes.yahoo.com/pipes/pipe.run?u=http%3A%2F%2Fisp123.co.uk%2Fcw%2FNorthWales%2FTest.txt&_id=332d9216d8910ba39e6c2577fd321a6a&_render=json&_callback=?", function(data){
//This always gets executed!!!
alert('here');
});
I don't know if you know enough about JSONP but this is not JSONP
?({"name" : "hello world"});
It really should be something like this http://isp123.co.uk/cw/NorthWales/Test.txt?jsoncallback=foo
foo({"name" : "hello world"});
From the jQuery.getJson manual page:
Important: As of jQuery 1.4, if the JSON file contains a syntax error, the request will usually fail silently. Avoid frequent hand-editing of JSON data for this reason. JSON is a data-interchange format with syntax rules that are stricter than those of JavaScript's object literal notation. For example, all strings represented in JSON, whether they are properties or values, must be enclosed in double-quotes. For details on the JSON format, see http://json.org/.
Your JSON is invalid according to http://jsonlint.com/
Here Clearly mentioned
As of jQuery 1.5, setting the jsonp
option to false prevents jQuery from
adding the "?callback" string to the
URL or attempting to use "=?" for
transformation. In this case, you
should also explicitly set the
jsonpCallback setting
and read jsonpCallback section
jsonpCallback,
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
Probably worth using jQuery.ajax() - http://api.jquery.com/jQuery.ajax/
You can pass in the dataType as "jsonp" and then jQuery takes care of all the callback business, but more importantly you can specify a function to run when there's an error, which may help you:
$.ajax({
dataType: "jsonp",
success: function(d) {console.log(d);},
error: function() { console.log("error") } //do your debugging in here
//add other parameters such as URL, etc
});
The error function you define can be passed 3 variables, read up on it on the ajax() page on the jQuery docs (linked at the beginning of my post) to find out more about that and how to use them.
Your problem lies with how your server is outputting the information. In the link you've supplied, the assumption is that any name placed in the ?jsonpcallback should result in wrapping the JSONP code in a function with that same name. It, however, is not the case.
So the next option is this: use a static function name in your server file and wrap the code. (e.g. use foo(<jsonp>) and stick with it) Then, you have to explicitly tell jQuery that we are going to use a specific function name (leave jQuery with the assumption it's supplying (and thus receiving) that name back, when in-fact you're just supplying it server side and filling in the blanks).
Once you have your file setup, use something like the following:
$.ajax({
// setup the request
url: 'http://isp123.co.uk/cw/NorthWales/Test.txt',
crossDomain: true,
dataType: 'jsonp',
jsonp: false,
jsonpCallback: 'foo', // "supply" the jsonp function (pseudo-defined)
// function to call when completed
complete: function(data){
alert(data);
}
// just in case, catch the error
error: function(j,t,e){
alert('AJAX Error');
}
});
So now when jQuery makes the call and it thinks it's supplying the callback, it's really just getting the server-defined callback in return. So, for the above to work, your text file should look something like this:
foo({name:"Hello, World!"});
Also, if you can, change your header to application/javascript, though this is some-what optional.
I have an ajax script that sends some data to an external URL. The external URL is hosted on the same server, however the domain is different than the source of the ajax call.
This is working perfectly in Firefox and Chrome. However in IE The ajax call does not go through, and the Return False function does not either work (once the ajax call fails).
Below is my code:
$.get('http://myexternaldomian.com/feedback/save.php', {
answer: $('#answer').val(),
page_url: pathname
});
// Keeps the user on the page
return false;
When I try removing the http:// from the ajax url, the return false does work.
Any help on this would be greatly appreciated. Thank You
From jQuery documentation
Due to browser security restrictions,
most "Ajax" requests are subject to
the same origin policy; the request
can not successfully retrieve data
from a different domain, subdomain, or
protocol.
and Same Origin Policy on Wiki
I'm surprised any of them are working. Browsers generally don't allow ajax calls to a domain other than the one the current page came from.
The main exception to this rule is if you make an ajax call using jsonp (json with padding). You can do this with jQuery, here's how. Look under the dataType option.
(this is copypaste from my another similar answer). You could try enabling "jQuery.support.cors=true" flag and see how it goes. I use jQuery v1.7.2.
I had to load webpage from local disk "file:///C:/test/htmlpage.html", call "http://localhost/getxml.php" url, and do this in IE8+ and Firefox12+ browsers, use jQuery v1.7.2 lib to minimize boilerplate code. After reading dozens of articles finally figured it out. Here is my summary.
server script (.php, .jsp, ...) must return http response header Access-Control-Allow-Origin: *
before using jQuery ajax set this flag in javascript: jQuery.support.cors = true;
you may set flag once or everytime before using jQuery ajax function
now I can read .xml document in IE and Firefox. Other browsers I did not test.
response document can be plain/text, xml, json or anything else
Here is an example jQuery ajax call with some debug sysouts.
jQuery.support.cors = true;
$.ajax({
url: "http://localhost/getxml.php",
data: { "id":"doc1", "rows":"100" },
type: "GET",
timeout: 30000,
dataType: "text", // "xml", "json"
success: function(data) {
// show text reply as-is (debug)
alert(data);
// show xml field values (debug)
//alert( $(data).find("title").text() );
// loop JSON array (debug)
//var str="";
//$.each(data.items, function(i,item) {
// str += item.title + "\n";
//});
//alert(str);
},
error: function(jqXHR, textStatus, ex) {
alert(textStatus + "," + ex + "," + jqXHR.responseText);
}
});
http://en.wikipedia.org/wiki/Same_origin_policy
I dont think it should work on Chrome or Firefox, unless you testing on localhost or something like that, this would be against the crossdomain policy.
What you need is to proxy it inside the same domain, use php to connect to the destination you need and call the url from the same domain.
save_cross_domain.php -> connect through server to the desired url
then ajax calls save_cross_domain.php
you should add a
callback=?
to your url and handle this on the server side.
I did this once for a java servlet, and when the callback param was included I added an extra pair of parenteses around the json response..
hope it helps!
A couple of things:
The answers/conversation for this question has gone a bit out of context. Actually from the question it was more implied how to make ajax calls in IE. [Atleast modify the question title, else the question is very localized]
A couple of solutions to this cross-domain issue:
CORS[compatible after IE7]
JSONP [ here actually the browser takes in the input thinking it is a script]
server side encoding