I have the following code and also have defined the response for POST/messages but when I go to /bc/add and submit a form it shows that Cannot POST /messages.
Can you please explain me the reason?
Here is my code :
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use("/bc/add", (req, res, next) => {
console.log("In the next middleware !", req.url);
res.send(
'<form action="/messages" method="post"><input type="text" name="message"><button type="submit">Submit </button></form>'
);
app.use("/s", (req, res, next) => {
res.send("hup");
});
app.post("/messages", (req, res, next) => {
console.log(req.body);
console.log("In the middleware !", req.url);
res.redirect("/s");
});
});
app.use("/favicon.ico", (req, res, next) => {
console.log("In the middleware !", req.url);
res.sendStatus(204);
});
app.listen(3000, () => {
console.log("Server running at port 3000");
});
You are declaring handlers inside a middleware, which isn't how Express works.
The handlers need to be declared at the "top level":
app.use("/bc/add", (req, res, next) => {
console.log("In the next middleware !", req.url);
res.send(
'<form action="/messages" method="post"><input type="text" name="message"><button type="submit">Submit </button></form>'
);
}); // end of the "middleware"
app.use("/s", (req, res, next) => {
res.send("hup");
});
app.post("/messages", (req, res, next) => {
console.log(req.body);
console.log("In the middleware !", req.url);
res.redirect("/s");
});
Besides that, semantically speaking the handlers for /bc/add/ and /s aren't middleware, but route handlers. It's better to declare them as such explicitely, by using app.get() instead of app.use().
Related
I had originally been using bodyParser as so:
app.use(bodyParser.json());
However, now I want to conditionally use bodyParser:
app.use((req, res, next) => {
if (req.originalUrl === '/hooks') {
next();
} else {
bodyParser.json()(req, res, next);
}
});
When I try to remove (req, res, next), the parser does not work. That is,
app.use((req, res, next) => {
if (req.originalUrl === '/hooks') {
next();
} else {
bodyParser.json();
}
});
does not work.
Why do I need (req, res, next) after bodyParser.json()?
https://github.com/expressjs/body-parser/blob/master/index.js#L108
function bodyParser (options) {
var opts = {}
// exclude type option
if (options) {
for (var prop in options) {
if (prop !== 'type') {
opts[prop] = options[prop]
}
}
}
var _urlencoded = exports.urlencoded(opts)
var _json = exports.json(opts)
return function bodyParser (req, res, next) {
_json(req, res, function (err) {
if (err) return next(err)
_urlencoded(req, res, next)
})
}
}
Body parser is a middleware that needs access to res, req and next.
It parses your request using req and in order to pass control to the next middleware, it needs access to the next function.
Here app.use(bodyParser.json()); are passed (req, res, next) by default as
bodyParser.json() returns return function bodyParser (req, res, next) { .. }
so it becomes --> app.use(function bodyParser (req, res, next) { .. });
but in your case, you are creating a middleware by your self and you are responsible to pass the parameters to bodyParser so it can have access to the required arguments.
app.use((req, res, next) => {
if (req.originalUrl === '/hooks') {
next();
} else {
bodyParser.json()(req, res, next);
}
});
See how app.use works below
https://github.com/expressjs/express/blob/master/lib/application.js#L187-L242
I have two middleware functions attached to my app get request which works fine.
const express = require('express');
const app = express();
function fun1 (req, res, next) {
console.log('this is fun1')
next()
}
function fun2 (req, res, next) {
console.log('this is fun2')
next()
}
app.get('/', fun1, fun2, function (req, res, next) {
res.send('User Info')
})
app.listen(8080, () => console.log(`Listening on port 8080!`))
Now if I try to do next('test') in fun1 then it bypass fun2 and does 'test' output in browser window instead of 'User Info' which is correct. But how do I get data in fun2? I need to pass something from fun1 and get it in fun2 for further validation.
Assign it to req. You will have access to the same request and response objects through all middlewares.
Note that next('test') does not respond to the client or at least it is not meant to. It is meant to handle errors. Without an error handler and in development mode, Express shows these errors in the browser.
Read on:
Error handling in Express
You can do this by attaching a key-value pair with req` object.
Now how to do this,
const express = require('express');
const app = express();
function fun1 (req, res, next) {
req.MY_VAR = 'MY_VAL'; // setting the value
console.log('this is fun1')
next()
}
function fun2 (req, res, next) {
let myVar = req.MY_VAR; // retrieving the value
console.log(myVar); // MY_VAL
console.log('this is fun2')
next()
}
app.get('/', fun1, fun2, function (req, res, next) {
res.send('User Info')
})
app.listen(8080, () => console.log(`Listening on port 8080!`))
Now, why not next()? Generally, the value passed in next() will be received by the error argument in app.get('/', function (err, req, res, next) {} );
im trying to setup an API using node.js and in my app.js class im handling request errors where i return a 404 in case something goes wrong, now thats my problem, i can't see how am i requesting anything wrong, i am still receiving 404 error, im trying to send a post request to my API exactly like this:
{
"name":"Harry Potter 5",
"price":"12.99"
}
then i get this
Here's my app.js
const express = require('express');
const app = express();
const morgan = require('morgan');
const productRoutes = require('./api/routes/product');
const orderRoutes = require('./api/routes/order');
const bodyParser = require('body-parser');
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({
extended:false
}));
app.use(bodyParser.json());
app.use((req, res, next) => {
const error = new Error("Not found");
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
app.use('/products', productRoutes);
app.use('/orders', orderRoutes);
module.exports = app;
Here's my product.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res, next) => {
res.status(200).json({
message: 'Handling GET requests to /products'
});
});
router.post('/', (req, res, next) => {
const product = {
name: req.body.name,
price: req.body.price
};
res.status(201).json({
message: 'Handling POST requests to /products',
createdProduct: product
});
});
router.get('/:productId', (req, res, next) => {
const id = req.params.productId;
if (id === 'special') {
res.status(200).json({
message: 'You discovered the special ID',
id: id
});
} else {
res.status(200).json({
message: 'You passed an ID'
});
}
});
router.patch('/:productId', (req, res, next) => {
res.status(200).json({
message: 'Updated product!'
});
});
router.delete('/:productId', (req, res, next) => {
res.status(200).json({
message: 'Deleted product!'
});
});
module.exports = router;
It's because you are setting everything to error out :)
See the documentation from here - from the provided link:
Writing error handlers Define error-handling middleware functions in
the same way as other middleware functions, except error-handling
functions have four arguments instead of three: (err, req, res, next).
For example:
// pay attention to err param
app.use(function (err, req, res, next) {
console.error(err.stack)`
res.status(500).send('Something broke!')
})
In your code you have this bit:
app.use((req, res, next) => {
const error = new Error("Not found");
error.status = 404;
next(error);
});
which tells express that every request should be responded with a 404. You should either make it a proper error handler, or remove it.
This is because any request execute the 404 handler.
Look at this shorten version of your code:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended:false
}));
app.use(bodyParser.json());
app.use((req, res, next) => {
console.log("Got into 404 handler");
const error = new Error("Not found");
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
console.log("Got into 500 handler");
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
app.use('/products', (req, res, next) => {
console.log("Got into 200 handler");
res.status(200).end();
});
app.listen(8080);
It prints "Got into 404 handler" at each request. Now, if you comment out the 404 callback this way: all requests go through the 500 and 200 callbacks:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended:false
}));
app.use(bodyParser.json());
/* there used to be the 404 callback here */
app.use((error, req, res, next) => {
console.log("Got into 500 handler");
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
app.use('/products', (req, res, next) => {
console.log("Got into 200 handler");
res.status(200).end();
});
app.listen(8080);
Now in your specific problem, the code below would work (I just swapped the order of the handlers):
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended:false
}));
app.use(bodyParser.json());
app.use('/products', (req, res, next) => {
console.log("Got into 200 handler");
res.status(200).end();
});
app.use((req, res, next) => {
console.log("Got into 404 handler");
const error = new Error("Not found");
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
console.log("Got into 500 handler");
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
app.listen(8080);
Hope this helps.
I am trying to pass some predefined functions in the callback of app.post() method. I am getting next is not defined error. Below is my code. Please suggest where I am doing wrong or am I missing any concept here?
var express = require('express');
var app = express()
app.post('/api/signup', function(req, res) {
validateParams(req, res, next),
dbCall(req, res, next),
sendResponse(req, res)
})
where I have each function defined and imported and returning next() after my process.
my validateParams function is below :
validateParams = function(req, res, next) {
console.log("at validator ", req);
next();
}
module.exports = validateParams;
my dbCall function is below :
dbCall = function(req, res, next) {
console.log("at dbCall ", req);
next();
}
module.exports = dbCall;
my sendResponse function is below :
sendResponse = function(req, res) {
console.log("at dbCall ", res);
res.send("Response sent successfully");
}
module.exports = sendResponse;
You probably forgot to add the next argument in your callback.
app.post('/api/signup', function(req, res, next) {
validateParams(req, res, next),
dbCall(req, res, next),
sendResponse(req, res)
})
I think you are trying to use validateParams(req, res, next) and dbCall(req, res, next) as middleware functions. In this case, you need something like this:
const validateParams = (req, res, next) => {
// do stuff here
next();
}
const dbCall = (req, res, next) => {
// do stuff here
next();
}
app.post('/api/signup', validateParams, dbCall, function(req, res) {
sendResponse(req, res)
})
You can read more here
I am new to Node.js,and so far I have managed to install Express. Now I have three js files,that handle CRUD requests to a localserver.
ie.
localhost:3000/dishes
localhost:3000/promotions
etc. However, when I am doing a simple get request in postman,I get this error.
GET /dishes 500 8.883 ms - -
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
I am going to show you my files.
dishRouter.js
//exporing the functionality
module.exports = function (dishRouter, bp) {
dishRouter.use(bp.json()); //using body parser for parsing json from body
content
//code for url '/'
dishRouter.route('/').all(function (req, res, next) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
next();
})
//setting up code for get request
.get(function (req, res, next) {
res.end('Will send all the dishes to you!');
})
//setting up code for post request
.post(function (req, res, next) {
res.end('Will add the dish: ' + req.body.name + ' with details: ' +
req.body.description);
})
//setting up code for delete request
.delete(function (req, res, next) {
res.end('Deleting all dishes');
});
//code for url with specific ids
dishRouter.route('/:dishId')
.all(function (req, res, next) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
next();
})
//setting up code for get request
.get(function (req, res, next) {
res.end('Will send details of the dish: ' + req.params.dishId + ' to you!');
})
//setting up code for put request
.put(function (req, res, next) {
res.write('Updating the dish: ' + req.params.dishId + '\n');
res.end('Will update the dish: ' + req.body.name +
' with details: ' + req.body.description);
})
//setting up code for delete request
.delete(function (req, res, next) {
res.end('Deleting dish: ' + req.params.dishId);
});
};
promoRouter.js
//exporting the functionality
module.exports = function (promoRouter, bp) {
promoRouter.use(bp.json()); //using body parser for parsing json
from body content
//code for url '/'
promoRouter.route('/').all(function (req, res, next) {
res.writeHead(200, { //writing header
'Content-Type': 'text/plain'
});
next();
})
//setting up code for get request
.get(function (req, res, next) {
res.end('Will send all the promotions to you!');
})
//setting up code for post request
.post(function (req, res, next) {
res.end('Will add the promotion: ' + req.body.name + ' with
details: ' + req.body.description);
})
//setting up code for delete request
.delete(function (req, res, next) {
res.end('Deleting all promotions');
});
//code for url with specific ids
promoRouter.route('/:promoId')
.all(function (req, res, next) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
next();
})
//setting up code for get request
.get(function (req, res, next) {
res.end('Will send details of the promotion: ' +
req.params.promoId + ' to you!');
})
//setting up code for put request
.put(function (req, res, next) {
res.write('Updating the promotion: ' + req.params.promoId + '\n');
res.end('Will update the promotion: ' + req.body.name +
' with details: ' + req.body.description);
})
//setting up code for delete request
.delete(function (req, res, next) {
res.end('Deleting promotion: ' + req.params.promoId);
});
};
leaderRouter.js
//exporing the functionality
module.exports = function (leaderRouter, bp) {
leaderRouter.use(bp.json()); //using body parser for parsing json from body
content
//code for url '/'
leaderRouter.route('/').all(function (req, res, next) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
next();
})
//setting up code for get request
.get(function (req, res, next) {
res.end('Will send all the leaders to you!');
})
//setting up code for post request
.post(function (req, res, next) {
res.end('Will add the leader: ' + req.body.name + ' with details: '
+ req.body.description);
})
//setting up code for delete request
.delete(function (req, res, next) {
res.end('Deleting all leaders');
});
//code for url with specific ids
leaderRouter.route('/:leaderId')
.all(function (req, res, next) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
next();
})
//setting up code for get request
.get(function (req, res, next) {
res.end('Will send details of the leader: ' + req.params.leaderId + ' to you!');
})
//setting up code for put request
.put(function (req, res, next) {
res.write('Updating the leader: ' + req.params.leaderId + '\n');
res.end('Will update the leader: ' + req.body.name +
' with details: ' + req.body.description);
})
//setting up code for delete request
.delete(function (req, res, next) {
res.end('Deleting leader: ' + req.params.leaderId);
});
};
server.js
var express = require('express');
var morgan = require('morgan');
var port = 3000;
var hostname = 'localhost';
var app = express();
app.use(morgan('dev'));
var dishRouter = require('./dishRouter');
app.use('/dishes',dishRouter.exports);
var leaderRouter = require('./leaderRouter');
app.use('/leadership', leaderRouter.router);
var promoRouter = require('./promoRouter');
app.use('/promotions', promoRouter.router);
app.use(express.static(__dirname + '/public'));
app.listen(port, hostname, function () {
console.log(`Server running at http://${hostname}:${port}/`);
});
The above 4 files are inside the routes folder. And finally,I have app.js.
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var dishRouter = require('./routes/dishRouter');
var promoRouter = require('./routes/promoRouter');
var leaderRouter = require('./routes/leaderRouter');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/dishes',dishRouter);
app.use('/promotions',promoRouter);
app.use('/leadership',leaderRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
Any ideas why I am getting this error? Please advice.
Thanks,
Theo.