how to pass data from conttoller to route - node.js

I am trying to pass data from controller to route.
I want to change the status code from a controller to route. let say if in controller status 200 then change it into 400 from routes
or
just simple print hello or something from routes after the response
here is controller from controller file
contact controller. js
exports.index = function(req, res) {
Contact.get(function(err, contacts) {
if (err) {
res.json({
status: "error",
message: err
});
}
res.json({
status: "success",
message: "Contacts retrieved successfully",
data: contacts
});
});
};
here is the route of it from route file
contact router.js
var contactController = require('./contactController');
// Contact routes
router.route('/contacts')
.get(contactController.index)

Follow this article to design you application using express router
https://scotch.io/tutorials/learn-to-use-the-new-router-in-expressjs-4
define your controller like this
exports.index = function(req, res, next) {
Contact.get(function(err, contacts) {
if (err) {
next(null,{
status: "error",
message: err
});
}
next({
status: "success",
message: "Contacts retrieved successfully",
data: contacts
},null);
});
};
Define main app file like this
var contactController = require('./contactController');
var router = express.Router();
// apply the routes to our application
// route middleware that will happen on every request
router.use(function(req, res, next) {
// continue doing what we were doing and go to the route
next();
});
// about page route (http://localhost:8080/about)
router.get('/contacts', function(req, res) {
//here you can call your controller js method
contactController.index(req,res, function(data, err){
//change anything you want here and set into res.
if(err){
//change status and data
}
else{
//change status and data
}
})
});

