My express.js configuration looks like this:
//app.js:
var routes = require('./routes/index');
app.use(express.static(path.join(__dirname, '../client/build'), {'index': false}));
app.use('/', routes);
//routes/index.js:
router.get('/', function(req, res) {
console.log("im never called");
});
My handler is NEVER called (should be called when requesting without path or just '/'), the browser just gets a 303 with Location //, what is wrong here?
Thanks in advance for help!
Try to add module.exports = router; to the end of routes/index.js
Edit:
There is a common practice to put all your static files in one directory (maybe you have done it already) and make all requests to static files start with /public:
app.use('/public', express.static(path.join(__dirname, '../client/build'));
Doing this way
http://yoursite.com/public/some/file.js
will be served with
../client/build/some/file.js
Instead of /public you may choose a path that will not intersect with your router.
I was having this same issue this morning and I thought I would share my solution.
The express.static method is running on all of your requests... when it cannot find a match, it can either run the next() function and continue to your desired handler or redirect to a trailing slash to check if the request is for a directory.
I fixed it by adding 'redirect:false' as follows:
app.use(express.static(
path.join(__dirname, '../client/build'),
{index: false, redirect: false}));
Reference: express.static(root, [options])
Related
This is what I have in mind:
app.use(express.static(path.join(__dirname, 'public')));
app.get('/foo', (req, res) => {
// server the public folder again here
});
app.get('/bar/:id', (req, res) => {
// server the public folder again here
});
I'm trying to deploy a react app that uses routing. The problem is, I need to point all user-facing paths (so, /about, /contact, etc. but not /assets/images/icon.png) back to the homepage, because the react app uses react-router, and once the app is built for production and served as a static site, going to mysite.com/about gives a 404, where it wouldn't have before building.
So it turns out express.static("./path/to/site") can be the only argument to app.use(), or it can be the second argument.
Instead of using app.get(), I need to use app.use() for these other paths.
To capture all paths that weren't handled by default by the static site, I could have something like this:
app.use(express.static(path.join(__dirname, 'public')));
app.use('*', express.static(path.join(__dirname, 'public')));
To be more specific as in the question, I could have something like:
app.use(express.static(path.join(__dirname, 'public')));
app.use('/foo', express.static(path.join(__dirname, 'public')));
app.use('/bar/:id', express.static(path.join(__dirname, 'public')));
In that case, paths that aren't handled automatically by the static site and aren't listed afterwards will result in a 404.
Whenever I open my site (i.e. http://127.0.0.1:8090), a GET request to / is not made.
app.use(session({
//session stuff
}));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static('client'));
app.get('/', async function(req, res){
console.log(req);
}
module.exports = app;
app.listen(8090);
This is not being called and I am unsure why - what can I do to fix this? My other app.get() functions are called when the relevant pages are opened.
When you open your site (i.e. http://127.0.0.1:8090) it sends a GET request but doesn't send back to the browser any response. That is why it seems GET request wasn't made. Send a response in the app.get and it'll send a response.
app.get('/', async function(req, res){
console.log(req);
res.send('Hello World');
}
express.static('client') suggest from where your static files are to be loaded. Here 'client' is treated as your root path.
If your 'client' directory has some 'abcd.img' file then, http://127.0.0.1:8090/abcd.img will load 'abcd.img'. 'index.html' in your 'client' directory will be loaded by default when you point to root path. That means 'http://127.0.0.1:8090/' will load your index.html file.
Express has a very good documentation on this part. I am pasting it for your reference.
Express documentation for serving static files
I want to use static file serve without any rendering engine.
I've tried to use:
res.sendfile('public/index.html');
on the '/' GET route, and express middleware for static files on my route:
app.use(express.static(path.join(__dirname, 'public')));
BUT it seems like all of the javascripts which the client asks for are downloaded with index.html file information.
How can I make a successful download of the CSS/JS static files ?
UPDATE:
Here is the route for the "res.sendfile ..." :
app.get('/*', index);
I want all of the requests to the server on any route will get index.html and all of its JS&CSS assosiciated with.
I guess this might help you...
in app.js file...
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use("/styles", express.static(__dirname + '/public/stylesheets'));
app.use("/scripts", express.static(__dirname + '/public/javascripts'));
app.use("/images", express.static(__dirname + '/public/images'));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', function (req, res) {
res.sendfile(__dirname + '/public/home.html');
});
save the home.html inside the /public folder and JavaScript files in /public/javascripts, images in /public/images, css files in /public/stylesheets folder.
In the HTML file reference should be the words you define(eg: /scripts/home.js)... like this
<link rel="stylesheet" type="text/css" href="/styles/home.css" >
<script src="/scripts/home.js" type="text/javascript"></script>
var express=require("express");
var app=express();
app.use('/', express.static(__dirname + '/website/views/'));
app.set("views",__dirname+'/website/views');
app.get("/",function(req,res){
res.sendfile('index.html');
});
the codes above is mine.i wish to help you.
Why not something like this?
if(req.url == '/') { // Root lookups appear to be mapped to index.html
next();
} else {
fname = [disk location of your website] + req.url;
fs.open(fname, 'r', function(err, fd) {
if(err) {
next();
} else {
fs.close(fd);
res.sendfile(fname);
}
});
}
Well, the simplest solution will be to move app.use(express.static(path.join(__dirname, 'public')))
up before you call app.use(app.router);
This way, the static middleware gets served before the app.get('/*', index);
I've made an assumption here that your routes are declared in this order:
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
If this is indeed the case, then the following suggestion holds:
The problem here is the app.get('/*', …) will intercept all requests that match, which is basically everything. Your static middleware won't get a chance at serving files.
If you remove that route, things should work for you as index.html is already in the public directory and can be served by the static middleware.
For a good explanation of how this works, see the answer to this question: node.js / express.js - How does app.router work?
Update based on additions to the above question:
You've stated this as the current behavior of your server:
it seems like all of the javascripts which the client asks for are downloaded with index.html file information.
You have asked the question:
How can I make a successful download of the CSS/JS static files ?
with this requirement
I want all of the requests to the server on any route will get index.html and all of its JS&CSS assosiciated with.
Your question and requirement are opposed to each other. The server will send back to the client exactly what you tell/configure it to. It will either always send back index.html which is exactly what your requirement states, or it will successfully serve up both index.html and any CSS/Javascript it references which is what your original problem statement was.
In one of your comments below you've stated:
the reason I want to do it, is because I'm using templates, and index.html wraps each template. I'm using angular on the client, and I'm starting to realize that i'll have to use a render engine in order to achieve this. Again, my angular client defines the partial url, and when it sends the request to : '/partial/sample' I need the index.html to wrap the 'sample.html' for instance
My assumptions based on this statement (please correct if wrong)
You are using client side templates
The files you are retrieving from the server are static (i.e., they need to be served up as is from the server)
Your routes are currently declared in this order
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
You are not doing any server side templating (i.e. everything is located under public somewhere)
If these assumptions are correct, the fix is to do what I originally suggested and remove this route:
app.get('/*', index);
If you do this (assuming your resources are referenced correctly):
your index.html will be retrieved as is from the server via the static middleware.
Each css/js file you've referenced in index.html will be returned from the server via the static middleware
Any requests to load template files (such as sample.html) will be serviced by your static middeware and returned to the client without modification
I have this piece of code here:
var express = require('express')
, http = require('http')
var app = express();
var server = app.listen(1344);
var io = require('socket.io').listen(server);
app.use(express.static(__dirname + '/public'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({secret: 'secret'}));
app.get('/', function(req, res){
if(req.session){
console.log(req.session);
}
console.log('ok');
});
The code inside the app.get() callback is not being called. If I comment out the app.use(express.static(__dirname + '/public')) line, then the callaback works. I've tried changing the order, but its like a lottery! I would prefer to know whats going wrong here.
I'm sure this have to do with lack of knowledge from my part on how the middleware is called. Can someone help me understand this problem?
Basically I just want to perform some logic before the files are served and the index.html is load on the browser. By the way placing the app.get() before the app.use(express.static()) line, does not did the trick!
Your static file middleware should go first.
app.use(express.static(__dirname + '/public'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({secret: 'secret'}));
And you should be adding a use for app.router as well.
app.use(express.static(__dirname + '/public'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({secret: 'secret'}));
app.use(app.router);
Middleware is processed in order for each request. So if you have an index.html in your static files then requests for yourdomain.com/ will never make it to the app.router because they will get served by the static file handler. Delete index.html and then that request will flow through to your app.router.
Rename your index.html file to something else. It is that simple
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
if(req.session){
console.log(req.session);
}
console.log('ok');
res.sendfile(new_index_file);
});
I believe, you have 3 options here:
1) Mount your app.get('/') route (possibly, using app.router) before static middleware, so that they take precedence. Middleware that is mounted first, processes a matching request first.
2) Use a path prefix for your static paths like app.use('/static', express.static('public'));, so that statics is served from example.com/static/...
3) Want to act smart and shoot yourself in the leg? :) Sometimes people use Accept headers and content negotiation to serve 2 different content types from the same url in different circumstances. You can make your static middleware check for a specific content type in Accept header and process request, only if requests's Accept header wants a proper type. Otherwise, it will pass the processing down the stream to you / view. You can customise your static middleware content negotiation in req.accepts.
Before I ask about app.router I think I should explain at least what I think happens when working with middleware. To use middleware, the function to use is app.use(). When the middleware is being executed, it will either call the next middleware by using next() or make it so no more middleware get called. That means that the order in which I place my middleware calls is important, because some middleware depends on other middleware, and some middleware near the end might not even be called.
Today I was working on my application and had my server running in the background. I wanted to make some changes and refresh my page and see the changes immediately. Specifically, I was making changes to my layout. I couldn't get it to work so I searched Stack Overflow for the answer and found this question. It says to make sure that express.static() is beneath require('stylus'). But when I was looking at that OP's code, I saw that he had his app.router call at the very end of his middleware calls, and I tried to figure out why that was.
When I made my Express.js application (version 3.0.0rc4), I used the command express app --sessions --css stylus and in my app.js file the code came setup with my app.router above both the express.static() and require('stylus') calls. So it seems like, if it comes already setup that way, then it should stay that way.
After re-arranging my code so I could see my Stylus changes, it looks like this:
app.configure(function(){
//app.set() calls
//app.use() calls
//...
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(__dirname + '/public', {maxAge: 31557600000}));
});
app.get('/', routes.index);
app.get('/test', function(req, res){
res.send('Test');
});
So I decided that the first step would be to find out why it is important to even have app.router in my code. So I commented it out, started my app and navigated to /. It displayed my index page just fine. Hmm, maybe it worked because I was exporting the routing from my routes file (routes.index). So next I navigated to /test and it displayed Test on the screen. Haha, OK, I have no idea what app.router does. Whether it is included in my code or not, my routing is fine. So I am definitely missing something.
So Here Is My Question:
Could somebody please explain what app.router does, the importance of it, and where I should place it in my middleware calls? It would also be nice if I got a brief explanation about express.static(). As far as I can tell, express.static() is a cache of my information, and if the application can't find the requested page, it will check the cache to see if it exists.
Note: This describes how Express worked in versions 2 and 3. See the end of this post for information about Express 4.
static simply serves files (static resources) from disk. You give it a path (sometimes called the mount point), and it serves the files in that folder.
For example, express.static('/var/www') would serve the files in that folder. So a request to your Node server for http://server/file.html would serve /var/www/file.html.
router is code that runs your routes. When you do app.get('/user', function(req, res) { ... });, it is the router that actually invokes the callback function to process the request.
The order that you pass things to app.use determines the order in which each middleware is given the opportunity to process a request. For example, if you have a file called test.html in your static folder and a route:
app.get('/test.html', function(req, res) {
res.send('Hello from route handler');
});
Which one gets sent to a client requesting http://server/test.html? Whichever middleware is given to use first.
If you do this:
app.use(express.static(__dirname + '/public'));
app.use(app.router);
Then the file on disk is served.
If you do it the other way,
app.use(app.router);
app.use(express.static(__dirname + '/public'));
Then the route handler gets the request, and "Hello from route handler" gets sent to the browser.
Usually, you want to put the router above the static middleware so that a accidentally-named file can't override one of your routes.
Note that if you don't explicitly use the router, it is implicitly added by Express at the point you define a route (which is why your routes still worked even though you commented out app.use(app.router)).
A commenter has brought up another point about the order of static and router that I hadn't addressed: the impact on your app's overall performance.
Another reason to use router above static is to optimize performance. If you put static first, then you'll hit the hard drive on every single request to see whether or not a file exists. In a quick test, I found that this overhead amounted to ~1ms on an unloaded server. (That number is much likely to be higher under load, where requests will compete for disk access.)
With router first, a request matching a route never has to hit the disk, saving precious milliseconds.
Of course, there are ways to mitigate static's overhead.
The best option is to put all of your static resources under a specific folder. (IE /static) You can then mount static to that path so that it only runs when the path starts with /static:
app.use('/static', express.static(__dirname + '/static'));
In this situation, you'd put this above router. This avoids processing other middleware/the router if a file is present, but to be honest, I doubt you'll gain that much.
You could also use staticCache, which caches static resources in-memory so that you don't have to hit the disk for commonly requested files. (Warning: staticCache will apparently be removed in the future.)
However, I don't think staticCache caches negative answers (when a file does not exist), so it doesn't help if you've put staticCache above router without mounting it to a path.
As with all questions about performance, measure and benchmark your real-world app (under load) to see where the bottlenecks really are.
Express 4
Express 4.0 removes app.router. All middleware (app.use) and routes (app.get et al) are now processed in precisely the order in which they are added.
In other words:
All routing methods will be added in the order in which they appear. You should not do app.use(app.router). This eliminates the most common issue with Express.
In other words, mixing app.use() and app[VERB]() will work exactly in the order in which they are called.
app.get('/', home);
app.use('/public', require('st')(process.cwd()));
app.get('/users', users.list);
app.post('/users', users.create);
Read more about changes in Express 4.
Routing means determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on).
Each route can have one or more handler functions, which are executed when the route is matched.
In Express 4.0 Router, we are given more flexibility than ever before in defining our routes.
express.Router() is use multiple times to define groups of routes.
route used as middleware to process requests.
route used as middleware to validate parameters using ".param()".
app.route() used as a shortcut to the Router to define multiple requests on a route
when we are using app.route(), we are attaching our app with that router.
var express = require('express'); //used as middleware
var app = express(); //instance of express.
app.use(app.router);
app.use(express.static(__dirname + '/public')); //All Static like [css,js,images] files are coming from public folder
app.set('views',__dirname + '/views'); //To set Views
app.set('view engine', 'ejs'); //sets View-Engine as ejs
app.engine('html', require('ejs').renderFile); //actually rendering HTML files through EJS.
app.get('/', function (req, res) {
res.render('index');
})
app.get('/test', function (req, res) {
res.send('test')
})
In express Version 4 we can easily define routes in the following manner:
server.js:
const express = require('express');
const app = express();
const route = require('./route');
app.use('/route', route);
// here we pass in the imported route object
app.listen(3000, () => console.log('Example app listening on port 3000!'));
route.js:
const express = require('express');
const router = express.Router();
router.get('/specialRoute', function (req, res, next) {
// route is now http://localhost:3000/route/specialRoute
});
router.get('/', function (req, res, next) {
// route is now http://localhost:3000/route
});
module.exports = router;
In server.js we imported the router object of the route.js file and apply it in the following manner in server.js:
app.use('/route', route);
Now all of the routes in the route.js have the following base URL:
http://localhost:3000/route
Why this approach:
The main advantage of taking this approach is that now our app is more modular. All the route handlers for a certain route now can be put into different files which makes everything more maintainable and easier to find.
An article by #kelyvinn from 2016, with the intent to demonstrate modularity, includes this code:
// controllers/apis/dogs/index.js
const
express = require('express'),
dogService = require('../../../services/dogs');
let router = express.Router();
router.get('/', dogService.getDogs);
router.get('/:id', dogService.getDogWithId);
module.exports = router;