Firefox addon sdk Request module POST method with payload - javascript

I need to do a POST method inside a firefox add-on to another server, I have been trying to use different ways, and after googling I found out that I should use the Request module from the SDK inside my main.js.
I am using firefox v 23
I tried using the chrome module
var xmlhttp = chrome.Cc["#mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(chrome.Ci.nsIXMLHttpRequest);
but I got NS_ERROR_FAILURE. I even added the permissions in the package.json
"permissions": {
"cross-domain-content": ["https:[some url]"]
}
But it still gives the same error.
I then used the Request module but didn't work so far. I tried a GET method with the Request module and it works fine. But the POST method always returns a 0 status and an empty response.
I tried doing the same request via a browser http client and it worked fine!! But through the code inside the add-on it always returns a 0.
The request sets headers and of course has a payload.
var contentObject = {[Valid JSON Object]};
var myRequest = Request({
url: "https://[some url]",
headers: {
"pragma": "no-cache"
},
content: contentObject,
contentType: "application/json",
onComplete: function (response) {
console.log("Status: " + response.status);
console.log("Response json: " + JSON.stringify(response));
}
}).post();
Your support is highly appreciated. There are very few resources I found over the internet about this issue and non of them solved my problem.

I guess the server script expects a JSON string representation of the contentObject. But this is not how objects are treated by the request module, they are turned to key/value pairs.
So change
content: contentObject
to
content: JSON.stringify(contentObject)

the POST method always returns a 0 status and an empty response
This might not be direct answer, but I had the same problem last couple of days. A friend who was connected to network via different provider tried the same code and it worked fine. Also, if I remember correctly, I could connect to the port 80 but not to the port where I was sending POST request so that port might be blocked on the network you are connected.

Related

Trouble with Cloudflares Worker Cache API

I’ve now spent countless hours trying to get the cache API to cache a simple request. I had it working once in between but forgot to add something to the cache key, and now its not working anymore. Needless to say, cache.put() not having a return value that specifies if the request was actually cached or not does not exactly help and I am left with trial and error. Can someone maybe give me a hint on what I’m doing wrong and what is actually required? I’ve read all the documentation more than 3 times now and I’m at a loss…
Noteworthy maybe is that this REST endpoint sets pragma: no-cache and everything else cache-related to no-cache, but i want to forcibly cache the response anyway which is why I tried to completely re-write the headers before caching, but it still isn’t working (not matching or not storing, no one knows…)
async function apiTest(token, url) {
let apiCache = await caches.open("apiResponses");
let request = new Request(
new URL("https://api.mysite.com/api/"+url),
{
headers: {
"Authorization": "Bearer "+token,
}
}
)
// Check if the response is already in the cloudflare cache
let response = await apiCache.match(request);
if (response) {
console.log("Serving from cache");
}
if (!response) {
// if not, ask the origin if the permission is granted
response = await fetch(request);
// cache response in cloudflare cache
response = new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: {
"Cache-Control": "max-age=900",
"Content-Type": response.headers.get("Content-Type"),
}
});
await apiCache.put(request, response.clone());
}
return response;
}
Thanks in advance for any help, I've asked the same question on the Cloudflare community first and not received an answer in 2 weeks
This might be related to your use of caches.default, instead of opening a private cache with caches.open("whatever"). When you use caches.default, you are sharing the same cache that fetch() itself uses. So when your worker runs, your worker checks the cache, then fetch() checks the cache, then fetch() later writes the cache, and then your worker also writes the same cache entry. Since the write operations in particular happen asynchronously (as the response streams through), it's quite possible that they are overlapping and the cache is getting confused and tossing them all out.
To avoid this, you should open a private cache namespace. So, replace this line:
let cache = caches.default;
with:
let cache = await caches.open("whatever");
(This await always completes immediately; it's only needed because the Cache API standard insists that this method is asynchronous.)
This way, you are reading and writing a completely separate cache entry from the one that fetch() itself reads/writes.
The use case for caches.default is when you intentionally want to operate on exactly the cache entry that fetch() would also use, but I don't think you need to do that here.
EDIT: Based on conversation below, I now suspect that the presence of the Authorization header was causing the cache to refuse to store the response. But, using a custom cache namespace (as described above) means that you can safely cache the value using a Request that doesn't have that header, because you know the cached response can only be accessed by the Worker via the cache API. It sounds like this approach worked in your case.

There was an error in evaluating the Pre-request Script

I'm trying to access the response of my POST request in Postman via Post Request Script.
I added this 2 lines, under Pre-request Script
let response = pm.response.json();
console.log('JSON Response: ',response );
Then, I opened up my Postman console, before hit Send to make my POST request
I kept getting
There was an error in evaluating the Pre-request Script: TypeError: Cannot read property 'json' of undefined
Do I need to enable anything on Postman?
Pre-request scripts are ran before the request is sent. You do not have a response yet.
Try putting your script under the Tests tab, which is ran after a response is received.
In my case, there was a script that was screwing up my request. If you get the postman collection from someone else, check this and try to fix it. (in my case I don't need it so I deleted it)
You can try setting an environment variable, get it and parse it, I was created a POST requests to make a login and get a token to each request.
const echoPostRequest = {
url: pm.environment.get("url_login"),
method: 'POST',
header: 'Content-Type: application/json',
body: {
mode: 'raw',
raw: JSON.stringify({ email: pm.environment.get("user"),password: pm.environment.get("password") })
}
};
pm.sendRequest(echoPostRequest, function (err, res) {
console.log(err ? err : res.json());
pm.environment.set("login_response", res.json());
pm.environment.set("bearer_token", pm.environment.get("login_response").bearer_token);
});
was helping a friend and he had tried to make an adjustment to all requests in the collection.
I found in the documentation, how to remove
https://learning.postman.com/docs/writing-scripts/pre-request-scripts/
Please Make Sure That You Cleared Text Area Of PRE-REQUEST & TESTS TAB
By Clearing Text I Solved This Issue
Check if you SSL was turn off. If isn't, turn off.
Settings >> General >> SSL Certificate Verification

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.

SailsJS, Socket IO 101 (Switching Protocols) pending forever

I have been working on an application using SailsJS. Everything has been working fine until a couple of hours ago when I wasn't getting responses from socket.get(). I checked the network tab in chrome console and found that the last request is still pending.
Uri for request:
ws://localhost:1337/socket.io/1/websocket/FBcw-Q4H3PLFXcIlb0GB
Status code:
101 Switching Protocols
I have searched around and some people have been saying it is due to firewalls. So I disabled them but this didn't help. Some others have suggested defaulting to xhr polling so I did that but the same thing happens, a request to
http://localhost:1337/socket.io/1/xhr-polling/4_gAWYQJtKdXhDFEcxHe?t=1395536371612
just stays pending forever.
In response to the comment here is the request event:
socket.get('/session/create', {
username: username,
password: password
}, function (response) {
console.log(response) // null
});
The response is never returned and is always null in the callback. I even tried sending a response straight away and that isn't returned either. Example below:
// Session controller
module.exports = {
create: function (req, res) {
return res.json({foo: 'bar'}, 200);
}
}
Sorry, I have done some fiddling and I have found the issue (probably a silly mistake on my part).
I have shortcut urls enabled which in SailsJS means a request to /foo/bar will map to the FooController.bar
This worked fine until I added a wildcard route like the below example:
get /:foo/:bar
This is what seems to have broken the request. Since I was sending a request to /session/create and relied on shortcut routes without specifying an explicit route it was interpreted by the :foo/:bar route.
Lesson learned: Disable shortcut URLs and use proper routing.

MooTools Request Failing

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.

Categories