Don't end the request-response cycle in the controller, just return the result from the controller instead of ending the cycle.
const httperror = require('http-errors');
exports.index = async function(parameter) {
Contact.get(function(err, contacts) {
if (err) {
throw new httperror(400, "Error occured!");
}
return {
status: "success",
message: "Contacts retrieved successfully",
data: contacts
}
});
};
request should start from the route and response should be sent from the route
const contactController = require('./contactController');
router.get('/contacts', function (req, res, next) {
contactController.index()
.then(result => {
res.json(result)
}).catch((error) => {
res.status(200).json({"Error":"Returned success code 200 even though error
occured"});
})
});

Related

NodeJs Express Response Handler

I am new to express (or any JS backend) so sorry if question was already answered, or kind of stupid.
I have registered endpoint.
app.get('/hello-world'), async (req, res) => {
try {
// do something
sendResponse({"Message": "Hello World"}, res);
} catch (e) {
handleError(e, res);
}
});
Where sendResponse and handleError are doing just setting status and body / additional exception metadata using res.status().json()
Is there any way to make response handling more simple by registering some response handler and write the logic of response / exception handling at one place?
What I have in mind is this:
Change example endpoint logic to:
app.get('/hello-world'), async (req, res) => {
return {"Message": "Hello World"}
// or throw new error
});
and some repsonse handler which will handle result of function
resposeHandler(payload, err, res) {
if (err) {
res.status(500).json(err) // just as an example
} else {
res.status(200).json(payload)
}
}
You can create a function wrapper to catch all the errors and send them to the error middleware:
const errorHandler = (routeHandler) =>
(req, res, next) => {
const routeHandlerReturn = routeHandler(req, res, next)
return Promise.resolve(routeHandlerReturn).catch(next)
}
Then you can reutilize it in all your controllers, making the app much cleaner:
app.get('/hello-world', errorHandler(async function(req, res, next) {
sendResponse({"Message": "Hello World"}, res);
});
If some error is thrown, it will be handled in your error handler middleware:
// index.js
app.use((err, req, res, next) => {
res.status(err.status || 500)
res.json({
message: err.message || 'Internal Error',
error: err.error
})
})
create two middlewares, one for error handle and the other one for success response
// error handling when error occured
function errorHandler(req,res,next) => {
return res.status(err.status || 500).json({
success: false,
message: err.message
});
};
// success response and return data
function successHandler(successMsg, successData) => {
return (req,res,next) => {
return res.status(200).json({
success: true,
message: successMsg,
data: successData
});
};
};
register them in express
const app = express();
app.get('/someroute', successHandler('it is endpoint of someroute!', 'your data here'))
app.use(errorHandler)
use errorHandler after you call and define the route

Can I make an exception for a route in Express?

Following is the code I am referring to,
axios.get('http://localhost:1337/')
.then( response => {
var dataSet = response.data;
// URL Handle for Data page
app.get('/data', (req, res) => {
res.render('data', {
data = dataSet
});
});
})
.catch( error => {
console.log('An error occurred: ' + error);
});
// URL Handle for Contact page
app.get('/contact', (req, res) => {
res.render('contact');
});
// URL Handle for Error page
app.all('*', (req, res) => {
res.render('error');
});
Now, as I am using Axios for fetching the response from the database, I am also rendering the data in that desired page where I want the response of the API.
But there's a problem when I am using "app.all" handler for the wrong URL handle, it redirects to the error page.
I need a solution in which there can be an exception which can be added to the "app.all" handler and whenever the handle is '/data' it does not redirect to '/error'.
Looks like your route for /data is registered after the async call of axios is completed.
Try, putting axios call inside route handler
app.get('/data', (req, res) => {
axios.get('http://localhost:1337/').then( response => {
var dataSet = response.data;
res.render('data', {
data: dataSet
});
})
.catch( error => {
console.log('An error occurred: ' + error);
});
});
// URL Handle for Contact page
app.get('/contact', (req, res) => {
res.render('contact');
});
// URL Handle for Error page
app.all('*', (req, res) => {
res.render('error');
});
You should use axios in controller, so code should look like this:
app.get('/data', async (req, res, next) => {
try{
const { body } = await axios.get('http://localhost:1337/')
res.render('data', {
data : body
});
}catch(error){
next(error)
}
});
As You see, if there is error You should call next function with error instance and then create middleware as errorHandler to catch it.

Make redirection in express post, by react

I am using react and its router to make the redirect of my application. When I use a get instruction in my server express it works fine. But when I make a post instruction, it doesn't redirect. What I have to do?. Here is my code:
(I receive the response in the way that I expect, but after that, nothing happens)
lisaApp.post('/signup', (req, res) => {
const validationResult = validateSignupForm(req.body);
if (!validationResult.success) {
return res.status(400).json({
success: false,
message: validationResult.message,
errors: validationResult.errors
});
}
var newClient = req.body
newClient.clientemailname = newClient.userclient
newClient.client_id = uuid.v4()
delete newClient.confirmPassword
ClientApi.saveClient(newClient, function (err, usr) {
if (err) return res.status(500).send(err.message)
console.log('ready to redirect') //Here, the response has a status "0k"
res.redirect('/')
});
});
You can write your api like this:
lisaApp.post('/signup', (req, res) => {
const validationResult = validateSignupForm(req.body);
if (!validationResult.success) {
return res.status(400).json({
success: false,
message: validationResult.message,
errors: validationResult.errors
});
}
var newClient = req.body
newClient.clientemailname = newClient.userclient
newClient.client_id = uuid.v4()
delete newClient.confirmPassword
ClientApi.saveClient(newClient, function (err, usr) {
if (err) return res.status(500).send(err.message)
console.log('ready to redirect') //Here, the response has a status "0k"
return res.status(200).json({
success:true,
redirectUrl: '/'
})
});
});
And in your React file you can use this code in your POST handler to redirect using react-router.
this.history.pushState(null, res.redirectUrl);

NodeJS Express catch-all route firing after previous route

I have a basic express setup that includes the following:
app.all('/api/:controller/:id?', [ api, response.success, response.error ])
app.get('*', (req, res) => {
console.log('This should only fire when no route matched')
res.sendFile(path.resolve(pubRoot, 'index.html'))
})
In the code for the middleware on the first route the api module simply resolves a promise at this point (or rejects on 404) and then calls next, this makes it into the response middleware which looks like this:
const response = {
success: (req, res, next) => {
res.status(200).send(res.data)
},
error: (error, req, res, next) => {
const statusCode = error.statusCode || 500
res.status(statusCode).send(error.message || 'Internal Server Error')
}
}
This works fine on a successful request and I get the data (and status code 200) back. It also works on error (returning 404 and Not Found as expected), however, it continues on to the wildcard route. I get the console.log along with Error: Can't set headers after they are sent.
UPDATE: Below is the code for the api module:
const api = (req, res, next) => {
const controller = req.params.controller
const event = { body: req.body, id: req.params.id, query: req.query }
// Handle non-existent controller
if (!controllers[controller]) {
next(new HTTPError(404))
return
}
// Controller found, process
controllers[controller][req.method.toLowerCase()](event)
.then((result) => {
res.data = result
next()
})
.catch((err) => {
next(err)
})
}

How can I extend the res object in express and use the extended property in a error middleware?

Here's the response-hander.js middleware file. I have 2 function that extend the res object normal behavior. If I use these function in a normal route everything works fine, the problem shows when I try to call one of these in another middleware.
var responseHandler;
responseHandler = function(req, res, next) {
res.jsonSuccess = function(results) {
res.status(200).json({
status: "OK",
results: results
});
};
res.jsonBadRequest = function(message) {
res.status(400).json({
status: "BAD_REQUEST",
error_message: message
});
};
next();
};
module.exports = responseHandler;
Here's the error-handler.js middleware:
var errorHandler;
errorHandler = function(error, req, res, next){
if (error instanceof Error) {
res.jsonBadRequest("Error.");
}
}
module.exports = errorHandler;
The error:
TypeError: res.jsonBadRequest is not a function
Example:
This works
app.get("/my/route", function(req, res) {
return res.jsonBadRequest("Test");
});
This doesn't
app.get("/my/route", function(req, res) {
// the error middleware gets calld but dosn't find my function.
throw new Error();
});

Resources