Why not universally route all requests using a one short function? - node.js

I've been learning Node JS + Express and pretty much 100% of the dozens of tutorials I've watched either route each specific browser request one-by-one in a main JS file, or they separate routes into separate files (again, one-by-one in their respective files) and link them all back to the index.js file.
I've been trying to understand why these methods in general would be better than just writing something simple like this which handles all get requests universally by going to the proper file in the directory based off what the url is (and can pull the index.html file from each automatically)? It seems like it would be a lot of never ending code for what could be replaced with:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+req.path+'/'));
});
Why are the methods I've seen used as opposed to the method I thought of?

Related

Is there any way to know how many bytes a client downloaded from a file on my server?

I'm looking for a way to get that information. I'm currently dealing with the problem of track how many seconds of an mp3 file were listened from the backend side. I've been working with the "Content-Range" header but it doesn't provide the information that I need (considering the accuracy of it). So, I started thinking in this other way to track this information, does anyone has experience with this?
Thanks!
I tried to intercept "Partial Content" requests with success, but doesn't provide the level of accuracy that I need. For doing this I have a small node express app that does this:
app.get('/episodes/:filename', (req, res, next) => {
console.log("HEADERS RANGE", req.headers.range);
// res.send(req.params)
next();
})
I have a folder called episodes on my project public folder, so, before the server returns the file I'm intercepting it to log requested range values.
Again, this is working fine, but I'm searching for a more accurate solution which I think it's related to the problem that I described initially.

NodeJs setting up production and development

I was learning NodeJs advance concepts after going through the basic course.
I am following stepehen grinder course where we would be using his folliwng repo
I was initially walking through the repo where somethings were sort of new to me
My main question evolves around his index.js file in repo
This isn't prime question but first he have done something like this
require('./routes/authRoutes')(app);
require('./routes/blogRoutes')(app);
Is this equivalent to something like this
const auth = require('./routes/auth.js')
const profile = require("./routes/profile.js")
app.use('/auth', auth)
app.use('/profile', profile)
Second, Primary question, In his index.js file he have done something like this
if (['production'].includes(process.env.NODE_ENV)) {
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve('client', 'build', 'index.html'));
});
}
This does not make sense to me at all, can someone explain me what does the above code do? and an interesting article which can help me comprehend.
Also, Can someone please tell me what does path module do? I went through their do documentation and was able to comprehend that path allows us to access files outside our node project. Is that correct understanding?
Concerning you first question:
It's not the same. app.use(...) defines a middleware that gets executed on all and every routes. Here, both routes files export a function which takes one argument: the application (ExpressJS server) instance.
So, require('./routes/blogRoutes') gives you a function app => {...}, and by adding parenthesis and the app variable as a parameter you immediately execute this function with the current server (application) instance. Which in the end will create all the routes defined in the route file.
Concerning your second question:
The if is testing if the NODE_ENV variable is equal to production. If it is in production mode, app.use(express.static('client/build')); tells ExpressJS to serve static files from the client/build folder.
The rest of the code app.get('*', ...) send the index.html file for calls made to any route except the one defined in the two routes files.
The path.resolve only role is to easily build the absolute path of the index.html file.

Register new route at runtime in NodeJs/ExpressJs

