Cross domain AJAX called with JSONP returns plain JSON - javascript

I have encountered a problem with an API I want to use. The API returns plain JSON but its a cross domain AJAX call so I have to use jsonp.
$.ajax({
type: "GET",
url: url + query,
contentType: "application/json",
dataType: "jsonp",
success: function(data){
console.log(data);
}
});
The problem is when I change the dataType to "json" an error occurs:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'X' is therefore not allowed access.
This is because its a cross domain ajax call. But when it is jsonp it says:
Uncaught SyntaxError: Unexpected token :
In other words it does not recognize the json format.
I am using jquery for the ajax call. Any suggestions how to solve this?

Since you dont have access to the server where the API is hosted, you use can a web service utility like CURL to access the API. AJAX calls requires CORS (Cross Origin Resource Sharing) to be enabled on the server where the API is served.
You can call a web service on your local server page via AJAX from where the CURL call will be made and appropriate response returned.

There are several methods of bypassing cross-domain restrictions (CORS, JSONP, Iframe transport, etc.) but all methods have in common that the API server needs to corporate. So if you don’t have privileges on the API server, you cannot come across the cross-domain restrictions.
The only way to make this work would be putting a proxy in front of the API that you can control (the proxy could either live on the same domain or inject the appropriate CORS headers). However, this will affect performance and might also have legal implications.
Regarding JSONP, here’s an excellent explanation of how and why this works:
What is JSONP all about?

Related

Call ajax HTTP to API with Sinatra

I'm calling a service from my api built with sinatra, and I make a simple ajax call as I mention it below:
<script>
$(document).ready(function (){
seeStatus()
});
function seeStatus(){
token = $('#token').val();
$.ajax({
url: '/see/v1/status/' + token,
type: 'GET',
dataType: "script",
complete: function (response) {
var json = $.parseJSON(response.responseText);
if (json.error == 0) {
window.location.href = json.href
}
}
});
}
</script>
made a GET call and the server receives a call OPTIONS
190.141.191.102 - - [08/Mar/2018:12:31:38 +0000] "OPTIONS /see/v1/status/f4dce2eb193674cab37ff36cbaca2eb4c0355165?_=1520512306539 HTTP/1.1" 404 51 0.0133
The code of my service is not executed from the ajax method and I do not understand why? , when I try my service independently with an HTTP client it works correctly What can I do? Any help Thanks
It looks like you're having an issue with CORS (Cross-Origin Resource Sharing). It would be interesting to know where the script requesting the API and where the API itself are located. I guess they're not on the same server.
In a nutshell, CORS is a mechanism that prevents a resource on one domain to freely access a resource on another domain. Your webpage can load resource on its own domain (scripts, stylesheets, fonts, json, etc.) but by default, Javascript HTTP requests (XMLHttpRequest / fetch) use the same-origin policy by default, which means they can only request resources on the same domain.
According to the CORS dedicated page on the MDN, here's the reason for the OPTIONS request you see on the server side:
the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with an HTTP OPTIONS request method"
I guess you'll have to configure CORS on your server, or make it so that the HTML file calling the API is located on the same domain as the API itself (which might not be possible).
Since you used the Sinatra tag in this question, I guess your server is written in Sinatra, in that case you can use the britg/sinatra-cross_origin gem to setup CORS rule on your API server.

How can i send cross domain ajax request with JSON response?

