Express hanging in Chrome post AJAX delete - javascript

When issuing a same-origin AJAX delete via jQuery, subsequent calls to the server via the same client are hanging. I've excerpted the problem below. Please advise if something is malformed as this would seem like such a strange bug.
Using Express 3.5.1, jQuery 1.11.0, and Chrome 33.x.
To replicate:
Create directory with code below and install Express dependency
node main.js
Visit localhost:5000 in Chrome 33
Click on simulated deletion link
Wait for a moment, and refresh
In the Network region, Chrome will handle the DELETE request ok, but the subsequent server call will stay as "pending". I have tried both HTML and JSON dataTypes and responses.
main.js:
// Dependencies
var http = require('http'),
express = require('express');
// Basic app
var app = express();
// Logging (for debugging), and parsing dependencies
app.use(express.logger());
app.use(express.json());
app.use(express.urlencoded());
app.use(express.cookieParser());
app.use(express.methodOverride());
// Simple home page
app.get("/", function(req, res) {
var head = "<head><script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js'></script></head>",
body = "<a id='link' style='text-decoration:underline;cursor:pointer;'>Click here to simulate delete</a>, wait a second, then try refreshing.",
params = {
url : "/item/5",
type : "DELETE"
}
ajax = "<script>$(function() { $('#link').click(function() { $.ajax(" + JSON.stringify(params) + "); }); });</script>"
res.send("<html>" + head + "<body>" + body + ajax + "</body></html>");
});
// Simulated deletion
app.del("/item/:id", function(req, res) {
res.send(204);
});
// Make the server listen
var server = http.createServer(app).listen(5000);

This ended up being a non-node-related third-party plugin (I believe it was Sophos, but I may be mistaken). Once the plugin was disabled, everything worked fine.
You can see more information here: https://github.com/strongloop/express/issues/2069

Related

Node.js - Window.Location.Href Not Working

I am trying to build a Puppeteer app that can be uploaded to a web server and receive parameters via the URL, but I can't seem find a way to get the current URL from my browser using Node. Right now I have a default server.js file created by Visual Studio which I modified to include code for getting the URL, but when I run the file I get an object promise error for window.location.href.
Here is the codeL
'use strict';
var http = require('http');
var port = process.env.PORT || 1337;
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
var url = window.location.href;
res.end('Hello World\n' + url);
}).listen(port);
My goal is to be able to get the URL and then pass it to my Puppeteer script as a parameter when it is run. The above code should result in a url value of http://localhost:1337 which could then be modified to include any additional parameters by appending query strings.
Next I tried getting the URL outside of the createServer loop by appending the following:
var url = window.location.href;
document.write(url);
That causes the app to crash with no error message beyond failing to connect to the server.
This is my first Node.js application, so the concept of server side javascript is new to me.

Use Express server to control a nodejs application

I have a node.js application which I use to interact with a REST API provided by another server. I would like to expose a web interface (html + css + javascript) using express.js in order to control the first application.
How can I let the browser talk to the server and let it make node.js actions like using http from that machine or writing to its filesystem? I tried using XMLHttpRequest, but HTTP requests are sent by my local PC instead of from my server.
The only solution I found is using XMLHttpRequest in the javascript of my web interface to invoke some middleware functions on my server, but I had some problems: when I make POST requests, I cannot read data from server. I used FormData and its append method to make the "body" of the POST request, then used body-parser in express to read that body, but it turns out to be always empty. Also tried changing the 'Content-Type' of the header.
Any suggestions? Any better solution than mine (I think it is not efficient)?
As pointed by Jonas, using node server as proxy would be the right approach.
I'm providing sample code for both frontend as well as backend app. Hope this helps you.
Frontend App Code
<html>
<head>
<script type="text/javascript">
function sendData(data) {
if (!data) {
// lets define some dummy data for testing
data = { somekey: "somevalue", anotherkey: "anothervalues" };
}
var XHR = new XMLHttpRequest();
var FD = new FormData();
// Push our data into our FormData object
for (name in data) {
FD.append(name, data[name]);
}
// Define what happens on successful data submission
XHR.addEventListener("load", function(event) {
alert("Yeah! Data sent and response loaded.");
alert(event.target.responseText);
});
// Define what happens in case of error
XHR.addEventListener("error", function(event) {
alert("Oops! Something went wrong.");
});
// Set up our request
XHR.open("POST", "http://path/to/your/nodejs/server/app");
// Send our FormData object; HTTP headers are set automatically
XHR.send(FD);
}
</script>
</head>
<body>
<button onclick="sendData()">Send Test Request to the Server</button>
</body>
</html>
Backend App code
const http = require('http');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.get('/', (req, res) => res.send('Yeah! Server is UP! Post some data'));
app.post('/', (req, res) => {
// You'll see the posted data in req.body, simply for testing purpose return it back to the calling user
res.json(req.body || {});
});
const server = http.createServer(app);
server.listen(3000);
server.on('error', console.error);
server.on('listening', () => console.log('Listening on 3000'));
process.on('exit', (code) => console.warn('Server terminated with code=' + code));
Please note that for this backend app to run, you must have installed following npm packages: express, body-parser

Simple redirect in Express with static file