I want to extend this open topic: Add Routes at Runtime (ExpressJs) which sadly didn't help me enough.
I'm working on an application that allows the creation of different API's that runs on NodeJs. The UI looks like this:
As you can see, this piece of code contains two endpoints (GET, POST) and as soon as I press "Save", it creates a .js file located in a path where the Nodejs application is looking for its endpoints (e.g: myProject\dynamicRoutes\rule_test.js).
The problem that I have is that being that the Nodejs server is running while I'm developing the code, I'm not able to invoke these new endpoints unless I restart the server once again (and ExpressJs detects the file).
Is there a way to register new routes while the
NodeJs (ExpressJs) is running?
I tried to do the following things with no luck:
app.js
This works if the server is restarted. I tried to include this library (express-dynamic-router, but not working at runtime.)
//this is dynamic routing function
function handleDynamicRoutes(req,res,next) {
var path = req.path; //http://localhost:8080/api/rule_test
//LoadModules(path)
var controllerPath = path.replace("/api/", "./dynamicRoutes/");
var dynamicController = require(controllerPath);
dynamicRouter.index(dynamicController[req.method]).register(app);
dynamicController[req.method] = function(req, res) {
//invocation
}
next();
}
app.all('*', handleDynamicRoutes);
Finally, I readed this article (#NodeJS / #ExpressJS: Adding routes dynamically at runtime), but I couldn't figure out how this can help me.
I believe that this could be possible somehow, but I feel a bit lost. Anyone knows how can I achieve this? I'm getting a CANNOT GET error, after each file creation.
Disclaimer: please know that it is considered as bad design in terms of stability and security to allow the user or even administrator to inject executable code via web forms. Treat this thread as academic discussion and don't use this code in production!
Look at this simple example which adds new route in runtime:
app.get('/subpage', (req, res) => res.send('Hello subpage'))
So basically new route is being registered when app.get is called, no need to walk through routes directory.
All you need to do is simply load your newly created module and pass your app to module.exports function to register new routes. I guess this one-liner should work just fine (not tested):
require('path/to/new/module')(app)
Is req.params enough for you?
app.get('/basebath/:path, (req,res) => {
const content = require('content/' + req.params.path);
res.send(content);
});
So the user can enter whatever after /basepath, for example
http://www.mywebsite.com/basepath/bergur
The router would then try to get the file content/bergur.js
and send it's contents.

Express static serving wrong path

I am messing around with express.js and have built some basic functionality but am having issues with express static serving from the wrong place if the URL is longer than one directory from root. See the examples below.
I am using the normal documented approach to using static.
app.use(express.static(__dirname + '/public'));
And have set up a couple of routes. eg.
app.get('/signup', function(req, res) {
res.render('signup.ejs');
});
With a 404 catch at the end of the chain.
app.get('*', function(req, res){
res.status(404).render('404');
});
If I hit page such as localhost:3000 or localhost:3000/login which are defined routes, all is well. Even if I hit an undefined route of localhost:3000/foo, I get the 404 rendered correctly with all images present.
However if I go one further and do something like localhost:3000/login/foo all the images are missing and I will get an error in the browsers console with the following address.
http://localhost:3000/login/img/site-brand.png
This happens the same on routes defined with more than one directory too.
I interpreted the docs on the express website that regardless of what was calling for the static image it would be served from the public directory in root, which contains a js, img, and css directories.
My questions are, what have I misinterpreted? and how do I get express to always serve relative to root?
I wrote the whole question then realised that when I had set up the src="" tags in my .ejs files I had used relative paths, not absolute. Rather than delete the question I decided to answer it and post it for others.
So instead of using src="img/my-image.png" it should be src="/img/my-image.png" The leading slash indicates that the request is relative to root not the path that is making the request.
Basic web development stuff there. I should have seen it first time out but its late, and I am cramming my head full of new frameworks which is in turn squeezing the more trivial stuff out of my small brain.

How to create href links in a view, pointing to Express routes?

I want to create href links inside my views, but I do not want to point to a static address. I want to dynamically create href urls based on routes.
Example:
// app.js:
app.get('/test', function testPage(req, res, next) {
// do something here
});
// inside view.html:
<a href="path('testPage')" /> // something similar
<a href="/test" /> I do NOT want this!
Am I missing something, or there is no way to do that easily?
I've searched and I found that app._router.stack has all routes. But they are just a plain ARRAY so they don't have any kind of id or smth! What I came up with, is a function that parses all routes (from stack), gets their name, which is set only if the function has a name (http://expressjs.com/4x/api.html#req.route) and then create an object with key (route name) -> path.
Then I can use this function (somehow) inside views to create paths, right?
Any better ideas?
Coming from PHP frameworks background, I am used to two way routes. However, from what I've seen in tutorials, people just use the static links. I think it has to do with the nature of Node.js web applications. Lots of them are SPAs, so you just build an API and then refer to it statically from the frontend application.
When researching this topic, I've came accross this little library called 2-way router which can be used with Express. I haven't experimented with it yet, but it might be useful to you.
EDIT: Tried to re-word my search and I've found similar thread about url generation and express route naming.
EDIT: You can also implement django-like routing.

Resources