Express.js - How to set a header to all responses - node.js

I am using Express for web services and I need the responses to be encoded in utf-8.
I know I can do the following to each response:
response.setHeader('charset', 'utf-8');
Is there a clean way to set a header or a charset for all responses sent by the express application?

Just use a middleware statement that executes for all routes:
// a middleware with no mount path; gets executed for every request to the app
app.use(function(req, res, next) {
res.setHeader('charset', 'utf-8')
next();
});
And, make sure this is registered before any routes that you want it to apply to:
app.use(...);
app.get('/index.html', ...);
Express middleware documentation here.

Related

Express routes invoking multiple router function

I've created a NodeJS Express app. But my express route is invocking multiple routes function, one after another, but I only need one at a time.
My express app.js
app.use(routes)
Express router:
const router = express.Router();
router.post("/product", controller.productFunction)
router.post("/user", controller.userFunction)
router.get("/:id", idController.getId)
Whenever I create a post request for "/product" route, first the productFunction is invocked, but then the "/:id" routes getId function is also get invocked. Same thing happen for /user route as well. Always /:id route is getting invocked.
Is there any way to prevent this?
I even tried this way, but after the homepage loading then again it invockes getId function.
app.get("/", (req, res, next) => {
res.sendFile(..........);
});
app.use(routes);
I am sure that this is not an issue with the router itself.
You can't skip from POST to GET handling. So invocations are caused by different requests.
router.get("/:id", idController.getId) kind of wild card, and <server_url>/favicon.ico will trigger it
If you check it via browser it tries to get favicon or smth else and invokes this handler.
Try to make POST request via curl/Postman and idController.getId should not be called.
It is risky to serve static and process requests on a same level.
You can add some prefix to all your request, like that app.use('/api', routes); then static file will be available on /<file_name> and all server logic will be under /api/<request>

NodeJs/Express: Authorise all endpoints except one

In my NodeJs/express based application, I am authorizing calls to all the endpoints by using the following middleware.
app.use(restrictByCookieMiddleware);
I want to authorize all endpoints except one i.e. I don't want "restrictByCookieMiddleware" middleware to run for "/metrics" endpoint. Is there a way to escape one endpoint?
Here, I found some examples that matches endpoint for which middleware should run, I am looking for a solution that skips one.
Your have a couple of choices:
First, you can just define the one exception route handler BEFORE the middleware. Then, it will handle that route and the routing will never get to the middleware.
app.get("/login", (req, res) => {
// handle that one special route here
});
// all other routes will get this middleware
app.use(restrictByCookieMiddleware);
Second, you can make a wrapper for the middleware that compares to the one specific route and skips the middleware if it's that route:
app.use((req, res, next) => {
// shortcircuit the /login path so it doesn't call the middleware
if (req.path === "/login") {
next();
} else {
restrictByCookieMiddleware(req, res, next);
}
});
// then, somewhere else in your code would be the /login route
app.get("/login", ...);
Third, if you have multiple routes that you want to skip the middleware for, you can segment things by router. Create a router for the non-middleware routes and put all of them on that router. Hook that router into the app object first.
Then, create a second router that contains the middleware and has all your other routes on it.
Place that specific route, you want to exclude, before this line:
app.use(restrictByCookieMiddleware);
So this will solve your problem.

Express JS match route without handling

Given an instance of a Express JS app or router, is it possible to match a request against the apps configured routes and receive a object that describes the route as registered with the app?
For instance, if a request for /users/1 were to be handled by the application, would it be possible for the app/router instance to programatically check if the app has a route that would satisfy this request given the URI and HTTP method?
Desirable sudo(ish) code:
const app = express();
app.use((req, res, next) => {
const handler = app.match(req);
// {
// 'method': 'GET',
// 'path': '/user/:id', <--- mainly looking for this
// 'handler': <function reference>
// }
next();
});
app.get('/user/:id', (req, res, next) => {
// fetch the user and do something with it
});
...
AFAIK there are no publicly documented Express router endpoints that provide the behavior you are describing based on its 4.x Documentation.
However, you could implement this yourself by creating a custom regular expression validator to check if the req.path string matches any defined path. The downside to this is that you would have to maintain that list separately from what is registered to Express, which might prove to be difficult to maintain.
You may be able to root through the internals of the app object to get the functionality you need, but note the instability of that approach will mean your solution could potentially be broken by non-major updates to Express.

nodejs express wildcard route not working

