Parse image url from JSON api - javascript

I am having problems getting an image URL from a Wordpress JSON API and fill in an image tag.
Here's my non-working code:
$(document).ready(function() {
$.getJSON('http://interelgroup.com/api/get_post/?post_id=4683', {format: "json"}, function(data) {
$('#thumb').attr("src", data.post.thumbnail_images.full.url);
});
});
And the HTML is like:
<img id="thumb" src="#">
What am I doing wrong?
Help appreciated.
Thanks!
NOTE: My real case is dynamic (I am getting a dynamic list of post IDs and looping through them with $.each()), but for this case I am providing an example with an hardcoded post ID, so you can check the JSON returned.

Your problem is because you can't do cross request using Javascript, say websiteA.com wants to fetch information from websiteB.com with a plain XMLHttpRequest. That's forbidden by the Access Control.
A resource makes a cross-origin HTTP request when it requests a resource from a different domain than the one which served itself. For example, an HTML page served from http://domain-a.com makes an <img> src request for http://domain-b.com/image.jpg. Many pages on the web today load resources like CSS stylesheets, images and scripts from separate domains.
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest follows the same-origin policy. So, a web application using XMLHttpRequest could only make HTTP requests to its own domain. To improve web applications, developers asked browser vendors to allow XMLHttpRequest to make cross-domain requests.
If you know the owner of the website you're trying to read, what you can do is asking them to add your domain to the whitelist in the page headers. If you do so, then you can do as much as $.getJSON as you want.
Another alternative could be using some sort of backend code to read that website and serve it locally. Say your website is example.com, you could have a PHP script that runs on example.com/retrieve.php where you can query that website, adding the "parameter" you need. After that, since example.com is your own website you can just do a $.getJSON to yourself. There's a simple PHP proxy you can use here with a bit of explanation on why you can do it this way.
A third option would be editing the Javascript code to use Yahoo! YQL service. Although there's no guarantee that'll work forever, you can use it to query the website on your behalf and then use it to print whatever you want to the screen. The downside is that this maybe is not ethically correct if you do not own the website you're trying to fetch (plus, they can add a robots.txt file preventing the access).
Hope that helps.

JSONP solves the problem. Just need to add a callback parameter and specify it is a JSONP, like:
$(document).ready(function() {
$.getJSON('http://interelgroup.com/api/get_post/?post_id=4683&callback=?', {format: "jsonp"}, function(data) {
$('#thumb').attr("src", data.post.thumbnail_images.full.url);
});
});
More info here: Changing getJSON to JSONP
Info on JSONP: https://en.wikipedia.org/wiki/JSONP

Related

Make REST call in JavaScript without using JSON?

(extremely ignorant question, I freely admit)
I have a simple web page with a button and a label. When I click the button, I want to make a REST call to an entirely different domain (cross-domain, I know that much) and display the results (HTML) in the label.
With other APIs, I've played around with using JSON/P and adding a element on the fly, but this particular API doesn't support JSON so I'm not sure how to go about successfully getting through.
The code I have is:
function getESVData() {
$.get('http://www.esvapi.org/v2/rest/passageQuery?key=IP&passage=John+1', function (data) {
$('#bibleText').html(data);
app.showNotification("Note:", "Load performed.");
});
}
I get an "Access denied." Is there anyway to make this call successfully without JSON?
First off, JSON and JSONP are not the same. JSON is a way of representing information, and JSONP is a hack around the same-origin policy. JSONP works by requesting information from another domain, and that domain returns a script which calls a function (with the name you provided) with the information. You are indeed executing a script on your site that another domain gave to you, so you should trust this other domain.
Now when trying to make cross domain requests you basically have 3 options:
Use JSONP. This has limitations, including the fact that it only works for GET requests, and the server you are sending the request to has to support it.
Make a Cross Origin Resource Sharing (CORS) request. This also must be supported by the server you are sending the request to.
Set up a proxy on your own server. In this situation you set an endpoint on your site that simply relays requests. ie you request the information from your server, your server gets it from the other server and returns it to you.
For your situation, it the other server doesn't have support for other options, it seems like you will have to go with options 3.

