How to reference a variable in regex URL? - javascript

router.get("/(A|B)/account/", async (req, res) => {});
How to do I reference the (A|B) inside of the async function?

I guess your route responsibility is getting account information of only A or B. So let's change your router path to /account/:name(A|B), then your express router will look like this:
router.get("/account/:name(A|B)", async (req, res) => {
const name = req.params; // A or B
});
Only 2 kinds of requests are handled by this router:
GET /account/A
or
GET /account/B

Related

How to pass req.params as an an argument to a middleware function?

I'm trying to figure out a way to use req.params as an argument in my middleware. Take this (obviously broken) code for example:
router.post('/:myParam', checkSchema(schemas[req.params.myParam]), async (req, res, next) => {
// do stuff
})
The goal here is that I am using express-validator and I load a dynamic schema based on what param is passed. The above code is obviously broken because I don't yet have the scope to access the req variable, I'm just trying to illustrate what I'm trying to accomplish.
if you know the possible params ahead, you could do something like the following:
router.post("/:myParam", checkSchema("soccer"), async (req, res, next) => {});
//checkSchema.JS
const soccerSchema = require("../schemas/soccerSchema");
const swimmingSchema = require("../schemas/swimmingSchema");
module.exports = function (schemaName) {
return (req, res, next) => {
const schemas = { soccer: soccerSchema, swimming: swimmingSchema };
//You can access it here schemas[schemaName]
console.log(schemas[schemaName]);
next();
};
};
You can directly call schemas(req.params.myParam) inside the checkSchema middleware since the middleware will have access to the request object.

chain middleware functions in custom function

I know that I can chain middleware functions after passing in the route like
const express = require('express');
const router = express.Router();
router.post('/', middlewareFunction1, middlewareFunction2, controllerFunction);
module.exports = router;
I would like to know if it's possible to call only one function (called gateway)
router.post('/', gatewayFunction1);
and this function is able to chain all those methods
const controller = require('../controllers/controller');
function gatewayFunction1(request, response, next) {
// validate route
// do other middleware stuff
// call controller.function1
}
module.exports = {
gatewayFunction1,
};
Why would I do that? I was thinking about separating the middleware logic from the routes. This gateway should just get executed after routing and before calling the router.
I tried to return an array of functions (example code)
function gatewayFunction1(request, response, next) {
return [(request, response, next) => {
console.log('called middleware 1');
next();
}, (request, response, next) => {
console.log('called middleware 2');
next();
}, (request, response, next) => {
response.status(200).json({
message: 'that worked',
});
}];
}
but when I call this api route I get no response
Could not get any response
so it keeps loading forever. Is there a way to chain these middleware functions within another function?
Your gatewayFunction1 does nothing except returns an array.
Just use router.
const express = require('express');
const gatewayFunction1 = express.Router();
gatewayFunction1.use(middlewareFunction1, middlewareFunction2, controllerFunction);
module.exports = gatewayFunction1;
Then
const gatewayFunction1 = require('...'); // where you define gatewayFunction1
router.post('/', gatewayFunction1);
Middleware should be a function and you are returning an array.If next function is not called it will get stuck. I don't like the whole idea combining them but I think the best way is to import all your middleware functions in one function and call them individually then use that function as your combined middleware.

Express Nested Router not calling sub functions

I have the following router.use calls in one of my routers
router.use("/:collection/", (req) => {
return require(`./${req.params.collection}`);
});
and that calls in this example, example.js
example.js is as follows:
const header = require("../../header"); //gets our header that declares everything
const router = header.express.Router(); //makes our router for collections requests
console.log("123");
///The Following is when a name is requested
router.get("/test", (req, res, next) => {
console.log("test");
res.json({msg:"hi"});
next();
});
module.exports = router; //makes our router avialable
you'd expect when:
http://localhost:3000/api/example/test
is request that it would write in the console something to the effect of:
123
test
and I would get the response:
{msg:"hi"}
Instead the console gets just:
123
written and there is no response.
It seems the
router.get
in the example.js is never called, can someone tell me why?
I fixed it, instead of
router.use("/:collection/", (req) => {
return require(`./${req.params.collection}`);
});
I use
router.get("/:collection", (req, res) => {
//this is my other call that will do stuff in the parent file
//we don't call next because it is already matched, otherwise we call next
});
router.use("/:collection/", (req, res, next) =>{ //says if it gets here pass on the info
router.use("/:collection/", require(`./${req.params.collection}`)); //then route
next();
});

Routes in express JS taken from DB