I'm doing an API in nodejs with express as router.
Now i'm trying to implement an client-id and an apikey to add some security to the API, and the problem that i'm facing is the next:
One of my API call is like this:
router.get("roles/get-objects/:mail/:filter*?")
So this means, that i can request an object like this:
/roles/get-objects/mail#mail.com/customer
Now the tricky part begins... when I needed to stablish a middleware to read an client-id and an apikey to verify that the client is authorized to se the API, so I did this:
In the declaration of the middleware, I use this wildcard:
router.all('/*', function (req, res, next) {
XXXX})
The thing is, I have tried in the middleware, as a wildcard everything...
I want that any API call is filtered thru that middleware, but apparently I can't find the right wildcard for it...
When I use /roles/* as wildcard, if I do a request to /roles it does work, but when I use the complete URL like: /roles/get-objects/mail#mail.com/customer it doesn't go thru my middleware.
So anybody has any idea? i'm starting to loose my mind
Thank you so much to all of you!
EDIT:
Now i'm using this middleware declaration:
router.use(function (req, res, next) {XXXX})
So when I call:
/roles/get-objects/
It's executed, the problem is when I add the email to the route:
/roles/get-objects/mail#mail.com
The app goes directly to the route that i have for that, but omits my middleware:
router.get("roles/get-objects/:mail",
I don't understand why is this happening, apparently everything should go thru my middleware first, or am I wrong?
If you want to establish a middleware to check all HTTP request whose URL starting with /roles/, the middleware should be placed before any other specific router definition:
router.use('/roles', function(req, res, next) {...});
...
router.get('/roles/get-objects/:mail', ...);
If the middleware is defined after specific route, when HTTP request comes in, the specific route is targeted and processed, the middleware won't be executed any more:
router.get('/roles/get-objects/:mail', ...);
...
router.use('/roles', function(req, res, next) {...}); // This middleware logic won't execute when request is sent to '/roles/get-objects/some-email', as the request has already been handled and response is already sent to browser.

How to use AngularJS routes with Express (Node.js) when a new page is requested?

I'm using Express, which loads AngularJS from a static directory. Normally, I will request http://localhost/, in which Express serves me my index.html and all of the correct Angular files, etc. In my Angular app, I have these routes setup, which replace the content in an ng-view:
$routeProvider.when('/', {
templateUrl: '/partials/main.html',
controller: MainCtrl,
});
$routeProvider.when('/project/:projectId', {
templateUrl: '/partials/project.html',
controller: ProjectCtrl,
});
$locationProvider.html5Mode(true);
On my main page, I have a link to <a href="/project/{{project.id}}">, which will successfully load the template and direct me to http://localhost/project/3 or whatever ID I have specified. The problem is when I try to direct my browser to http://localhost/project/3 or refresh the page, the request is going to the Express/Node server, which returns Cannot GET /project/3.
How do I setup my Express routes to accommodate for this? I'm guessing it will require the use of $location in Angular (although I'd prefer to avoid the ugly ?searches and #hashes they use), but I'm clueless about how to go about setting up the Express routes to handle this.
Thanks.
with express 4, you probably want to catch all requests and redirect to angularjs index.html page.
app.use(app.router); doesn't exist anymore and res.sendfile is deprecated, use res.sendFilewith an uppercase F.
app.post('/projects/', projectController.createProject);
app.get('/projects/:id', projectController.getProject);
app.get('*', function (req, res) {
res.sendFile('/public/index.html');
});
put all your API routes before the route for every path app.get('*', function (req, res){...})
I would create a catch-all handler that runs after your regular routes that sends the necessary data.
app = express();
// your normal configuration like `app.use(express.bodyParser());` here
// ...
app.use(app.router);
app.use(function(req, res) {
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/public/index.html');
});
app.router is the middleware that runs all of your Express routes (like app.get and app.post); normally, Express puts this at the very end of the middleware chain automatically, but you can also add it to the chain explicitly, like we did here.
Then, if the URL isn't handled by app.router, the last middleware will send the Angular HTML view down to the client. This will happen for any URL that isn't handled by the other middleware, so your Angular app will have to handle invalid routes correctly.
I guess I should have clarified that I wasn't interested in using a template engine, but having Angular pull all of the HTML partials on it's own, Node is functioning completely as a static server here (but it won't be for the JSON API. Brian Ford shows how to do it using Jade here: http://briantford.com/blog/angular-express.html
My app is a single-page app, so I created an Express route for each possible URL pattern, and each of them does the same thing.
fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, content) {
res.send(content);
});
I was assuming I would have to pass some request variables to Angular, but it looks like Angular takes care of it automatically.

Resources