I am new to Node and Express.
I've got a static html page where the users posts his username via ajax to my server. Then I want to redirect him to another html file.
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(__dirname + "/public/arena.html"));
app.get('/',function(req,res){
res.sendFile(__dirname + "/public/index.html");
});
app.post('/login',function(req,res){
var username=req.body.username;
console.log("User name = "+username);
res.redirect(__dirname + "/public/arena.html");
});
var server = app.listen(3000);
I get the username and also the respond in the browser but the server does not redirect me to arena.html. I also don't get any errors.
Why are these "easy" things so difficult in Node?
Thank you guys so much for your help.
The problem in this case is that it looks like you had some test (debugging?) code inserted into your POST route that is stopping the redirect call from running.
Here's the modified (corrected) version of your program, which will redirect the user in the way you want:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(__dirname + "/public/arena.html"));
app.get('/', function(req, res) {
res.sendFile(__dirname + "/public/index.html");
});
app.get('/arena', function(req, res) {
res.sendFile(__dirname + "/public/arena.html");
});
app.post('/login', function(req, res) {
var username = req.body.username;
console.log("User name = " + username);
// Note how I'm redirecting the user to the /arena URL.
// When you issue a redirect, you MUST redirect the user
// to a webpage on your site. You can't redirect them to
// a file you have on your disk.
res.redirect("/arena");
});
app.listen(3000);
I had to do a couple of things to get this working:
Get rid of your call to res.end. Whenever you call res.end, it will END the request, so any code that happens AFTER that call in the route will not run.
I had to create a new route for /arena. This just renders the arena.html file that you've created. This is required if you want to 'redirect' the user to an arena page.
I had to update your redirect code to actually redirect the user to /arena (the new route I created in step 2), so that the user will then hit your /arena route, and finally get back the template you are trying to show them.
Your res.redirect function is never executed because you are returning from function right before that statement.
You pass a URL to res.redirect(). That URL should be a URL that you have an appropriate route for that will serve the desired file.
Instead you are doing:
res.redirect(__dirname + "/public/arena.html");
But, that isn't a URL at all. That's a path name on your local hard disk. res.redirect() sends a URL back to the browser and, if the browser is following redirects, it will then request that URL from scratch as a branch new request. So, you need to send a URL (not a path) and you need to send a URL that you have a route configured for that will serve the desired file.
It also looks like your express.static() statements might be incorrect. For us to help more specifically with those, we need to know where the static HTML files are on your hard drive relative to __dirname and we need to know exactly how you want the URLs for them to work. For example, do you want a request for /arena.html to serve __dirname + /public/arena.html? Is that what you are trying to do? Please explain that part so we can advise more specifically on your express.static() statements.
If that is the case, then you can change your redirect to:
res.redirect("/arena.html");

How to pass variable from express view to router.js file - Node JS

I collecting information on my view via javascript and an onclick event, however the only way I see to pass back as a response is the below.
window.open("/explorer/" + e.target.id , "_self" );
Then in the router file index.js file I use the follow to get that param and use it in my node code.
router.get('/explorer/:folder_name, function(req,res) {
var command = 'ls -lrt ' + req.params.folder_name;
exec(command);
}
});
This does work, but the problem is that the router file then tried to open a page that doesn't exist.
This is a simple process, but I can't seem to find a simple way to do this.
Any suggestions on how to pass a var from an express view eg.. index.hjs to router file eg.. index.js in node.js express?
It doesn't appear that you have returned a response from the request. Could it be trying to find a 404 or 500 page that's not found? If you send a response like below does it resolve the problem?
res.send({ status: 'success' });
Update:
Per your comment here is a contrived example on sending data from the client (view) to the express router:
$.post('/explorer', 'folder=' + e.target.id);
On the server you can set up a route handler like so to handle the request:
router.post('/explorer', function(req, res) {
var command = 'ls -lrt ' + req.body.folder;
exec(command);
});
This code has not been validated, so you may have to tinker with it.

Can not login via nodejs with https.get and auth parameter to page on another server

Hi I´m trying to figure out how to login to a website with node js.
Even if I get back a 200 OK , I'm NOT logged in to the page.
The loggin is normally via form on the page, but for complex functionality it should work via nodes.
Here is my actual code, is there something wrong with the code ?
var express = require('express'),
request = require("request"),
https = require('https'),
http = require('http');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.use(express.bodyParser());
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'jade');
app.use(app.router);
});
var auth = 'Basic ' + new Buffer("usernameString:passwordString");
var options = require('url').parse( "https://example.com/path" );
options.rejectUnauthorized =false;
options.host="example.com";
options.path="https://example.com/usr/login";
options.defaultEncoding = 'utf8';
options.headers= { 'content-type' : 'application/x-www-form-urlencoded',
"Proxy-Authorization": auth,
host: "example.com",'accept-encoding': '*'
};
options.agent = new https.Agent( options );
var req = https.get( options, function(res) {
console.log(res.statusCode); //200 but not logged in ?!?
});
UPDATE:
If I test the login with an AJAX request, everything works fine but I need NODE JS:
Here the JavaScript code with ajax:
$.ajax{(
type: get,
…
…
data: "LoginForm[username]=usernameString&LoginForm[password]=passwordString"
…)};
Any suggestions ?
In most cases authenticating service will return a cookie which you have to include in every following requests so that the remote service recognize you ...
As far as I know, proxy authentication works the same as basic authentication, in that a client is never really logged in (by means of a session being held by the server), but just sends the authentication headers along with every request.
So try sending the Proxy-Authorization header along for every request you make.
EDIT: okay so perhaps you don't need to use proxy authentication at all. I also noticed that your options.path is incorrect: it should only contain the path name, not a full URL.
Try this:
options.path = "/usr/login?LoginForm[username]=usernameString&LoginForm[password]=passwordString";

Categories