MooTools Request Failing - javascript

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.

Related

How can I query the iTunes search API in javascript?

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);
});
}

Cross-domain requests stopped working due to no `Access-Control-Allow-Origin` header present in the response

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.

XMLHttpRequest.send() throws exception when asked for a DOM object

I want to retrieve a HTML page as document inside a Firefox/Greasemonkey userscript.
Edit: This is not a cross-domain request.
Here's my example code:
var r = new XMLHttpRequest();
r.open("GET", document.location.href, true);
r.responseType = "document";
r.send(null);
This looks just like the example in https://developer.mozilla.org/en/HTML_in_XMLHttpRequest ,
but r.send(null) causes a TypeError. Causes, not throws! Wrapping the line in a try...catch won't change anything, it seems like a callback or an event handler raises the exception:
TypeError: document.location is null
The traceback refers to a Firefox-internal event.js file, but not to my script.
Removing the line setting the responseType gets rid of the exception, adding callbacks does not.
However, the response is valid and responseXML provides a DOM tree.
I'm using FF 13.0.1.
Am I missing something or is this a bug?
Solution: This had something to do with an extension created by Mozilla's Addon Builder, not Firefox.
The script is running on google.com and you are trying to fetch google.de, right? That's a cross-domain request. (Also, the question code is not a valid synch or asynch use of XMLHttpRequest.)
To do cross-domain (or not) AJAX in a Greasemonkey script (Or Chrome), use GM_xmlhttpRequest().
Note that GM_xmlhttpRequest() does not currently let you specify responseType, but you don't need to do that in this case anyway. If you want a nice parsed document, use DOMParser.
Putting it all together:
GM_xmlhttpRequest ( {
method: 'GET',
//url: 'https://www.google.de/',
url: location.href, // self get, checking for updates
onload: function (respDetails) {
processResponse (respDetails);
}
} );
function processResponse (respDetails) {
// DO ALL RESPONSE PROCESSING HERE...
var parser = new DOMParser ();
var doc = parser.parseFromString (respDetails.responseText, "text/html");
//--- Example showing that the doc is fully parsed/functional...
console.log (doc.querySelectorAll ("p") );
}
PS: Since this is not cross-domain after all, the original code, corrected would be:
var r = new XMLHttpRequest();
r.onload = function () {
// DO ALL RESPONSE PROCESSING HERE...
console.log (this.response.querySelectorAll ("div") );
}
r.open ("GET", location.href, true);
r.responseType = "document";
r.send (null);
for an asynchronous request.
Unfortunately, you cannot do Ajax from one domain to another:
http://en.wikipedia.org/wiki/Same_origin_policy
You can read into CORS:
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
or JSONP as possible solutions:
http://en.wikipedia.org/wiki/JSONP
However, browsers are designed in such a way so that people can't just randomly create Ajax requests across domains due to this being a security issue.
If you absolutely need to grab content off a different domain, I'd look into creating your own server API using cURL, serving your own content on the same domain, and then using Ajax there. Otherwise, you'll have to see if Google will grant CORS access or has some sort of built in JSONP request.

Finding the URL of an XMLHttpRequest

I've got some code that does an ajax request using jQuery, and handles success and error conditions. On an error, I want to find out what the URL I called was, so I can log it. This information appears to be contained in the XMLHttpRequest.channel, but firefox is complaining about accessing this -
Permission denied for <http://localhost:8081> to get property XMLHttpRequest.channel
Any ideas how I can determine the URL associated with an XMLHttpRequest? What's the security issue getting hold of this information? Cheers,
Colin
Ok - sorry about this - an answer is here
http://api.jquery.com/ajaxError/
specifically this code from above link -
$('.log').ajaxError(function(e, xhr, settings, exception) {
if (settings.url == 'ajax/missing.html') {
$(this).text('Triggered ajaxError handler.');
}
});
shows how to access the request url in the event of an ajax error. Doesn't explain why the XMLHttpRequest.channel object is a no go though. Anyway, hopefully that will help others with a similar problem.
Well, you just add it ;]
XMLHttpRequest.prototype.baseOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async) { this._url = url; return XMLHttpRequest.prototype.baseOpen.apply(this, arguments); };
then you can later ask for xhr._url in your error handler.
PS: Sorry, just discovered this thread is old.
The security issue is cross domain XHR requests.
In FF2 you used to be able to override this in about:config, also see this blog and especially this preference:
user_pref("capability.policy.default.XMLHttpRequest.channel", "allAccess");
But that's all not possible anymore in FF3. And with a good reason.
Note that XMLHttpRequest.channel is Gecko-specific, so this wouldn't have worked in non-Gecko browsers.
Firebug presents this error with a trace that shows the URI used.

