Cleaner way to write api route handlers in NextJS - express

Currently most of the api route handlers are in the following shape(api/test.js):
export default function handler(req, res) {
if (req.method === 'POST') {
// Process a POST request
} else {
// Handle any other HTTP method
}
}
where we constantly compare req.method with ifs
Is there a way to write it similar to ExpressJS:
app.get(...)

import nextConnect from 'next-connect';
const handler = nextConnect();
//handler.use(middleware);
handler.get(async (req, res) => {
...your code
})
...
handler.post(async (req, res) => {
...your code
})
...
So in theory you can have /api/product where you have .get .post .delete (etc) in 1 api route
Clean solution (/api/product.js)
const handler = async (req, res) => {
try {
}
catch(e){
}
}

Related

ExpressJS mixing middleware arguments with custom arguments

I'm writing a function to create errors and I want to use express' next() function. I have seen working examples using a nested function but my code isn't reached. This is what I have:
/middleware.js
import { errorCreator } from './helper.js';
const middleWare = async (req, res, next) => {
if (!req.headers.header) {
errorCreator('Not Authorized', 401);
}
// More async code here
};
and
/helpers.js
export const errorCreator = (message, statusCode) => {
// this is reached <-----------------
return (req, res, next) => {
// this is not reached <---------------
const error = new Error(message);
error.status = statusCode;
throw error;
};
};
Why do I not reach the nested function?

node axios as middleware

I am trying to construct a middleware and then use it within the app.get route.
I know it's looks very "pioneer" but i am learning.... How can io get it to work?
const BooksMiddle = async (req, res, next) => {
axios
.get(`https://www.googleapis.com/books/v1/volumes/? q=${term}&keyes&key=${process.env.GBOOKSKEY}`)
.then((result) => {
const data = result.data;
const books = data.items;
return books;
});
next();
}
module.exports = textMiddle;
app.get("/", textMiddle, (req, res, next) => {
res.render('index');
});
If the point of this middleware is to get some book data and make that available for your template rendering, then you can put that data into res.locals where templates called from res.render() will automatically look for data:
const bookMiddle = async (req, res, next) => {
axios
.get(`https://www.googleapis.com/books/v1/volumes/?q=${term}&keyes&key=${process.env.GBOOKSKEY}`)
.then((result) => {
res.locals.books = result.data.items;
next();
}).catch(next);
}
module.exports = bookMiddle;
And, then after you import bookMiddle, you can use it like this:
app.get("/", bookMiddle, (req, res, next) => {
res.render('index');
});
If you refer to the books data structure in your template, the template engine will look in res.locals.books for that data (where the middleware puts the data).

How to use different middlewares for get and post methods in Next js api?

With express we can use different middlewares for get and post requests,
eg.
// GET method route
app.get('/users', function (req, res) {
// handle get request
})
// POST method route
app.post('/users', auth, function (req, res) {
// handle post request
})
How do I do the same in next js.
I am totally new to next js. I might be simply missing something.
To handle different HTTP methods in an API route, you can use req.method in your request handler.
export default function handler(req, res) {
if (req.method === 'POST') {
// Process a POST request
} else {
// Handle any other HTTP method
}
}
Or you can use a package like next-connect which enables expressjs like API.
In your api file:
import nc from "next-connect";
const handler = nc()
.use(someMiddleware())
.get((req, res) => {
res.send("Hello world");
})
.post((req, res) => {
res.json({ hello: "world" });
})
.put(async (req, res) => {
res.end("async/await is also supported!");
})
.patch(async (req, res) => {
throw new Error("Throws me around! Error can be caught and handled.");
});
export default handler

Axios interceptor use express req object

I have an express route in which I send a header from the front end, in this route I'm making a GET request using axios. I created an interceptor with axios, but I would like to be able to read the req object from the activated route in order to add the header to the axios GET call.
// Example Interceptor
axios.interceptors.request.use(
config => {
// How to get req.headers from the route here?
return config;
},
error => {
return Promise.reject(error);
}
);
// Exemple GET route
router.get('/get', async (req, res, next) => {
try {
const { data } = await axios.get('https://kjhf.fsadjhfewq.....');
} catch (error) {
console.log(error)
}
res.status(200).json({});
});
Is it possible to do this?
So I think the way to do this is to use a middleware to set the headers, and pass on the axios instance
// apiSetHeader.js middleware
exports.default = (req, res, next) => {
req.CustomAxios = axios.create({
headers: { 'HeaderForTheApi': req.headers.apiHeader'}
})
next()
}
And then use that in your route
// Exemple GET route
router.get('/get', apiSetHeaderMiddleware, async (req, res, next) => {
try {
const { data } = await req.CustomAxios.get('https://kjhf.fsadjhfewq.....');
} catch (error) {
console.log(error)
}
res.status(200).json({});
});
Hope this helps!

call app.get inside response.render

How can I call another express route inside response.render. Following is my code snippet. I would like to render performance.jade when /pages/performance is requested and populate the jade with data returned from /api/notifications
module.exports = function(app){
app.get('/pages/performance', function(req, res){
res.render("performance", {results: app.get("/api/notifications", function (request, response) {return response.body;}), title: "Performance"});
});
};
/api/notifications will return json data which is then used in jade as follows:
block pageContent
for result in results
p #{result.message}
Make a function that gets the notifications and passes them to a callback. Then use that function in both routes. You can code that either as a pure function or as a connect middleware.
Pure Function
function loadNotifications(callback) {
database.getNotificiations(callback)
}
app.get('/api/notifications', function (req, res) {
loadNotifications(function (error, results) {
if (error) { return res.status(500).send(error);
res.send(results);
}
});
app.get('/pages/performance', function (req, res) {
loadNotifications(function (error, results) {
if (error) { return res.status(500).send(error);
res.render('performance', {results: results});
});
});
Middleware
function loadNotifications(req, res, next) {
database.getNotificiations(function (error, results) {
if (error) { return next(error);}
req.results = results;
next();
});
}
app.get('/api/notifications', loadNotifications, function (req, res) {
res.send(req.results);
});
app.get('/pages/performance', loadNotifications, function (req, res) {
res.render('performance', {results: req.results});
});