im want to call haveibeenpwned v3 API,
here is my code
<script>
$.ajax({
url:"https://haveibeenpwned.com/api/v3/breachedaccount/brian.c#softnet.co.id",
headers: { 'Content-type': 'x-www-form-urlencoded', 'hibp-api-key': 'my-key'},
async: false,
datatype:'application/json',
success:function(data){
alert("a");
},
error:function(data){
console.log(JSON.stringify(data));
}
});
</script>
but i always get this this error at the console
{"readyState":0,"status":0,"statusText":"NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'https://haveibeenpwned.com/api/v3/breachedaccount/brian.c#softnet.co.id'."}
pls help me if you ever use haveibeenpwned.com
i already doing this way with another api, this is my first time with headers
i expect the json output
You likely have some other errors in your console too which are more relevant than the one you posted - including, I expect, a CORS-related error.
According to https://haveibeenpwned.com/API/v3#CORS you may have a problem because
"CORS is only supported for non-authenticated APIs".
...and according to https://haveibeenpwned.com/API/v3#Authorisation
Authorisation is required for all APIs that enable searching HIBP by email address...The key is then passed in a "hibp-api-key" header
Therefore the endpoint you are trying to search is one requiring authentication/authorisation and as such you are not allowed to make a CORS (cross-origin ) AJAX request to it.
In conclusion you will need to connect to this API via your server-side code instead.
Related
I am trying to query the App Store for information on a given app, however I keep getting the following error.
XMLHttpRequest cannot load https://itunes.apple.com/lookup?id=<some-app-id>.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://www.<some-website>.co.uk' is therefore not allowed access. The response had HTTP status code 501.
The code I'm using to execute the request is as follows.
Does anyone know where I may be going wrong?
var config = {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With',
}
};
$http.get("https://itunes.apple.com/lookup?id=<some-app-id>", config).success(
function(data) {
// I got some data back!
}
);
You can use $http.jsonp,
$http.jsonp("https://itunes.apple.com/lookup", {
params: {
'callback': 'functionName',
'id': 'some-app-id'
}
});
Where functionName is the name of your globally defined function in string form. You can redefine it in your module so that it has access to $scope.
Documentation
Edit: here's a plunker showing my successful approach roughly getting it into an AngularJS app:
http://plnkr.co/edit/QhRjw8dzK6Ob4mCu6T6Z?p=preview
Adding those headers to your server won't change what is happening. The cross origin headers need to be added by the iTunes API.
That is not going to happen, so what you need to do instead is to use JSONP style callbacks in your webpage. There is an example on the iTunes search API page.
http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html
Note: When creating search fields and scripts for your website, you
should use dynamic script tags for your xmlhttp script call requests.
For example:
<script src="https://.../search?parameterkeyvalue&callback="{name of JavaScript function in webpage}"/>
Note the 'callback' parameter there. That is a function defined globally in your javascript on the page that will get called with the response from the request to the url in 'src'. That function puts the data into your page, or application. You'll have to figure out how.
It's a shame that the language used in this documentation is not clearer, because you must do some kind of JSONP style workaround since they don't have CORS enabled on their API.
If you need to dynamically add a script tag (fetching data once is not enough) you can try this tutorial:
Dynamically add script tag with src that may include document.write
The API in general is probably intended for use by backends (not affected by cross origin issues), not for client side fetching.
Using angular 2:
constructor(private _jsonp: Jsonp) {}
public getData(term: string): Observable<any> {
return this._jsonp.request(itunesSearchUrl)
.map(res => {
console.log(res);
});
}
I have an error reporting beacon I created using Google Apps script and it is published to run as myself and to be accessible to "anyone, even anonymous," which should mean that X-domain requests to GAS are allowed.
However, my browsers are now indicating there is no Access-Control-Allow-Origin header on the response after the code posts to the beacon.
Am I missing something here? This used to work as recently as two months ago. So long as the GAS was published for public access, then it was setting the Access-Control-Allow-Origin header.
In Google Apps Script:
Code.gs
function doPost(data){
if(data){
//Do Something
}
return ContentService.createTextOutput("{status:'okay'}", ContentService.MimeType.JSON);
}
Client Side:
script.js
$.post(beacon_url, data, null, "json");
When making calls to a contentservice script I always have sent a callback for JSONP. Since GAS does not support CORS this is the only reliable way to ensure your app doesn't break when x-domain issues arrive.
Making a call in jQuery just add "&callback=?". It will figure everything else out.
var url = "https://script.google.com/macros/s/{YourProjectId}/exec?offset="+offset+"&baseDate="+baseDate+"&callback=?";
$.getJSON( url,function( returnValue ){...});
On the server side
function doGet(e){
var callback = e.parameter.callback;
//do stuff ...
return ContentService.createTextOutput(callback+'('+ JSON.stringify(returnValue)+')').setMimeType(ContentService.MimeType.JAVASCRIPT);
}
I've lost a couple of hours with the same issue. The solution was trivial.
When you deploy the script as webapp, you get two URLs: the /dev one and the /exec one. You should use /exec one to make cross domain POST requests. The /dev one is always private: it requires to be authorized and doesn't set *Allow-Origin header.
PS.: The /exec one seems to be frozen — it doesn't reflect any changes of code until you manually deploy it with a new version string (dropdown list in deploy dialog). To debug the most recent version of the script with the /dev URL just install an alternative browser and disable it's web-security features (--disable-web-security in GoogleChrome).
Just to make it simpler for those who are only interested in a POST request like me:
function doPost(e){
//do stuff ...
var MyResponse = "It Works!";
return ContentService.createTextOutput(MyResponse).setMimeType(ContentService.MimeType.JAVASCRIPT);
}
I stumbled upon the same issue:
calling /exec-urls from the browser went fine when running a webpage on localhost
throws crossorigin-error when called from a https-domain
I was trying to avoid refactoring my POST JSON-clientcode into JSONP (I was skeptical, since things always worked before).
Possible Fix #1
Luckily, after I did one non-CORS request (fetch() in the browser from a https-domain, using mode: no-cors), the usual CORS-requests worked fine again.
last thoughts
A last explanation might be: every new appscript-deployment needs a bit of time/usage before its configuration actually settled down at server-level.
Following solution works for me
In Google Apps Script
function doPost(e) {
return ContentService.createTextOutput(JSON.stringify({status: "success", "data": "my-data"})).setMimeType(ContentService.MimeType.JSON);
}
In JavaScript
fetch(URL, {
redirect: "follow",
method: "POST",
body: JSON.stringify(DATA),
headers: {
"Content-Type": "text/plain;charset=utf-8",
},
})
Notice the attribute redirect: "follow" which is very very important. Without that, it doesn't work for me.
I faced a similar issue of CORS policy error when I tried to integrate the app script application with another Vue application.
Please be careful with the following configurations:
Project version should be NEW for every deployment.
Execute the app as me in case you want to give access to all.
Who has access to the app to anyone, anonymous.
Hope this works for you.
in your calling application, just set the content-type to text/plain, and you will be able to parse the returned JSON from GAS as a valid json object.
Here is my JSON object in my google script doPost function
var result = {
status: 200,
error: 'None',
rowID: rowID
};
ws.appendRow(rowContents);
return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);
and here I am calling my app script API from node js
const requestOptions = {
method: 'POST',
headers: {'Content-Type': 'text/plain'},
body: JSON.stringify({param1: value, param2:value})
};
const response = await fetch(server_URL, requestOptions);
const data = await response.json();
console.log(data);
console.log(data.status);
My case is different, I'm facing the CORS error in a very weird way.
My code works normally and no CORS errors, only until I added a constant:
const MY_CONST = "...";
It seems that Google Apps Script (GAS) won't allow 'const' keyword, GAS is based on ES3 or before ES5 or that kind of thing. The error on 'const' redirect to an error page URL with no CORS.
Reference:
https://stackoverflow.com/a/54413892/5581893
In case this helps all any of those people like me:
I have a .js file which contains all my utility functions, including ones which call a GAS. I keep forgetting to clear my cache when I go to test updates, so I'll often get this kind of error because the cached code is using the /dev link instead of the /exec one.
I'm currently working on a userscript/extension for Chrome and am trying to pull in some JSON data from "some website". This was my approach:
$.get( "http://cloud.hartwig-at.de/~oliver/superuser.json",
function( data ) { console.log( data ); }
);
Of course, that leads to the following error:
XMLHttpRequest cannot load http://cloud.hartwig-at.de/~oliver/superuser.json. Origin http://superuser.com is not allowed by Access-Control-Allow-Origin.
I was able to resolve that after reading Origin 'url' is not allowed by Access-Control-Allow-Origin (among other questions). So, this is the next version:
$.get( "http://cloud.hartwig-at.de/~oliver/superuser.json",
function( data ) { console.log( data ); },
"jsonp"
);
Sadly, that results in another error:
Uncaught SyntaxError: Unexpected token : (superuser.json:2)
There's also a warning telling me "Resource interpreted as Script but transferred with MIME type text/plain:" which already gave me an idea what the trouble could be. (And more details were provided through Chrome says "Resource interpreted as script but transferred with MIME type text/plain.", what gives?)
Apparently, the HTTP server has to send the proper MIME type for my file, which would be application/json.
Okay, So I quickly added the required change to my mime.types and went for another go. But, no dice! The warning went away, the error didn't. I still get Uncaught SyntaxError: Unexpected token :. (I had also previously attempted to utilize the mimeType parameter to fix this, the outcome was the same.)
The MIME type looks fine though:
Now I'm somewhat out of ideas. The content of the .json file validates fine on http://www.jslint.com/
Telling the jQuery's get to do JSONP does not magically make it work. It makes a JSONP request, but the server on the other end needs to support JSONP calls.
The response from the server should look something like
someFunction( { "foo" : "bar" } );
See jQuery's docs on getJSON with JSONP to see how to use the callback
If it is a modern day browser you can use CORS and you have control over the second domain.
Other option is a serverside proxy on your domain that requests data from the other domain. Or you can use a service like Yahoo pipes.
You can't use JSONP on a request unless the server supports it. The way JSONP calls work is that you pass a callback=something parameter along with the request and the server encapsulates the JSON with something() so that it can be loaded by your browser by calling something when the script is accessed.
Another way to get it to work is to configure that server to set the CORS headers correctly, if you own the domain.
If you don't have access to the server, consider using a JSONP proxy, which wraps the first step for you. I've used YQL to do this (see the link), which doesn't require me to set anything up myself. Below is coffeescript code that does that:
uri = "http://cloud.hartwig-at.de/~oliver/superuser.json"
jqxhr = $.getJSON \
"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" \
+ encodeURIComponent(uri) + "%22&format=json&callback=?"
jqxhr.success (yql) ->
unless yql.query.results
alert("Failed to get stuff")
return
json = $.parseJSON(yql.query.results.body.p)
# do stuff with json
And in the form of javascript using http://js2coffee.org:
uri = "http://cloud.hartwig-at.de/~oliver/superuser.json";
jqxhr = $.getJSON("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22"
+ encodeURIComponent(uri) + "%22&format=json&callback=?");
jqxhr.success(function(yql) {
var json;
if (!yql.query.results) {
alert("Failed to get stuff");
return;
}
json = $.parseJSON(yql.query.results.body.p);
// do stuff with json
});
I'm grabbing user information from the Last.fm website with a JQuery $.get request.
Since some users' accounts are private, I sometimes receive a 403 error stating that authentication is required. This breaks the JS code. The last.fm API doesn't let you see if a user is private or not.
Is there a way to catch this error and continue through the code?
Thanks!
Not sure if it works with cross-domain requests, but you could do something like this:
$.ajax({
type: 'GET',
statusCode: {
403: function() {
alert('a 403 was received');
}
},
success: function() {
alert('everything OK');
}
});
Or possibly set it up in $.ajaxSetup() if it works ?
You would be better using a proxy to get the data from API since $.ajax() error handler won;t return errors for cross domain requests per jQery API docs:
http://api.jquery.com/jQuery.ajax/
EDIT Note in docs for error option:
"Note: This handler is not called for cross-domain script and JSONP requests."
So I have a bit of a problem. When I ask MooTools to send a request it comes back as failed every time. I can't seem to diagnose the problem either because if I try to get the returned header info the console just gives me "Refused to get unsafe header 'Status'" Message. The only thing I can think of is that the server isn't letting me access outside resources but maybe I just coded it wrong.
Here's the request code:
var finfo = current.textFontData();
var url = 'http://antiradiant.com/clients/TMW/rbwizard/mailer.php?s='+current.size+'&b='+current.box+'&l='+current.lidWood+'&c='+current.cartID+'&f='+finfo.font+'&l1='+finfo.line1+'&l2='+finfo.line2;
console.log(url);
var req = new Request({
url: url,
onSuccess: function() {
console.log('success');
//atc2.send();
},
onFailure: function() {
console.log('failure');
console.log(this.getHeader('Status'));
//atc2.send();
},
onException: function(headerName, value) {
console.log('exception');
console.log(headerName+': '+value);
}
});
req.send();
This code is derived from the resource rb_wizard.js (lines 81-103) on http://tylermorriswoodworking.myshopify.com/pages/recipe-box-wizard?b=maple&l=cherry&s=3x5&c=42042892
Mootools has a class called Request.JSONP that will help with your cross domain problem. Its sub class of the Request class, so your methods should work the same. I believe you need to call .post() or .get() at the end instead of send, but thats about all that should chnge. I'm not sure what version you're running on but here is the link tot he docs Mootools Request.JSONP
The error message "Refused to get unsafe header 'Status'" is spat out by WebKit based browsers (Safari, Chrome, etc) when you violate the cross-domain security model.
Therefore, it seems likely that the code you pasted is located on a domain other than antiradiant.com, and therefore is not allowed (by the browser) to request sites on antiradiant.com.
What I ended up doing was just using an iframe. All I really had to do was send data to another site and not receive any so it worked out.