jQuery cross domain image upload

Ok, so basically.
I inject some javascript code into a web page and it uploads an image on that page to another server.
Now I have it working when I run it on my domain (of course), but I need to post the multipart/form-data request to a PHP file that I do not own.
Since it is a upload and not a simple request to just get data, I cannot use jsonp in the initial call since the response would not be in json.
Using James Padolsey's cross domain script, I am able to do $.get and $.post request across domains, but since I am using $.ajax it does not work.
He uses the Yahoo Query Language to acomplish this
This is basically how I am making the request
$.ajax({
url: 'http://website.com/upload.php',
type: 'POST',
contentType:'multipart/form-data',
data: postData,
success: successCallback,
error : function(XMLHttpRequest, textStatus, errorThrown) {
console.log('Error');
}
});
I want to make it completely JavaScript based to avoid making my server do the request.
So to re-cap, I can get the image bytes and make the request with javascript. But so far I cannot make it cross domain since I am $.ajax to set the content Type to "multipart/form-data".
Is there another way to make the request cross domain with or without the YQL?
Making the request with an iframe will not work since the domain of the iframe would change and I would not have access to the response.
This is a well known and difficult problem for web development, know as the Same Origin Policy
Javascript prevents access to most methods and properties to pages across different origins. The term "origin" is defined using the domain name, application layer protocol, and (in most browsers) port number of the HTML document running the script. Two resources are considered to be of the same origin if and only if all these values are exactly the same.
There are several ways around this.
Create your own proxy
Create a page that simply forwards the request to the other server, and returns its response
or, Use Apache's rules to form a proxy (see above link)
Use someone else's proxy
For GET requests which are typical Use YQL to access yahoo's proxy
For POST requests, if the 3rd party supports Open Data Tables
or, Use some other public proxy
See if the 3rd party conforms to the CORS specification
Cross domain POST query using Cross-Origin Resource Sharing getting no data back
If you are willing to allow a little flash on your page, try flXHR
it claims to implement the exact XHR api and also has a jquery plugin
These are pretty much your only options

How to do cross domain ajax in jQuery with dataType 'text'?

In my javacript function I call this ajax. It works fine but only when I access the web page from firebird server. I have the same code on my testing server. The ajax asks to download some files but only firebird server has its ip registers with our clients to be able to scp there. I need to do the same if I access the php files from testing server. All the servers are inside intranet.
is it possbile to use dataType text to do so?
do I need to do any changes on the server side?
ajax call:
url = "https://firebird"+path+"/tools.php?";
jQuery.ajax({
type: 'get',
dataType: 'text',
url: url,
data: {database: database_name, what: 'download', files: files, t: Math.random() },
success: function(data, textStatus){
document.getElementById("downloading").innerHTML+=data;
}
});
Update 1
My little web application restores databases so I can do my testing on them. Now I want to enhance it so I can connect to our customers and download a particular backup. Our customer allowed only firebird server to connect to their networks. But I have my own server dedicated to testing. So every time I want to download a database I need to connect firebird. The source of my web application and the folder with all backups are mounted into the same location on both servers firebird and testing. Right now my solution (for downloading) works but only from firebird. I work basically only testing server though.
Update 2
I make two ajax calls. One is pure jQuery call (I guess I can apply any solution to this one) and the other one is ajax call from jsTree. I created new question for that one. I seems to me that I have to go for #zzzz's option b).
To do cross domain requests, your options are fairly limited. As #Mrchief mentioned, you could do server side proxy and jsonp.
Another option is Cross-Origin Resource Sharing (CORS), a W3C working draft. Quoting from this blog post:
The basic idea behind CORS is to use custom HTTP headers to allow both
the browser and the server to know enough about each other to
determine if the request or response should succeed or fail.
For a simple request, one that uses either GET or POST with no custom
headers and whose body is text/plain, the request is sent with an
extra header called Origin. The Origin header contains the origin
(protocol, domain name, and port) of the requesting page so that the
server can easily determine whether or not it should serve a response.
You can find some live examples on this site.
You will need to make changes to the server side, to accept the CORS requests. Since you have control over the server, this shouldn't be a problem. Another downside with CORS is that, it might not be compatible with older browsers. So, if some of your essential audiences use incompatible browsers, the server side proxy may actually be a better option for you.
I just want to offer an alternative.
I am not too sure regarding your network setup, but if you have access to the DNS, maybe it would be easiest if you just give your servers some arbitrary subdomain of the same domain. Something like www.foo.com for the webfront and firebird.private.foo.com for the firebird server. This way, it becomes cross subdomain instead of cross domain. Then somewhere in your JavaScript on both pages,
document.domain = "foo.com";
This gentleman achieved this solution here.
You have the following options with you
a) You use jsonp type as your datatype but this involves making changes on the server side to pass the data back as json and not as txt.. this change might be as simple as
{
"text":<your current text json encoded>
}
and on your js side you use this as response.text; Having said that if you are getting the textis for you file from sm other domain I am not sure how easy it is for you to change the code.
b) The other option is you write a handler/end point on your server i.e within your domain that will make an HTTP request to this third domain gets the file and you send the file back to your client and effectively now your client talks to your domain only and you have control over everything. as most of yoyr questions are based on ruby here is an example:
req = Net::HTTP.get_response(URI.parse('http://www.domain.com/coupons.txt'))
#play = req.body
you can find more details about the same here.
Hope this helps.
Another idea is to use you web server as a proxy. You will need to consider the security implications for this route.

