Is it possible a single API handles multiple requests in Node JS? - javascript

My goal is to create an API that handles multiple requests. By doing this, I need to pass a string as an argument to the url of API like this:
// index.js in client
fetch(`http://localhost:4000/routerName/${tableName}`).then()
// router.js
router.get(`/${tableName_from_client_page}`, (req, res) => { // Do Something })
A problem is, the browser can't connect to the targeted pages unless I create a whole new APIs for every matching tableNames.
I want my API handles multiple requests by receiving the tableName as its /url.
Are there some tricks to solve this problem?
This is how my whole router looks like:
// Router
const express = require('express'),
db = require('./db.js'),
router = express.Router();
router.get('/table', (req, res) => {
db.loadTable('SELECT * FROM someTable', res);
}) // Handles only one request on the name of url; /table
router.get(`/${tableName_from_client_page}`, (req, res) => {
db.loadTable(`SELECT * FROM ${tableName_from_client_page}`, res)
}) // Handles multiple requests, depending on its argument.
module.exports = router;

// Router
const express = require('express'),
db = require('./db.js'),
router = express.Router();
router.get('/table', (req, res) => {
db.loadTable('SELECT * FROM someTable', res);
}) // Handles only one request on the name of url; /table
router.get('/tables/:tableName', (req, res) => {
db.loadTable(`SELECT * FROM ${req.params.tableName}`, res)
}) // Handles multiple requests, depending on its argument.
module.exports = router;

// Router
const express = require('express'),
db = require('./db.js'),
router = express.Router();
This API will only handle one request "/table".
router.get('/table', (req, res) => {
db.loadTable('SELECT * FROM someTable', res);
})
To handle multiple requests checkout below code
but make sure to write this API last in the route file, If you write this API before the "/table" API then your "/table" request will also be handled by this API.
router.get('/:table_name', (req, res) => {
db.loadTable(`SELECT * FROM ${req.params.table_name}`, res)
})
module.exports = router;

Related

How to modularize a delete route with params in Express

I am trying to hit a delete route in my Express.js app, and it is not working for some reason.
There is some issue with the way that I am setting up my router files and the request params in the listener.
I've tried all sorts of variations, and can't see what I'm doing wrong. Thank you for any pointers!
the url in the request from the client is:
DELETE: "localhost:8080/api/tasks/1"
the structure of the route modules is like this:
catch all of the urls that start with "/api" in the app.js file and send them to routes/index.js
in routes/index, send all of the urls that start with "api/tasks" to routes/tasks.js
in routes/task.js send all of the requests that have a delete verb /routes/tasks/delete.js
in routes/tasks/delete.js, there is a route:
router.delete("/:id, async (req, res, next)=>{
ISSUE -----> this route never gets hit
})
More details:
the route files are like this:
/app.js
app.use("/api", require("./routes/index.js"));
/routes/index.js
const express = require("express");
const router = express.Router();
module.exports = router;
/**
* #route /api/tasks
* #verb get
*/
router.use("/tasks", require("./tasks"));
/routes/tasks/index.js
const express = require("express");
const router = express.Router();
module.exports = router;
/**
* #route /api/tasks
* #verb post
*/
router.post("/", require("./create"));
/**
* #route /api/tasks
* #verb get
*/
router.get("/", require("./read"));
/**
* #route /api/tasks
* #verb put
*/
router.put("/", require("./update"));
/**
* #route /api/tasks
* #verb delete
*/
router.delete("/", require("./delete"));
/routes/tasks/delete.js
const express = require("express");
const router = express.Router();
const db = require("../../models/db");
const { User, Task } = db.models;
module.exports = router;
router.delete("/:id", async (req, res, next) => {
let { id } = req.params;
// ISSUE: THIS ROUTE DOES NOT GET HIT
console.log("hit delete route");
try {
res.json({ test, "hit the delete route", id });
} catch (error) {
next(error);
}
});
/**
you have two conflicts
app.use(...) is for loading an exported router
the way you are loading individual routes is incorrect, they will not load in an exported route, they will instead take in a function (also called a "controller" in many frameworks)
// file 1 ./deleteController.js
const deleteController = (req, res, next) => {
// ...
}
module.exports = deleteController
// file 2 ./deleteRoutes.js
const express = require('express')
const router = express.Router()
const deleteController = require('./deleteController')
router.delete('/:id', deleteController)
module.exports = router
// file 3 ./index.js
// ...
app.use("/someNamespace", require("./deleteRoutes"))
// ...

Node Express dynamic route/path

How can I implement and get a dynamic route or path with Express package? The main problem is the path is an id pass by the client and had no control over it.
const express = require('express');
const dynamic_path= express();
dynamic_path.get('/user', (req, res) => {
});
exports.v1 = functions.runWith(runtimeOpts).https.onRequest(dynamic_path);
The above will result as https://my-app.net/v1/user and the client request will be https://my-app.net/v1/user/user_id. I need to allow dynamic path and I need to get the value of user_id as well for future usage.
Added :user_id to the route.
dynamic_path.get('/user/:user_id', (req, res) => {
const user_id = req.params.user_id;
});
Use the route:
https://my-app.net/v1/user/:user_id
Your code will be like this:
dynamic_path.get("/user/:user_id" , (req, res)=>{
let user_id = req.parmas.user_id
}

Request parameter in Express router

I'm having some trouble accessing request parameters in express router.
My server.js file has this:
app.use('/user/:id/profile', require('./routes/profile');
And this is in my ./routes/profile.js file:
router.get('/', (req, res) => {
console.log(req.params.id);
}
But the console log prints undefined.
I'm new to express and feel like I'm missing something basic about how routing works.
Can someone please help me out?
Here is my full server.js:
const express = require('express');
const app = express();
app.use(express.json());
app.use('/user/:id/profile', require('./routes/profile'));
app.listen(5000, () => console.log('Listening'));
Here is my full profile.js:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
console.log(req.params.id);
res.status(200).send('In profile route');
});
module.exports = router;
URL parameters are not exposed to routers. You have a couple of options here:
Parse req.originalUrl to get the user id (not recommended). req.originalUrl isn't affected by the router's mount point and will remain as /user/112/profile or whatever url you visited.
Add some middleware to expose the id (recommended). Your new route statement will end up looking like this:
(Now you can use req.userId in your profile.js)
app.use('/user/:id/profile', function(req, res, next) {
req.userId = req.params.id;
next();
}, require('./routes/profile'));
Change the mount point from /user/:id/profile to /user, then edit your router to listen on /:id/profile (not recommended).

Is there a better way to structure Express (nodejs) application routes?

I have my app.js where I have the server created and this is where I define the main routes. I only added parts of my code.
const app = express();
const user = require("./routes/user/user");
app.use("/user", user);
In the ./routes/user/user.js I am able to define the routes like this
const express = require("express");
const router = express.Router();
router.get("/profile", (req, res) => {
/*some more code*/
});
router.post("/register", (req, res) => {
/*some more code*/
});
router.get("/timeline", (req, res) => {
/*some more code*/
})
module.exports = router;
Right now ./routes/user/user.js is not messy, but when we add more routes it can get pretty ugly.
My goal would be to have ./routes/user/combineUserRoutes.js where I could combine multiple requests without defining them there.
These request files would be structured something like this:
./routes/user/auth/register.js
./routes/user/profile/profile.js
./routes/user/timeline/index.js

