I have an HTML file (privacy.html) and I want to serve it as home. I wrote the following:
app.get('/', (req, res) => {
res.writeHead(200, {'Content-Type': 'text/html'})
res.write(require('./privacy.html'))
res.end()
})
What is wrong?
This may be what you are looking for:
app.get('/', function(req, res){
res.sendFile(__dirname + '/privacy.html');
});
You don't use require to include html. Take a look at express's res.sendFile and express.static. It looks like you probably want the latter, but the former is the more flexible one if you're sure you want the structure you have.
Here's a little more information about require and the module system.
Edit: I urge you to read the links I provided, but I'll give you some code to use anyway so you don't end up using bad techniques.
The full implementation is super-simple:
// Somewhere above, probably where you `require()` express and friends.
const path = require('path')
// Later on. app could also be router, etc., if you ever get that far
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'privacy.html'))
})
// If you think it's still readable, you should be able rewrite this as follows.
app.get('/', (req, res) => res.sendFile(path.join(__dirname, 'privacy.html')))
There are ways to make this fancier (bindings, etc.), but none of them are worth doing when this works fine as-is. This will work everywhere that express does, including on systems where the path delimiter/file system hierarchy is different.
app.get('/', function(req, res){
res.sendFile(__dirname + 'privacy.html');
});
Here is a good example: https://codeforgeek.com/2015/01/render-html-file-expressjs/
Related
Apologies for this question which may be seen as basic but I feel there must be an easy method for this for such a popular framework yet I am struggling to come across it.
I am wanting to serve page routes using a relative path.
i.e. sendFile("/pages/index.html")
but the only solution that works is using sendFile(__dirname + "/pages/index.html")
I have read posts which say to add app.use(express.static("public")) to serve static content but this only impacts get requests to the full URL from client not the sendFile() from server.
i.e. If client types http://...../pages/index.html it correctly returns but when they type http://...../ and I use sendFile("/pages/index.html") the route is incorrect.
Relevant chunks of code are below
const express = require('express');
const app = express();
app.use(express.urlencoded({extended: false}))
app.use(express.static("public"))
app.get("/", (req, res) => {
res.status(200);
res.sendFile("/pages/index.html")
});
Directory structure is public, public/css, public/js, public/pages.
Again all I'm trying to do is not have to write __dirname in every sendFile().
I feel like I'm missing something. Any suggestions are appreciated :) Thanks
As #Yasio linked https://stackoverflow.com/a/52031283/9488284 (Thank You).
The solution is to create a middleware function that prepends __dirname to every sendFile and then use that function instead of sendFile.
Like such
app.use((req, res, next) => {
res.show = (name) => {
res.sendFile(`/public/${name}`, {root: __dirname});
};
next();
});
You can then display pages (in my dir structure) using
app.get('/demo', (req, res) => {
res.show("pages/index.html");
});
i.e. when someone requests http://.../ you will return to them pages/index.html.
This essentially means instead of using sendFile() use show() to return files.
I tried to replace the / path with another callback:
app.get('/', (req, res) => res.send('Hello World!'))
app.get('/', (req, res) => res.send('404'))
But when I navigate to / path it still responds with Hello World! instead of 404, so that means that the callback was not replaced. So is there any way to do this?
Clarification:
What I actually want to do is to delete routes at runtime, but replacing callbacks with something that respond with say 404 would also do the trick.
It's not clear from your question, but it looks like you have both routes present in your code. If that is the case, then only the first one will be used.
If you are trying to set up some sort of dynamic routes (ie. replace the route handler completely after the application starts), I'm not sure that is possible in Express. According to this comment on deleting Express routes at runtime, it appears that the routes are optimized when the application is first initialized and there is no easy way to change them after that.
If you need a route to behave differently at runtime, the way to do it is in the route callback. For example:
app.get('/', (req, res) => {
// test something & respond accordingly
if (req.query.someValue === 'do this') {
return res.send('Hello world');
}
// otherwise, return a 404 error
return res.status(404).send('No way, man!');
});
According to the docs for express, the path parameter is optional for app.use, so to apply the middleware to any incoming request you can write:
app.use(function (req, res, next) {
res.send('ANY request');
next();
});
But for app.get the path parameter is apparently not optional, so to apply the middleware to any incoming GET request you have to write:
app.get('/', function (req, res, next) {
res.send('GET request');
next();
});
But I find that it doesn't complain if I do miss out the path:
app.get(function (req, res, next) {
res.send('GET request');
next();
});
So, are the above two definitions equivalent, or is the second one doing something different to the first one?
I'm also not sure of the difference between specifying / or * as the path:
app.get('*', function (req, res, next) {
res.send('GET request');
next();
});
So, in summary, is there any difference between app.get('/', fn) and app.get('*', fn) and app.get(fn)?
Somewhat confusingly, there are two methods called app.get:
https://expressjs.com/en/4x/api.html#app.get
One is the converse to app.set, the other is the one for handling GET requests. In practice JS only allows a single method, so internally Express checks how many arguments are passed to work out which one you meant:
https://github.com/expressjs/express/blob/351396f971280ab79faddcf9782ea50f4e88358d/lib/application.js#L474
So while using app.get(fn) might not complain, it won't actually work as a route because it'll be treating it as the other form of get.
The difference between app.get('*', ...) and app.get('/', ...) is that the * will match any path whereas / will only match the exact path / (and nothing more). This is different from app.use, where the path is treated like a 'starts with'.
You may find the answer I gave here helpful to understand how paths differ between get and use: Difference between app.use and app.get *in proxying*.
I am trying to make route dynamic like /review-{title}-{id}
, but causing error don't know why, Also if user enter the wrong params than how to handle that.
My client requirement is like above, I am not good in node and express please anyone suggested how to make routes like above.
Also if I needed to make route like this /review/:title/:id format than how can I make like that.
I am trying but it redirect me out to the 404 page,
Please find my existing code details inside,
server.js
this is working..
app.get('/review', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
but not this one..
app.get('/review-*-*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
Also not this one working
app.get('/review/*/*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
This is 404 page which call evrytime while accessing dynamic pages
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/404.html'));
});
Check out the syntax for routes in Express.
In most cases you're better off using route params, e.g.:
app.get('/review/:title/:id', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
Some more flexibility (but more opaque for most developers) would be to match on regex.
I think you can put a * in the middle of words (they give an example like '/abc*def', but I'm not sure how nicely that plays with the other things you're doing, and I don't think you can have multiple *'s in the pattern if you do that.)
I'm not sure if that's so important but I like clean code so here's my question :
I use node.js with express. I have declared routes that render views :
app.get("/", function(req, res){
return res.render("index.jade");
});
Can I remove the "return" keyword like this :
app.get("/", function(req, res){
res.render("index.jade");
});
I've found lots of examples with both syntax. Don't know which one to use.
Thanks.
In your case it doesn't matter at all. However using return is a common method when using conditionals. For example:
app.get("/", function(req, res){
if(req.whatever) {
// Using return here will cause any code after to not be run
return res.render("index.jade");
}
// Default action
res.render("default.jade");
});
If you're using or switching to ES6+, this can be shortened using arrow functions to:
app.get("/", (req, res) => res.render("index.jade"))
which adds an implicit return statement, whilst keeping the code clean.
The example in the correct answer above can also be rewritten as:
app.get("/", (req, res) => return req.whatever ? res.render("index.jade") : res.render("default.jade"))