Calling Express by hand - node.js

In a node.js/express/socket.io application, how does one "call" express by hand to load/render the home page without saying app.use(blah). In other words, if I wanted to tell express to load index.html by hand instead of automatically.
var express = require('express'),
app = express(),
...
//app.use magically loads index.html when the browser hits 8080
app.use(express.static(path.join(__dirname, '../client/www'))); //index.html is in www
var port = process.env.PORT || 8080; //select your port or let it pull from your .env file
//===============PORT=================
http.listen(port, function () {
console.log('listening on: ' + port);
}
Where index.html is in www ? This doesn't work:
app.get('/', function(req, res){
res.sendfile('index.html', { root: __dirname + "/relative_path_of_file" } );
});
Nor this:
app.get('/', function(req, res){
res.render('/home/idf/Documents/js/react-trader/client/www/index.html', {user: req.user});
});

I was able to resolve the problem that is the cause of this question. I am using Passport to authenticate Express. I needed to protect the home page (index.html), so I added a route and ensured that the user had to be authenticated to view that page. So I said:
app.get('/index.html', ensureAuthenticated, function(req, res){
...
}
The problem is that if I do this, when the user authenticates, I couldn't figure out how to pass control to Express. I either could authenticate (and prevent accessing the home page) through Passport routing, or I could do Express. But I couldn't do both.
It turns out the answer is really simple (or at least in my very limited understanding at this point) I got to work by simply rewriting to
app.get('/index.html', ensureAuthenticated, function(req, res, next){
return next();
}
In essence, the way to break out of Passport routes and pass control to Express [or "call it by hand" - hence my question] is to return next();
This is not obvious at all, and it took quite a bit of experimentation to get it to work.

Related

Capture all http requests with node/express

I am looking to capture all of the data from any request (images, fonts, css, js, etc) on my website so that I can capture the file details, specifically the file name and file size. I have found almost an identical question/solution:
Node.js : How to do something on all HTTP requests in Express?
But the solution appears to be deprecated with Express v4. Is there a simple solution to do this? As another approach I have tried the below solution with no luck:
var express = require("express");
var path = require("path");
var port = process.env.PORT || 3000;
var app = express();
var publicPath = path.resolve(__dirname, "public");
app.use(express.static(publicPath));
app.get("/", function(req, res){
// I want to listen to all requests coming from index.html
res.send("index.html");
});
app.all("*", function(){
// can't get requests
})
app.listen(port, function(){
console.log(`server listening on port ${port}`);
});
Also I am not looking to do this from Fiddler/Charles because I am looking to display this data on my site.
Express routes are predicated on order. Notice the answer that you linked in your question has the middleware defined, and used before all other routes.
Secondly you're trying to implement something that requires middleware, not a wildcard route. The pattern in link you provided in your question is not deprecated according to their docs.
app.use(function (req, res, next) {
// do something with the request
req.foo = 'testing'
next(); // MUST call this or the routes will not be hit
});
app.get('/', function(req, res){
if (req.foo === 'testing') {
console.log('works');
}
res.send("index.html");
});

Need to understand why expressjs is redirecting to index.html

I have the following server file, using express:
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
app.listen(port);
console.log('Listening on port: ' + port);
// get an instance of router
var router = express.Router();
app.use('/', router);
app.use(express.static(__dirname + "/"));
// route middle-ware that will happen on every request
router.use(function(req, res, next) {
// log each request to the console
console.log(req.method, req.url + " logging all requests");
// continue doing what we were doing and go to the route
next();
});
// home page route for port 8080, gets executed when entering localhost:8080
// and redirects to index.html (correctly and as expected)
router.get('/', function(req, res) {
console.log("routing from route")
res.redirect('index.html');
});
// This gets executed when my url is: http://localhost:8080/test
// and redirects to index.html (the questions is why!? I thought
// all the requests to root route would be caught by the router instance
app.get('*', function(req, res){
console.log('redirecting to index.html');
res.redirect('/index.html');
});
Looking at the code above and my comments, I cannot understand why
app.get('*', function(){...})
does not get executed when URL is
localhost:8080/index.html but gets executed when URL is localhost:8080/test
Even though, this is the behavior that I was hoping for, I'm not sure why this works?
I don't have a "test.html" page in the root.
One other thing, the index.html does load other scripts, so I expected
app.get('*', function(){...})
to get executed for such get requests too, as it is supposed to be the catch all, but it does not.
Does app.use('/', router) mean that any route that has single character "/" should be handled by Router instance (as long as not a static file)? so "http:localhost:8080" gets interpreted as "http://localhost:8080/"?
I would appreciate any explanation.
This line-
app.use(express.static(__dirname + "/"));
will run first. It will see that index.html exists and serve that file statically.

Express wildcard rule

I am hosting a single page app with Node and Express. I use the static middleware for the client. I am using path URLs to navigate the app, for example domain.com/profile/134. I am using history.pushState to change pages internally on the client, and this works fine. What I am missing is a wildcard rule on the server to catch all possible paths when the user accesses my page directly to a path that is not root. If I try to access domain.com/profile/134 directly I get this: "Cannot GET /profile/134". I have tried to insert a wildcard get at the end of server.js, but it seems to be hit every time, also when I access the page root. This is my relevant code:
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/../client'));
app.get('/*', function(req, res) {
console.log('wildcard');
});
Is this the correct GET wildcard rule to achieve what I need, and how can I serve the static client inside this handler? My client side will find the right page afterwards as long as the initial path is preserved. I basically want this wildcard rule to behave the same as the static rule, but keep the initial path.
You can use a hack
app.get('/:url', function(req, res) {
console.log('wildcard');
});
or try this one
app.get('/(.*)', function(req, res) {
console.log('wildcard');
});
[edited]: this should work as you expect:
var express = require('express');
var app = express();
app.get(/(.*)/, function(req, res) {
console.log("req.path", req.path);
res.send('success');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
I ended up using an npm module named express-history-fallback-api to solve this. Out of the box it solved both simple and advanced paths, like domain.com/settings and domain.com/profile/username
https://www.npmjs.com/package/express-history-api-fallback

Express and URL rewriting | HTML5 history

I'm trying to build a simple server to serve a single HTML page where all the logics are
handled by Angular. As far as I'm using the HTML5 history mode I'm able to navigate
through standard URLs.
Now, to make this work I need to enable URL rewriting. I tried with this bunch of lines and
although return always the correct HTML page, the URL vary and does not keep the initial
value. For example /popular should load index.html and leave the URL /popular so that the
JS logic can load the desired page.
Here follows the express code.
var express = require("express");
var app = express();
app.configure(function(){
app.use(express.static(__dirname + '/dist'));
});
app.get("/*", function(req, res, next){
res.sendfile(__dirname + '/dist/index.html');
});
app.listen(3000);
Any suggestion is appreciated.
Thanks everyone.
You need to set the root directory for relative filenames.
app.all('/*', function(req, res) {
res.sendfile('index.html', { root: __dirname+'/dist' });
});

Is it possible to set a base URL for NodeJS app?

I want to be able to host multiple NodeJS apps under the same domain, without using sub-domains (like google.com/reader instead of images.google.com). The problem is that I'm always typing the first part of the url e.g. "/reader" in Express/NodeJS.
How can I set up an Express app so that the base URL is something.com/myapp?
So instead of:
app.get("/myapp", function (req, res) {
// can be accessed from something.com/myapp
});
I can do:
// Some set-up
app.base = "/myapp"
app.get("/", function (req, res) {
// can still be accessed from something.com/myapp
});
I'd also like to configure Connect's staticProvider to behave the same way (right now it defaults to serving static files to something.com/js or something.com/css instead of something.com/myapp/js)
The express router can handle this since 4.0
http://expressjs.com/en/api.html#router
http://bulkan-evcimen.com/using_express_router_instead_of_express_namespace.html
var express = require('express');
var app = express();
var router = express.Router();
// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function(req, res, next) {
console.log('%s %s %s', req.method, req.url, req.path);
next();
});
// this will only be invoked if the path ends in /bar
router.use('/bar', function(req, res, next) {
// ... maybe some additional /bar logging ...
next();
});
// always invoked
router.use(function(req, res, next) {
res.send('Hello World');
});
app.use('/foo', router);
app.listen(3000);
Previous answer (before express 4.0) :
The express-namespace module (dead now) used to do the trick :
https://github.com/visionmedia/express-namespace
require('express-namespace');
app.namespace('/myapp', function() {
app.get('/', function (req, res) {
// can be accessed from something.com/myapp
});
});
At the moment this is not supported, and it's not easy to add it on your own.
The whole routing stuff is buried deep inside the server code, and as a bonus there's no exposure of the routes them selfs.
I dug through the source and also checked out the latest version of Express and the Connect middleware, but there's still no support for such functionality, you should open a issue either on Connect or Express itself.
Meanwhile...
Patch the thing yourself, here's a quick and easy way with only one line of code changed.
In ~/.local/lib/node/.npm/express/1.0.0/package/lib/express/servers.js, search for:
// Generate the route
this.routes[method](path, fn);
This should be around line 357, replace that with:
// Generate the route
this.routes[method](((self.settings.base || '') + path), fn);
Now just add the setting:
app.set('base', '/myapp');
This works fine with paths that are plain strings, for RegEx support you will have to hack around in the router middleware yourself, better file an issue in that case.
As far as the static provider goes, just add in /mypapp when setting it up.
Update
Made it work with RegExp too:
// replace
this.routes[method](baseRoute(self.settings.base || '', path), fn);
// helper
function baseRoute(base, path) {
if (path instanceof RegExp) {
var exp = RegExp(path).toString().slice(1, -1);
return new RegExp(exp[0] === '^' ? '^' + base + exp.substring(1) : base + exp);
} else {
return (base || '') + path;
}
}
I only tested this with a handful of expressions, so this isn't 100% tested but in theory it should work.
Update 2
Filed an issue with the patch:
https://github.com/visionmedia/express/issues/issue/478
Just to update the thread, now with Express.js v4 you can do it without using express-namespace:
var express = require('express'),
forumRouter = express.Router(),
threadRouter = express.Router(),
app = express();
forumRouter.get('/:id)', function(req, res){
res.send('GET forum ' + req.params.id);
});
forumRouter.get('/:id/edit', function(req, res){
res.send('GET forum ' + req.params.id + ' edit page');
});
forumRouter.delete('/:id', function(req, res){
res.send('DELETE forum ' + req.params.id);
});
app.use('/forum', forumRouter);
threadRouter.get('/:id/thread/:tid', function(req, res){
res.send('GET forum ' + req.params.id + ' thread ' + req.params.tid);
});
forumRouter.use('/', threadRouter);
app.listen(app.get("port") || 3000);
Cheers!
I was able to achieve this using a combination of express-namespace for the routes and a fix from the below google group discussion for the static assets. This snippet will treat a request to /foo/javascripts/jquery.js like a request to /javascripts/jquery.js:
app.use('/foo', express.static(__dirname + '/public'));
Source:
https://groups.google.com/forum/#!msg/express-js/xlP6_DX6he0/6OTY4hwfV-0J
I know this is a very old question but Express has changed a lot since most these answers were posted so I thought I'd share my approach.
You can, of course, use Routers with Express 4 to group together related functionality behind a particular path. This is well documented and has already been covered by other answers.
However, it is also possible to mount an entire application at a particular path. As an example, let's assume our application (the one we want to host at /myapp) looks like this, in a file called myapp.js:
var express = require('express'),
path = require('path'),
app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.get('/hello', function(req, res) {
res.send('Hello');
});
// Lots of other stuff here
exports.app = app;
In our main js file we could then mount this whole application at the path /myapp:
var express = require('express'),
app = express(),
myApp = require('./myapp').app;
app.use('/myapp', myApp);
app.listen(3000);
Note that we've created two applications here, one mounted on the other. The main application could have further sub-apps mounted at different paths as required.
The code in myapp.js is completely independent of where it was mounted. It's similar to the structure used by the express-generator in that regard.
Some documentation about sub-apps can be found here:
https://expressjs.com/en/4x/api.html#app.mountpath
https://expressjs.com/en/4x/api.html#app.onmount
There are also reliability issues. If reliability is important, a common solution is to use a front-end reverse HTTP proxy such as nginx or HAProxy. They both use single-thread evented architecture and are thus very scalable.
Then you can have different node processes for different subsites, and if one site fails (uncaught exception, memory leak, programmer error, whatever) the rest of sub-sites continue to work.
I was looking for this feature but for API routes, not for static files. What I did was that when I initialized the router, I added the mount path. So my configuration looks like this
//Default configuration
app.configure(function(){
app.use(express.compress());
app.use(express.logger('dev'));
app.set('json spaces',0);
app.use(express.limit('2mb'));
app.use(express.bodyParser());
app.use('/api', app.router); // <---
app.use(function(err, req, res, callback){
res.json(err.code, {});
});
});
Notice the '/api' when calling the router

Resources