Guys,
I want to send a cross domain ajax request(http://dict.qq.com/dict?q=language), but the server only provides JSON(Not JSONP) response, is there anyway to make the request ?
Here's what i've did:
$.ajax({
url:"http://dict.qq.com/dict?q=language",
dataType:"jsonp",
type:'get',
processData:false,
crossDomain:true,
contentType:"application/json",
success:result
});
function result(data){console.log(data);}
The response is :
Uncaught SyntaxError: Unexpected token :
Thanks !
The server also needs to be configured to allow cross domain requests, something like:
Http.Response.current().accessControl("*", "GET,PUT,POST,DELETE,OPTIONS",false);
Generally the same origin policy prevents you from doing so.
If you have access to the other server you can attempt to change the http headers sent to circumvent this. Here's a tutorial for using CORS (Cross-Origin Resource Sharing) to achieve this.
If you have no control over the remote server perhaps you can try using a server-side proxy such as this one

Connect to webService using AJAX and CORS

I'm developing a phonegap App with html5, css, js and jQuery Mobile and I need to connect to a webservice which is already done and fully working. The problem is the Access Control Allow Origin and the Cross Domain. As if it wasn't hard enough I have to think about the authentication too, essential to connect to the web service. I already done my research, read a lot of tuts, tried a lot of solutions, some of them using jsonP which looked to me the closest one to work. The thing is I'm new at this and no tutorial looked good, so hopefully someone here could lead me the way. The webService was build in asp.net and I have full access to it if it's needed. I'm using AJAX to make the "call" but I can't pass the ForeFront authentication .
Here's the JS+AJAX code:
function conteudoProg() {
var webMethod = "myURL";
var credentials = {
username : "myUser",
password : "myPass"
};
$.ajax({
type : "GET",
url : webMethod,
//data: credentials,
contentType : "application/json; charset=utf-8",
dataType : "jsonp",
success : function(msg) {
alert(msg);
},
error : function(e) {
alert(e.status + " " + e.statusText );
}
});
}
If I change my dataType from jsonp to json, I get this error:
OPTIONS https://myURL 440 (Login Timeout)
XMLHttpRequest cannot load https://myURL Origin http://127.0.0.1:8020 is not allowed by Access-Control-Allow-Origin.
With jsonp, the error looks like this:
Resource interpreted as Script but transferred with MIME type text/html: "https://myURL/CookieAuth.dll?GetLogon?curl=Z2FWSInqueritosZ2FServ…1820135927463_1359737732559Z26_Z3D1359737732605&reason=0&formdir=3". jquery-1.8.2.min.js:2
Uncaught SyntaxError: Unexpected token <
Requests to another domain will cause a pre-flight OPTIONS request to see whether the requesting domain can make calls to this domain.
The receiving end needs to emit the correct headers or your browser will block the request and give you the error you posted.
Say you are requesting from mydomain.com to webservice.com
Then webservice.com/api should emit these headers:
Access-Control-Allow-Origin: http[s]://mydomain.com
Access-Control-Allow-Credentials: true # if you want cookies
Access-Control-Allow-Headers: Content-Type, X-Custom-Header # any extra headers you want to send
Make sure the webservice knows about OPTIONS requests. It really only needs to emit some CORS headers, it doesn't need to do anything else (like process a request to it's API).
You don't need to change anything in your AJAX handler, it will pass as any other request. If you want cookies make sure to set http_request.withCredentials = true;
Keep in mind that an HTTPS URL is considered to be different from an HTTP domain and make sure your HTTPS certificate is valid, if it's not valid the request may fail silently. If you're using a self-signed certificate (for testing) add it to your browser or OS whitelist.
Cross domain request from HTTP to HTTPS aborts immediately
As for compatibility. Earlier versions of Internet Explorer (8 and lower) use ActiveXObject, this API is very bad at CORS. It doesn't support authentication/cookies or custom headers (such as Content-Type: application/JSON). I would recommend a JSONp fallback.
The code does not work because when you tell jQuery that the .ajax method expects a dataType json, that's what's trying to parse the response into. If the response is html then you should use a dataType html (or none, to let the default intelligent guess do it's work). See jQuery.ajax() dataType for more info.

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

Basic Authentication with jQuery.ajax request and jsonp

I have some local html/js files with which I'd like to invoke some remote servers via https and eventually use Basic Authentication for the request.
I am encountering two problems. First is that if I don't specify 'jsonp' for the dataType, jQuery.ajax() request returns the error:
Access to restricted URI denied code:
1012
Are my requests considered cross-domain because my main work file is stored locally, but retrieving data from a server elsewhere?
So fine, I update the call so it now looks like:
$.ajax({
url: myServerUrl,
type: "GET",
dataType: "jsonp", // considered a cross domain Ajax request if not specified
username: myUsername,
password: myPassword,
success: function(result)
{
// success handling
},
error: function(req, status, errThrown){
// error handling
}
})
Because I need to use Basic Authentication, I'm passing in the username/password but if I monitor the request, I don't see it being set and additionally, the server sends an error response since it doesn't have the expected info.
Additionally, because I have jsonp set, beforeSend won't get invoked.
How do I pass along the credentials using Basic Authentication for this request?
The short version is you can't do this. Your suspicions are correct, because you're local and these files are remote, you can't access them, you're being blocked by the same-origin policy. The work-around for that is JSONP, but that really doesn't seem to apply to your situation...
JSONP works differently, it's a GET request via a <script> tag include to get the file, so you're not sending special headers or anything.
You'll need to proxy the request through the server you're on (the domain of where this script is running) or another proxy option, but going from the client to another domain is blocked, mainly for security reasons.
Try doing http://user:password#restservice. This mimics a basic-auth request.
I think you'll have to add a server proxy of some sort. JSONP is just a particular way to use a script tag. Thus, it doesn't allow setting arbitrary headers. And of course, you can't do a cross-origin XHR.

Categories

Resources