Custom middleware for express routes - javascript

I actually implemented a custom middleware in an expressJs application. I aim for modifying the request object before sending it back. It works and the result is exactly what i was expecting, but i am not sure if this is the correct way to do so. I am kind of afraid, that manipulating the reqeust object is not the correct way to do this.
Here is the code:
expressApp.get('/apps/:id', isAuthenticated, appLinks(dbController), async (req, res) => {
res.send(req.__appLink)
})
app-links.ts:
export const appLinks: MiddlewareWrapper = (dbController: DatabaseHandler) => async (req: Request, res: Response, next: NextFunction) => {
dbResult = modifyMyDatabaseResult(await dbController.getApps());
req.__appLink = dbResult
next()
}
As you can see, in my route i send req.__appLink which was set inside the middleware. It this the correct way to do such things?

This is good! Nothing is wrong with modifying the req object.

Yes this is fine. But for better presentation you can save the result of req._appLink in a variable and pass it to res object.

Related

How to create an express update route with multiple parameters

I want to update an attribute within a JSON object using fetch PUT. I've created a put function taking in 2 URL parameters
app.put('/trustRoutes/:id/:item', (req, res){
I am able to update the data with a single parameter but since I only want to change one value inside that object, calling put will replace the whole object with my new body.
below is what I've tried.
app.put('/trustRoutes/:id/:item', (req, res) => {
readFile(data => {
const userId = req.params['id/item'];
// have also tried const userId = req.params.id.item
data[userId] = req.body;
//write data back to file
I looked around at other examples but couldn't find any that were updating data instead of GET. If there is one I missed please let me know.
PUT requests are great for completely overwriting a resource, and is idempotent. This answer does a good job explaining idempotency. For updating a resource partially, a PATCH request is a better choice.
app.patch('/trustRoutes/:id/:item', (req, res) => {
readFile(data => {
data[userId] = req.params[id];
data[item] = req.params[item];
// A get request for this resource would now show both of the updated values
// Write file

express middleware after response

I've had a problem with middleware function which is launching on finish execution of main function from endpoint. Here is my middleware:
export const someMiddleware = async (
req: Request,
res: Response,
next: NextFunction
) => {
res.on("finish", () => {
//here
})
next();
}
I am having trouble getting the data that was sent to the client from the request handled by this middleware, can anyone tell me how to get the response body that is sent to the client inside the on () callback?
Thanks for any help!
This is quite painful with Express. One way to handle this is to override the send and write functions, and capture the output this way.
It's not impossible to do this, other middlewares like a gzip middleware would do this too.
A frustration with this limitation has eventually lead me to write my own framework, so I get where you are coming from.

How to share information between Express middleware and endpoints?

Lots of middleware comes with factories, that takes an options object. Among the options is usually a function that needs to provide some necessary information to the middleware. As an example, take a look at express-preconditions:
app.use(preconditions({
stateAsync: async (req) => { // Fetch the date the resource was last modified. }}
});
This is a neat pattern, but I find it gets complicated when the same information is needed in multiple places. For instance, let's say I've got a database table that contains both the information about the resource that the response is supposed to contain, and the last modified date. In other words, the same information is needed in both the middleware and the endpoint itself. I end up with code similar to this:
//The middleware
app.use(preconditions({
stateAsync: async (req) => {
const data = await fetchFromDb(req.param("id"));
return {
lastModified: data.lastModified
};
})
//The endpoint
app.use("path", (req, res, next) => {
const data = await fetchFromDb(req.param("id"));
res.send(data);
});
I'm hitting the database twice just because I need the same info in different places. I could off course just fetch it once, or store it somewhere on the request object. But that feels a bit like a hack. Another solution would be to have some kind of caching mechanism in fetchFromDb, but that feels a bit overcomplicated.
In my experience, this is a quite common problem when building stuff with Express. What is the recommended way to deal with situations like this?
You can pass data between middlewares with res.locals:
app.get('/yourEndPoint', (req, res, next) => {
const data = // fetch your datas;
res.locals.lastModified = data.lastModified;
next();
}, (req, res) => {
const lastModified = res.locals.lastModified;
// do whatever you need to do
});

How to make server side requests (API) with a catch-all React app?

I'm relatively new to react/redux and I've encountered a problem.
Say for example I want to search for an item.
export default function getSearchItems(itemName) {
return dispatch => {
// Show that it is requesting, will be updated after.
dispatch(requestItems(itemName));
// URL todo.
return fetch('/search')
.then(
response => response.json(),
error => dispatch(requestItemsFailure(itemName))
).then(
json => dispatch(requestItemsSuccess(itemName, json))
);
};
}
Here I've made a request to the url /search. But because I've opted to use React Router v4's client side routing, I did this on the server-side.
// Manage Routes
app.get('/*', function (req, res) {
res.sendFile(path.resolve(__dirname + '/../build/index.html'));
});
// Search Grab data
app.get('/search', function (req, res) {
console.log('hit');
res.status(200).json(
{item:"test"}
);
});
Since I used a "catch-all" method as described here in this stackoverflow post, I can no longer do something like "/login" and have it go to the correct component immediately.
How can I make the two work together properly?

Express callback needs more parameters than (req, res)

For an express app I'm working on, my callbacks can only have (req, res, next, err) passed into them.
This is what I had that worked.
function listEvents(auth, req, res, email, authURL = ""){
...
var calendar = google.calendar('v3');
calendar.events.list({
auth: auth, ... });
}
But my function definition must look like this:
function listEvents(req, res){...}
I can retrieve email and authURL from within the API call, but I don't know how to pass in auth which is created in the method of which listEvents is a callback. I am trying something like this:
oauth2Client.credentials = acctoken;
var output = {
auth: oauth2Client,
data: callback(req, res)
};
res.send(output);
But I need to get the oauth2Client into the callback itself. This would just let you send both in the response to the chain of callbacks.
I would appreciate any help. Thank you so much.
oauth2Client.credentials = acctoken;
var output = {
auth: oauth2Client,
data: callback(req, res)
};
res.send(output);
With reference to the above code block you are assigning auth as oauth2Client.
You can append oauth2Client in your req object and use it in your callback function.
So I've talked to multiple people and apparently my issue is that I was not thinking of the request object properly. As the above answer states, one can append fields to the body of the request. I have only ever prepared requests in postman up until this point - so this is very useful for me to know. This is almost exactly what I was looking for; I needed a way to give information to a callback without passing it in as a parameter.

Categories

Resources