Android Browser does not handle cross domain ajax request properly - browser

I wrote HTML/JS application which works offline - it's put on SD card and is run using default 4.1 Android Browser.
I'm making the Ajax request using jQuery to host in the internet. Since i'm running it from local filesystem it's obviously a cross domain request. The server has a mechanism based on header manipulation which enables such CD requests. Piece of troubling code:
$.ajax({
type: "POST",
crossDomain: true,
data : formData,
cache: false,
url: "http://someurlwhichhandlescrossdomain.com",
success: function(data){
alert("hurrayy!");
},
error: function(xhr, ajaxOptions, thrownError) {
alert("bah :/");
alert(xhr.status);
alert(thrownError);
}
});
The problem is that the error function is always executed, although data is being sent correctly and the server registered the request properly. The xhr.status is always 0, and thrownError is empty.
The same piece of code works correctly on Chrome on Desktop (alerts "hurray").
Currently i use a workaround based on navigator.onLine, and if the value is true i assume that data has been sent correctly to the server (as i don't need to read anything from server). However this solution is bad because if the connection is working, but the server is not, i can't handle it.
Any ideas?
Thanks,
Karol

Related

Why is my XMLHttpRequest POST not always making it to the server?

I'm making an XMLHttpRequest, posting a string to a nodejs server upon certain user events in the browser, but not every event seems to make it to the server.
Here is basically the function I'm calling for each browser event:
function xhr_event(timeStamp){
xhr=new XMLHttpRequest()
xhr.open("POST",'/record_event');
console.log(timeStamp.toString())
xhr.send(timeStamp.toString())
}
where timeStamp=event.timeStamp
On the client side, each event logs to console. On the server side, not all events appear to POST. To the best I can tell, lost events are random.
I read about browser caching but I don't think that can be the problem, since each payload has a unique time stamp? Then again I'm not doing any encoding or setting of headers, so maybe that's the issue?
As #mottek mentioned and explained in the comments, adding a var (or let or const) before xhr solved the problem.
I didn't realize xhr=new XMLHTTPRequest() creates a global variable.
I also got the post to work consistently by using fetch:
fetch('/record_event', {
method: 'post',
headers: {
'Content-Type':'text/plain'
}
body: timeStamp.toString()
}

Requests with status 400 (Bad request) doesn't pipe the correct body

request 2.83.0
node 8.11
yarn 1.5.1
Operating System: Windows Server 2012 R2
We're using request to power our proxy. It works well for all requests, and we're even transferring big files (400MB), all methods work and etc.
We create our options object like this:
let options = {
method: req.method,
url: url,
headers: proxyHelper.getHeaders(req.headers)
};
// The auth header needed to make the request
options.headers['Authorization'] = `Bearer ${token}`;
And then send it to request.
request(options, (err, responseFromApi, body) => {
logger.log("Body from API")
logger.log(body)
}).pipe(res);
The problem happens on requests that return "Bad Request" in the body, (status code 400).
The logger loggs the correct body, but pipes the wrong body to the client. The client only receives
"Bad Request". Instead of a complete JSON object that contains the reason for the error.
We use iisnode (a plugin for IIS) to run Node. It works locally when we run iisnode, but when we deploy it, it doesn't work.
Any ideas? Is it request? Is it pipe? Is it iisnode?
After a lot of struggling and research and breaking down the the whole node app, it was in the end IIS that took the body and and replaced its content with the statusText...

Sending POST from node.js - how does a website identify me?

there is a website that works with virtual items for an online game. I made a chrome extension that automates some actions on that website. Since I'd like to make this run on my raspberryPi (and chromium with the extension seems to be too slow and unefficient) I am trying to move this into node.js.
The login for the website works with Steam OpenID. It allows you to select items from a list, click a few buttons, then it sends you a tradeoffer on steam.
My extension works with the website while I was logged in there. It receives their database with jQuery getJSON, loops through the array, pushes some values into an array and then sends a post request telling the website which items I want and which items I am offering.
Here is how I am sending the request from chrome:
function withdrawXHR(botId, playerItems, botItems) {
$.ajax({
url: websiteURL,
type: 'post',
data: {
"steamid": botId,
"peopleItems": playerItems,
"botItems": botItems
},
success: function (data) {
console.error('>> Done: ' + data)
console.log("")
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.error('>> Error: ' + errorThrown)
console.log("")
}
});
}
I can do everything in node so far like receiving their database, working through it, filter out the values I need, but I can't manage to send a working request. The problem is probably the login / how the website knows who I am.
I used wrapAPI (a chrome extension) to catch the request that is being sent when manually working with the website. Here is what it looks like:
So these are the things I am wondering about:
How would I send this request from node?
How does the website know who I am? They obviously know, because they are sending me an offer, but I can't see any "personal" data in that request.
Would I need to log into Steam OpenId from Node in some way? Is that possible?
What is a CF-RAY? (See the end of the captured request).
I am quite new to JS and requests in general and even "newer" to Node.js. I don't fully understand how the background of sending requests works. I would just need some tips, ideas on how to achieve my goal here.
Any help is greatly appreciated! Thank you! :)
You cannot use XMLHttpRequest for resources across domains. ( incidentally, unless you are using an extension)
I would look into grabbing express.js, and something called CORS. CORS permits cross-domain requests.
Here: http://enable-cors.org/server_expressjs.html
And here is some information on XHR requests in browser extensions: https://developer.chrome.com/extensions

node.js, express and different ports

I've been playing with node.js and then came across the express framework. I can't seem to get it to work when different ports are being used.
I have my ajax on http://localhost:8888 which is a MAMP server I'm running on my Mac.
$.ajax({
url: "http://localhost:1337/",
type: "GET",
dataType: "json",
data: { },
contentType: "application/json",
cache: false,
timeout: 5000,
success: function(data) {
alert(data);
},
error: function(jqXHR, textStatus, errorThrown) {
alert('error ' + textStatus + " " + errorThrown);
}
});
As you can see my node.js server is running on http://localhost:1337/. As a result nothing is getting returned and it's throwing an error.
Is there a way around this?
Thanks
Ben
The problem you have is that you are trying to make a cross-origin request and that's not allowed by browsers (yes, the same hostname with a different port counts as a different origin for this purpose). You have three options here:
1. Proxy the request.
Do this one if you can. Write some code that runs on the :8888 server
that proxies requests to the 1337 one. You can also do this by
sticking a proxy in front of both of them, something like Nginx is
pretty good at this and easy to set up
2. Use CORS (Cross Origin Resource Sharing)
See: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing and https://developer.mozilla.org/en/http_access_control
This means adding some headers to your responses to tell the browser that cross-origin requests are ok here. In your Express server add middleware like this:
function enableCORSMiddleware (req,res,next) {
// You could use * instead of the url below to allow any origin,
// but be careful, you're opening yourself up to all sorts of things!
res.setHeader('Access-Control-Allow-Origin', "http://localhost:8888");
next()
}
server.use(enableCORSMiddleware);
3. Use JSONP
This is a trick where you encode your "AJAX" response as Javascript code. Then you ask the browser to load that code, the browser will happily load scripts cross-origin so this gets round the cross-origin issue. It also lets anyone else get round it as well though, so be sure that's what you want!
On the server side you need wrap your response in a Javascript function call, express can do this for automatically if you enable the "jsonp callback" option like this:
server.enable("jsonp callback");
Then send your response using the "json()" method of response:
server.get("/ajax", function(req, res) {
res.json({foo: "bar"});
});
On the client side you can enanble JSONP in jQuery just by changing "json" to "jsonp" in the dataType option:
dataType: "jsonp",

Addressing relative paths within Google Chrome extension

in my Google Chrome extension I'm trying to do an AJAX request using jQuery. This is the code I use:
//send data to the server
$.ajax({
type: "PUT",
url: "/addTransaction",
data: receivedData,
success: function(data){
console.log(data);
}
});
The problem I have is that Chrome tries to access to something like this chrome-extension://jeelhjnbimpcilllldencicbafjdgdon/addTransaction which gives of course an error. I don't want to put absolute paths because it resets the sessions in the server (node.js).
Any clue on how I can solve this? Thanks.

Resources