Dynamic routes with different functions in express js

I have loads of router.get functions in my code which I think, could be reduced to a single switch-case function. Here is what I have tried:
function handlerA(req, res) {}
function handlerB(req, res) {}
var routes = {
'/url-one': handlerA,
'/url-two': handlerB
}
router.get('/*', function(req, res) {
var url = req.url;
if (routes[url]) {
routes[url](req, res);
}
});
This works but also, significantly slows my application. Is there any other solution which would not hit the performance of my app?
Thanks
Is there a reason you don't want to use router.get functions? I would guess express.js is internally performing the same logic that you are doing anyway. You are just replacing get functions with handlers.
If you are using similar logic between multiple routes, that may be worth abstracting.
I usually go with a setup like this:
app.js
routes.js
api/
user/
index.js
user.controller.js
user.model.js
image/
index.js
image.controller.js
image.model.js
/api/user/index.js:
var express = require('express');
var controller = require('./user.controller');
var router = express.Router();
router.get('/', controller.index);
router.post('/', controller.create);
module.exports = router;
/api/user/user.controller.js:
var User = require('./user.model');
exports.index = function(req, res) {
// Show list of users
};
exports.create = function (req, res, next) {
// Create user
};
/routes.js:
module.exports = function(app) {
// Insert routes below
app.use('/api/users', require('./api/user'));
app.use('/api/images', require('./api/image'));
// All undefined asset or api routes should return a 404
app.route('/:url(api|auth|components|app|bower_components|assets)/*')
.get(errors[404]);
// All other routes should redirect to the index.html
app.route('/*')
.get(function(req, res) {
res.sendfile(app.get('appPath') + '/index.html');
});
};
And lastly, the /app.js:
// Set default node environment to development
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var express = require('express');
var mongoose = require('mongoose');
var config = require('./config/environment');
// Connect to database
mongoose.connect(config.mongo.uri, config.mongo.options);
// Populate DB with sample data
if(config.seedDB) { require('./config/seed'); }
// Setup server
var app = express();
var server = require('http').createServer(app);
require('./config/express')(app);
require('./routes')(app);
// Start server
server.listen(config.port, config.ip, function () {
console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});
// Expose app
exports = module.exports = app;
Most of this is directly from the Yeoman Generator Angular-Fullstack and it has a really nice setup!

Categories

Resources