jQuery.ajax call fails inside Chrome extension

I'm porting one of my Firefox extensions to Chrome, and I'm running into a little problem with an AJAX query. The following code works fine in the FF extension, but fails with a status of "0" in Chrome.
function IsImage(url) {
var isImage = false;
var reImageContentType = /image\/(jpeg|pjpeg|gif|png|bmp)/i;
var reLooksLikeImage = /\.(jpg|jpeg|gif|png|bmp)/i;
if(!reLooksLikeImage.test(url))
{
return false;
}
var xhr = $.ajax({
async: false,
type: "HEAD",
url: url,
timeout: 1000,
complete : function(xhr, status) {
switch(status)
{
case "success":
isImage = reImageContentType.test(xhr.getResponseHeader("Content-Type"));
break;
}
},
});
return isImage;
}
This particular part of the extension checks what's on the clipboard (another Chrome issue I've already solved), and if it's an image URL, it sends a HEAD request and checks the "Content-Type" response header to be sure it's an image. If so, it'll return true, pasting the clipboard text in an IMG tag. Otherwise, if it looks like a normal URL that's not an image, it wraps it in an A tag. If it's not a URL, it just does a plain paste.
Anyway, the url being checked is definitely an image, and works fine in FF, but in the complete function, xhr.status is "0", and status is "error" when the function completes. Upping the timeout to 10 seconds doesn't help. I've verified the test images should come back as "image/jpeg" when running:
curl -i -X HEAD <imageURL>
I also know I should be using the success and error callbacks instead of complete, but they don't work either. Any ideas?
As you figured out Chris, in Content Scripts, you can't do any Cross-Domain XHRs. You would have to do them in an extension page such as Background, Popup, or even Options to do it.
For more information regarding content script limitation, please refer to:
http://code.google.com/chrome/extensions/content_scripts.html
And for more information regarding xhr limitation, please refer to:
http://code.google.com/chrome/extensions/xhr.html
I've solved part of the problem, actually most of it. First, as Brennan and I mentioned yesterday, I needed to set permissions in manifest.json.
"permissions": [
"http://*/*",
"https://*/*"
],
It's not ideal to give permissions to every domain, but since images can be hosted from any domain, it'll have to do, and I'll have to guard against XSS.
The other problem is that Chrome indeed blocks anything in the content_scripts section from making AJAX calls, failing silently. However, there is no such restriction on the background_page, if you have one. That page can make any AJAX calls it wants, and Chrome has an API to allow your script to open a port and pass requests to that background page. Someone wrote a script called XHRProxy as a workaround, and I modified it to get the appropriate response header. It works!
My only problem now is figuring out how to make the script wait for the result of the call to be set in the event, instead of just returning immediately.
Check your manifest file. Does the extension have permission to access that url?
If it helps to your second problem (or anyone else):
You can send a request to your background page like:
chrome.extension.sendRequest({var1: "var1value", var2: "value", etc},
function(response) {
//Do something once the request is done.
});
The Variable response can be anything you want it to be. It can simply be a success or deny string. Up to you.
On your background page you can add a listener:
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
// Do something here
// Once done you can send back all the info via:
sendResponse( anything you want here );
// and it'll be passed back to your content script.
});
With this you can pass the response from your AJAX request back to your content script and do whatever you wanted to do with it there.
The accepted answer is outdated.
Content scripts can now make cross-site XMLHttpRequests just like background scripts!
The concerning URLs need to be permitted in the manifest:
{
"name": "My extension",
...
"permissions": [
"http://www.google.com/"
],
...
}
You can also use expressions like:
"http://*.google.com/"
"http://*/"
to get more general permissions.
Here is the Link to the documentation.

Categories