Based on Express docs, a middleware must run each time app is launched following this code:
var app = express();
app.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
Well, trying to execute with the most simple possilbe example middleware never is excuted:
var express = require('express');
var middleware = require('./middleware');
var app = express();
app.use(function (req, res, next){
console.log('MIDDLEWARE');
next();
});
module.exports = app;
Middleware never runs.
Also tryed to make it working from a separated file, but never runs.
Thanks
Middleware are lunch when there are any request to the server.
Create a route and send a request to that, the middleware would be lunched.
Ups, seems to be they're launched when recieves a request. So using Postman it worked.
Related
I have a few api calls set up via express and router. I am trying to debug and understand the working of the router. I have a logger set up, and trying to log all the api calls. However, the calls are never logged. All the api endpoints get called and the application works as expected though. Below is an example of what I am trying to do. Can someone please let me know what could be missing here?
const logger = require('./config');
const app = express();
// routes needed for the app
app.use(require('./routes/apis'));
app.use('/api', (req, res, next) => {
logger.info('in /api call');
});
you need to change the order of the middleware:
const logger = require('./config');
const app = express();
app.use('/api', (req, res, next) => {
logger.info('in /api call');
});
// routes needed for the app
app.use(require('./routes/apis'));
When I put app.use(bodyParser.json()); below app.use('/api', require('./routes/api'))
req.body returns undefined. But if I put app.use(bodyParser.json()); above app.use('/api', require('./routes/api')); it returns correctly. So the question is why?
Here is my code:
index.js file
const express = require('express');
const app = express();
const bodyParser= require('body-parser');
app.use(bodyParser.json());
app.use('/api', require('./routes/api'));
app.listen(process.env.port || 3000, function(){
console.log('You are listening to port 3000');
});
api.js file
const express= require('express');
const router= express.Router();
router.get('/ninjas', function(req, res){
res.send({type: 'GET'});
});
router.post('/ninjas', function(req, res){
console.log(req.body);
res.send({type: 'POST'});
});
router.put('/ninjas/:id', function(req, res){
res.send({type: 'PUT'});
});
router.delete('/ninjas/:id', function(req, res){
res.send({type: 'DELETE'});
});
module.exports =router;
Thanks in advance!
We need body-parser middleware to read from req.body,
In Javascript code executes line by line (for non IO operations).
So when you place app.use(bodyParser.json()) after requiring your router file logic, body-parser is not invoked and plugged, so you need to invoke it before any other logic, so that you can read from the request.
Bodyparser is a middleware which should run everytime when a route is accessed.
A middleware (like bodyparser) is written like this
const middleware = (req, res, next) => {
//some code here
next();
}
The next function starts the execution of another middleware function
So when you use the bodyparser middleware after the routes req.body will not be initialized because the bodyparser middleware never ran for the route and the response ends with the res.send().
But if you use the bodyparser middleware before initializing the routes the bodyparser middleware will always run.
You can see more examples on middleware in the expressjs docs
https://expressjs.com/en/guide/using-middleware.html
I am trying to de-bug an issue in my very simple express backend boilerplate. I have a universal middleware that I want to fire with every single request that hits the server (Essentially, I'm just trying to set a cookie.)
const express = require('express');
const path = require('path');
const uuidv4 = require('uuid/v4');
const cookieParser = require('cookie-parser')
const app = express();
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'client/build')));
app.use('/', (req, res, next) => {
console.log(req.cookies)
if (!req.cookies['audience_tracking_id']) {
console.log('Processed Request - User Does Not Have Cookie.')
const uniqueID = uuidv4();
res.setHeader('Set-Cookie', [`audience_tracking_id=${uniqueID}`, `contentFocus=${randomProductName()}`]);
}
next();
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/client/build/index.html'))
});
app.use(function(err, req, res, next) {
console.log(err)
res.status(err.status || 500).send();
});
const port = process.env.PORT || 6000;
app.listen(port);
console.log(`Audience Service Host listening on ${port}`);
The application includes a React Front-End which is hosted on Heroku, and I am serving the static build files through Express within the same container.
The issue is - Whether I use Postman to locally send a GET request to this file in localhost:6000, OR whether I access the container on Heroku, the console.log() fails to fire - and maybe the rest of the middleware.
However, if I move this line below the cookie middleware:
app.use(express.static(path.join(__dirname, 'client/build')));
OR, If I just comment it out, my middleware fires and the console.log() shows up. It was a simple fix, but I have no idea why this actually happens, does anyone know what I am doing wrong with this code that makes the middleware fail as-is?
It is because your "static file" middleware will try to match all request to your server:
app.use(express.static(path.join(__dirname, 'client/build')))
Your request "GET localhost:6000/*" will be routing to "static file" middleware before "cookie" middleware. If the "static file" middleware find the file exist, the response will be end with the file. If not, the middleware's action is relate to the option(fallthrough), you can get more detail on server-static's option
I suggest to set root mount path for static file middlware:
app.use("/dist", express.static(path.join(__dirname, 'client/build')))
If you want to check cookie in all request, use this format:
app.use((req, res, next) => {
// Do something
})
I just started learning express and I read that an express middleware is a Javascript function to handle HTTP requests. It accepts 3 parameters:- req, res and next.
When I tried the following code block:-
const express = require('express');
const app = express();
var x = app.get('/', function(req, res){
res.send('Hello World!');
} );
console.log(x.toString());
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
} );
I see the following output:-
function(req, res, next){
app.handle(req, res, next);
}
So is the express app object also an express middleware?
I'm sorry if this is a silly question, but wanted to have an insight nevertheless.
The .get() function is yes. the majority of the express functions .use() etc are really just middlewares for specific tasks. .get checks the req object against the url provided, if it's a match then it runs it's code. If it isn't then it continues to next() through all the other .get() middlewares.
The entire ecosystem of express is middlewares going to more middlewares
I have trouble implementing route mounting in express.js 4.13.3.
When I first install it, by default created in the app.js
var users = require('./routes/users');//get the "users" route
app.use('/users', users);//mount to "/users"
and the users.js route is like
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('respond with a resource');
});
module.exports = router;
Does not need to define router.get('/users'... because mounting took care of that in the app.js file.
But
When I try to do the same thing
in app.js I set
var upload = require('./routes/upload');
app.get('/upload', upload);//mounting (?)
the upload.js route is
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('upload', {title: 'Photo upload'});
});
module.exports = router;
When I access localhost/users I get 404 error. The only way to fix this , is to define in the upload.js router, this router.get('/upload' instead of this router.get('/'. But that would not be mounting.
The difference I see is that the default code uses app.use('/users', users); and my code uses app.get('/upload', upload);. Is the verb (use/get) the only difference that causes the 404? And if so, why? Or is it something else?
Thanks
You are totally correct that the problem is caused because these to functions work differently. Below are the official API specifications for the functions.
app.use is for mounting a middleware
app.get is for defining (only) one route for a HTTP GET request
This example shows a middleware function mounted on the /user/:id path. The function is executed for any type of HTTP request on the /user/:id path.
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
This example shows a route and its handler function (middleware system). The function handles GET requests to the /user/:id path.
app.get('/user/:id', function (req, res, next) {
res.send('USER');
});