I have the following Node Express routes...
get('/api/dogs')
get('/api/dogs/:id')
get('/api/dogs/breeds')
You can probably see the problem already. The routing gets confused when calling the 'breeds' route thinking I am trying to call the 'dogs/:id' route.
Is there a way to get around this? Or should I just create a unique route, something like 'api/dog-breeds'? I'd like to keep them all under the same resource because I am using the Express' modular 'router' object.
Related
I have an express application with the following routes:
// Get category by id
innerRouter.get('/:id', categoriesController.getById)
// Get all categories along with their subcategories
innerRouter.get('/withSubcategories', categoriesController.getAllWithSubcategories)
The problem is that express doesn't seem to distinguish between the two, for example with this request:
http://localhost:3000/api/categories/withSubcategories
Express will actually invoke categoriesController.getById and not categoriesController.getAllWithSubcategories.
I know i can create a single route and then check for req.params.id, but i want to believe that there's a more elegant way of doing this, is there?
Express is sensitive to the order with which you define routes, so moving /withSubcategories above /:id will solve the issue. However, you should probably move /:id to something like /category/:id since having a match-all in the root path is inadvisable.
I am looking at some code from someone else for learning purposes. The way they're mounting routes is vague to me.
app.use('/dist', express.static(path.join(CURRENT_WORKING_DIR, 'dist')))
// mount routes
app.use('/', userRoutes)
app.use('/', authRoutes)
app.use('/', postRoutes)
The confusing part for me is how they're using '/' and using app.use. I'm used to doing it with app.get() and on top of that you specify the route instead of putting '/' everywhere. How does this work? Is this better practice?
The repo I'm looking at is https://github.com/shamahoque/mern-social/tree/master/server
Writing routes directly can be confusing and difficult to manage if there are large number of routes. So according to MVC pattern, the application is divided into modules/logical blocks based on functionalities they perform. For example, a simple hospital management system can have authentication, billing, payroll , medical-stock , patients etc modules (imaginary). If you are building application using MVC pattern, the common practice is to write controller for each of the module. Express provides something called middleware also called as Router to attach these controllers to respective API routes (Imagine it as a sort of map that connects each route to respective controller).
Once you define routes for each of these modules through middleware, you use those routes with your application. These routes handle requests and send parameters to controller to process.
You can learn how to use Middleware and Routers here : https://www.tutorialspoint.com/expressjs/expressjs_routing.htm
Regarding quality of code, dividing the code into modules and using routers to connect them is less tedious for others to understand. It also provides a good view of the application and it becomes easier to add new modules / functionality.
You can read more about building production-ready express app here :
https://www.freecodecamp.org/news/how-to-write-a-production-ready-node-and-express-app-f214f0b17d8c/
I have an api.js file where I make a couple of XHR-equests. I was using it inside a script tag inside an .ejs file, but it was getting too crowded. So after I moved everything to the api.js I'm no longer able to access its data.
Every time I try to require it from my app.js my program crashes.[nodemon] app crashed - waiting for file changes before starting... I've tried putting it inside my public folder and some other places, but it never works.
Should I export the data from api.js like I would if it was a data schema? If so, how would I do that? (something like module.exports = mongoose.model("Data", dataSchema); ? I don't have any models in api.js, it's just a couple of requests)
The .ejs file that is supposed to make use of api.js has a route like this:
app.get('/home', function(req, res){
res.render('home', { moment: moment }); //home is an .ejs file
});
The { moment: moment } is from moment.js.,.if I'm supposed to export api.js, how could I use it in this route since I'm already using moment.js. I think I can't just do
res.render('home', { moment: moment }, {api: api});
The main problem might be the app crashing since without solving this issue I won't be able to solve anything else.
Any help is appreciated. Thanks!
I'm not sure how much of the process you understand, but your ejs file is a "template" --- you pass "variables" to it and "render" it, and then express sends the html file. After it renders it, the "variables" are no longer accessible unless they're passed into a <script> tag like you might be doing. (I'm not sure how you're using moment --- or maybe you only use moment to render something server side)
Instead of trying to pass api, your html file can use the script tag, which can refer to other files like
<script src='/js/api.js'></script>
But your server (through express.js) needs to serve this file.
That is the common option, and should work for you.
You generally don't "pass" a module or library to the template engine unless you need it to render something. But if you wanted to, you can also read the api.js file as a string and "inject" it into the script tag... (I don't usually see it done this way)
<script><%= api %></script>
I am starting work on an existing Node/Express/Mongoose project -- I am currently going through the code and trying to understand how it works. The Express routes are being generated dynamically, that is to say there are functions that set up the routes -- the http method, the path to resource, the Express app, etc are passed into those functions as parameters and the routes are constructed at runtime. There are many nested functions -- it's a complex project -- but it all ends up with the line
app[method](path, requireAuthentication, requireAdminAuthentication, validateRequestBody, done);
which sets up the route.
Is there any way to debug a route after it's been constructed? That is to say, if I wanted to put some debug() statements in the POST route for '/widgets', but that route doesn't exist anywhere in the code, and in fact doesn't exist at all until after the app starts, where do I put the statement?
Well, you can use the DevTools and can get into the Sources tab and then press CTRL+O and then if you start typing the file name (which contains your dynamic routes) you can find it listed over there, just open it and set the breakpoint(s) where ever it is required.
Hope this helps!
An Angular 2 app uses the following code to load an array of routes:
export const routing = RouterModule.forRoot(myRoutes);
Currently, the myRoutes array is defined in the Angular 2 app, and works perfectly. But this assumes that routes have been defined statically in the client app.
How can the myRoutes array be fed into RouterModule.forRoot(myRoutes) from a source that would allow users do define routes and content from a user interface in a separate administration app? This would involve feeding the user-defined routes through a backend server.
I figured out how to send a data argument into each Route object in the myRoutes array, so that the same component can be re-used for multiple routes by sending different config into the same component from each route. But how can the routes array be imported from an external data store in a backend server?
This link indicates that I am describing a feature request. However, There MUST be some way to have UI-based content management in Angular 2 without having to resort to third party tools. What is a minimalist approach to importing an array of routes into RouterModule.forRoot(myRoutes) from a backend server?
You could try using dynamic component loading. The docs for it are here: https://angular.io/guide/dynamic-component-loader
I have not tried it ... but it does not look like it does exactly what you want. It does not seem to provide a way to add dynamic routes. But it does allow adding dynamic components.
Also, as per the link you defined, this is an issue with the CLI and its dependence on Web pack and AOT. You may be able to achieve more of what you want using SystemJS as your module loader.