Cross-domain website promotion

I'd like to offer a way to my users to promote my website, blog etc. on their website.
I can make a banner, logo whatever that they can embed to their site, but I'd like to offer dynamic content, like "the 5 newest entry's title from my blog".
The problem is the same origin policy. I know there is a solution (and I use it): they embed a simple div and a JavaScript file. The JS makes an XmlHttpRequest to my server and gets the data as JSONP, parses the data and inserts into the div.
But is it the only way? Isn't there a better way I could do this?
On the Internet there are tons of widget (or whatever, I don't know how they call...) that gain the data from another domain. How they do that?
A common theme of many of the solutions, instead, is getting JavaScript to call a proxy program (either on the client or the server) which, in turn, calls the web service for you.
The output can be written to the response stream and then is available, via the normal channels, such as the responseText and responseXML properties of XMLHttpRequest.
you can find more solution here :
http://developer.yahoo.com/javascript/howto-proxy.html
or here :
http://www.simple-talk.com/dotnet/asp.net/calling-cross-domain-web-services-in-ajax/
CORS is a different way than JSONP.
Plain AJAX. All your server has to do is to set a specific header: Access-Control-Allow-Origin
More here: http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
If you go the JSONP route, you will implicitly ask your users to trust you, as they will give you full access to the resources of their page (content, cookies,...). If they know that they main complain.
While if you go the iframe route there is no problems.One famous example today of embeddable content by iframe is the Like button of facebook.
And making that server side with a proxy or other methods would be much more complex, as there are plenty of environments out there. I don't know other ways.
You can also set the HTTP Access-Control headers in the server side. This way you're basically controlling from the server side on whether the client who has fired the XMLHttpRequest is allowed to process the response. Any recent (and decent) webbrowser will take action accordingly.
Here's a PHP-targeted example how to set the headers accordingly.
header('Access-Control-Allow-Origin: *'); // Everone may process the response.
header('Access-Control-Max-Age: 604800'); // Client may cache this for one week.
header('Access-Control-Allow-Methods: GET, POST'); // Allowed request methods.
The key is Access-Control-Allow-Origin: *. This informs the client that requests originating from * (in fact, everywhere) is allowed to process the response. If you set it to for example Access-Control-Allow-Origin: http://example.com, then the webbrowser may only process the response when the initial page is been served from the mentioned domain.
See also:
MDC - HTTP Access Control

A question about cross-domain (subdomain) ajax request

Let's say I have the main page loaded from http://www.example.com/index.html. On that page there is js code that makes an ajax request to http://n1.example.com//echo?message=hello. When the response is received a div on the main page is updated with the response body.
Will that work on all popular browsers?
Edit:
The obvious solution is to put a proxy in front of www.example.com and n1.example.com and set it so that every request going to a subresource of http://www.example.com/n1 gets proxied to http://n1.example.com/.
Cross domain is entirely a different subject. But cross sub-domain is relatively easy. All you need to do is to set the document.domain to be same in both the parent page and the iframe page.
document.domain = "yourdomain.com"
More info here
Note: this technique will only let you interact with iframes from parents of your domain. It does not alter the Origin sent by XMLHttpRequest.
All modern browsers support CORS and henceforth we should leverage this addition.
It works on simple handshaking technique were the 2 domains communicating trust each other by way of HTTP headers sent/received. This was long awaited as same origin policy was necessary to avoid XSS and other malicious attempts.
To initiate a cross-origin request, a browser sends the request with an Origin HTTP header. The value of this header is the site that served the page. For example, suppose a page on http://www.example-social-network.com attempts to access a user's data in online-personal-calendar.com. If the user's browser implements CORS, the following request header would be sent:
Origin: http://www.example-social-network.com
If online-personal-calendar.com allows the request, it sends an Access-Control-Allow-Origin header in its response. The value of the header indicates what origin sites are allowed. For example, a response to the previous request would contain the following:
Access-Control-Allow-Origin: http://www.example-social-network.com
If the server does not allow the cross-origin request, the browser will deliver an error to example-social-network.com page instead of the online-personal-calendar.com response.
To allow access to all pages, a server can send the following response header:
Access-Control-Allow-Origin: *
However, this might not be appropriate for situations in which security is a concern.
Very well explained here in below wiki page.
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Another solution that may or may not work for you is to dynamically insert/remove script tags in your DOM that point to the target domain. This will work if the target returns json and supports a callback.
Function to handle the result:
<script type="text/javascript">
function foo(result) {
alert( result );
}
</script>
Instead of doing an AJAX request you would dynamically insert something like this:
<script type="text/javascript" src="http://n1.example.com/echo?callback=foo"></script>
Another workaround, is to direct the ajax request to a php (for example) page on your domain, and in that page make a cURL request to the subdomain.
The simplest solution I found was to create a php on your subdomain and include your original function file within it using a full path.
Example:
www.domain.com/ajax/this_is_where_the_php_is_called.php
Subdomain:
sub.domain.com
Create:
sub.domain.com/I_need_the_function.php
Inside I_need_the_function.php just use an include:
include_once("/server/path/public_html/ajax/this_is_where_the_php_is_called.php");
Now call sub.domain.com/I_need_the_function.php from your javascript.
var sub="";
switch(window.location.hostname)
{
case "www.domain.com":
sub = "/ajax/this_is_where_the_php_is_called.php";
break;
case "domain.com":
sub = "";
break;
default: ///your subdomain (or add more "case" 's)
sub = "/I_need_the_function.php";
}
xmlHttp.open("GET",sub,true);
The example is as simple as I can make it. You may want to use better formatted paths.
I hope this helps some one. Nothing messy here - and you are calling the original file, so any edits will apply to all functions.
New idea: if you want cross subdomain (www.domain.com and sub.domain.com) and you are working on apache. things can get a lot easier. if a subdomain actually is a subdirectory in public_html (sub.domain.com = www.domain.com/sub/. so if you have ajax.domain.com/?request=subject...you can do something like this: www.domain.com/ajax/?request=subject
works like a charm for me, and no stupid hacks, proxies or difficult things to do for just a few Ajax requests!
I wrote a solution for cross sub domain and its been working for my applications. I used iframe and setting document.domain="domain.com" on both sides. You can find my solution at :
https://github.com/emphaticsunshine/Cross-sub-domain-solution

Categories

Resources