I want to use routes something like this.
For example :
routes.use((req, res, next) => {
/**
* I have an example routes from database and i was passing into variable
* I'm assign fromDb as 'api/test'
*/
var a = fromDb;
next()
})
routes.get(a, (req, res, next) => {
console.log(req.path)
})
I know, a variable in next routes do not get a value from DB cause functional scope. So, any idea for solve this method. I just wondering if I can using modular like this
const DBRoutes = require('lib/example.js')
router.get(DBRoutes, (req, res) => {
console.log(req.path)
})
Any idea for the best method? Thanks
You want to add a route based on content in your database
So you could do the lookup and on success create the route
eg:
dbConnection.lookup(...some query)
.then((pathFromDB) => {
// where pathfromDb = /api/test
routes.get(pathFromDB, (req, res, next) => {
console.log(req.path)
})
});
routes.use((req, res, next) => {
/**
* I have an example routes from database and i was passing into variable
* I'm assign fromDb as 'api/test'
*/
res.locals.fromDb = fromDb;
next()
})
routes.get('/your/route', (req, res, next) => {
console.log(req.path);
console.log(res.locals.fromDb);
});
This is one way of passing variables through different middlewares in express.
I don't think you can dynamically set up routes for express web server. However, routes are set up once during startup. You can get the routes from database at that time.
const route = await routeFromDatabase();
routes.get(route, (req, res, next) => {
console.log(req.path);
console.log(res.locals.fromDb);
});
If you change the database after startup, you will have to restart the node app.
Update 19th Feb 2018: User mentioned the use case as API Gateway. This is worth exploring for such use cases: https://www.express-gateway.io/

Calling Express Route internally from inside NodeJS

I have an ExpressJS routing for my API and I want to call it from within NodeJS
var api = require('./routes/api')
app.use('/api', api);
and inside my ./routes/api.js file
var express = require('express');
var router = express.Router();
router.use('/update', require('./update'));
module.exports = router;
so if I want to call /api/update/something/:withParam from my front end its all find, but I need to call this from within another aspect of my NodeJS script without having to redefine the whole function again in 2nd location
I have tried using the HTTP module from inside but I just get a "ECONNREFUSED" error
http.get('/api/update/something/:withParam', function(res) {
console.log("Got response: " + res.statusCode);
res.resume();
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
I understand the idea behind Express is to create routes, but how do I internally call them
The 'usual' or 'correct' way to handle this would be to have the function you want to call broken out by itself, detached from any route definitions. Perhaps in its own module, but not necessarily. Then just call it wherever you need it. Like so:
function updateSomething(thing) {
return myDb.save(thing);
}
// elsewhere:
router.put('/api/update/something/:withParam', function(req, res) {
updateSomething(req.params.withParam)
.then(function() { res.send(200, 'ok'); });
});
// another place:
function someOtherFunction() {
// other code...
updateSomething(...);
// ..
}
This is an easy way to do an internal redirect in Express 4:
The function that magic can do is: app._router.handle()
Testing: We make a request to home "/" and redirect it to otherPath "/other/path"
var app = express()
function otherPath(req, res, next) {
return res.send('ok')
}
function home(req, res, next) {
req.url = '/other/path'
/* Uncomment the next line if you want to change the method */
// req.method = 'POST'
return app._router.handle(req, res, next)
}
app.get('/other/path', otherPath)
app.get('/', home)
I've made a dedicated middleware for this : uest.
Available within req it allows you to req.uest another route (from a given route).
It forwards original cookies to subsequent requests, and keeps req.session in sync across requests, for ex:
app.post('/login', async (req, res, next) => {
const {username, password} = req.body
const {body: session} = await req.uest({
method: 'POST',
url: '/api/sessions',
body: {username, password}
}).catch(next)
console.log(`Welcome back ${session.user.firstname}!`
res.redirect('/profile')
})
It supports Promise, await and error-first callback.
See the README for more details
Separate your app and server files with the app being imported into the server file.
In the place you want to call your app internally, you can import you app as well as 'request' from 'supertest'. Then you can write
request(app).post('/someroute').send({
id: 'ecf8d501-5abe-46a9-984e-e081ac925def',
etc....
});`
This is another way.
const app = require('express')()
const axios = require('axios')
const log = console.log
const PORT = 3000
const URL = 'http://localhost:' + PORT
const apiPath = (path) => URL + path
app.get('/a', (req, res) => {
res.json('yoy')
})
app.get('/b', async (req, res) => {
let a = await axios.get(apiPath('/a'))
res.json(a.data)
})
app.listen(PORT)

Categories