Unobtrusive middle-ware for Expres.js to inspect request body - express

Does there exist a thirdparty middleware or a way to create such middleware for Express.js that allows for intercepting all requests and inspecting the request's body content without affecting subsequent middleware such as bodyParser or route endpoints which may rely on the raw body such as express-http-proxy?
From what I can tell bodyParser itself seems to work in a somewhat obtrusive way that does not allow a route to override the default parsing behavior. The express documentation describes how request.body is filled in by middleware such as bodyParser. This behavior of bodyParser makes sense from simplicity and performance perspective but doesn't make it a great candidate for creating middleware which needs to inspect the contents of a request and let the remaining portion of the app working without modification. This is especially true seeing that depending on the parsing middleware the results may be in entirely different formats. After some digging I'm left wondering if it's generally possible to pull this off with express or perhaps once you read the request body you eliminate the ability to make use of further middleware such as bodyParser or express-http-proxy which expect to access the body directly.
Possibly related:
express req.pipe() does not work

You could always use the raw-body package with express middleware like so:
var getRawBody = require('raw-body');
var typer = require('media-typer');
app.use(function (req, res, next) {
getRawBody(req, {
length: req.headers['content-length'],
limit: '1mb',
encoding: typer.parse(req.headers['content-type']).parameters.charset
}, function (err, string) {
if (err) return next(err)
req.text = string
next()
})
})
If your only concern is performance, I wouldn't worry too much about body-parser as it's unlikely to have a massive performance impact. If you can, I'd suggest you just use body-parser with a typical express middleware app.use(..) to inspect the request body.

Related

How to secure an endpoint

I have an endpoint written in expressjs
router.post("/mkBet", async (req, res) => {
console.log(req.body)
const betToPush = new Bet({
addr: req.body.address,
betAmount: req.body.amount,
outcome: req.body.didWin,
timePlaced: Math.round(+new Date()/1000)
})
try {
const newBet = await betToPush.save()
res.status(201).json(newBet)
} catch(err) {
res.status(400).json({message: err.message})
}})
And I am trying to make it so that it can only be called when an action is performed on the frontend. So users cannot call it with custom arguments to make it so the outcome is always true. What would be the best way to achieve this?
It is not possible to securely tell what client sent the request. In other words, a request from your client and a different one can be identical in general.
Talking about unmodified browsers (as opposed to non-browser tools like Postman), you can tell the origin of the request (~the url loaded in the browser when the request was sent) with some confidence from the Origin and Referer request headers. However, your backend needs authentication and authorization anyway.
With the latter two in place, ie. with proper security implemented on the server-side, it doesn't matter anymore what client sends the requests.

How to handle backend auth with express as reverse proxy api

I am using express the first time in a project as a kind of reverse proxy in between my frontend and backend. The backend authentication is cookie based.
First I was using http-proxy-middleware to make my requests. This works fine and the cookie gets passed no problem.
The problem is that I want to decouple the front and backend as the api isn't very usable right now (for example 3 requests necessary to get data for one view). So instead of making requests directly I want to have my express server handle the heavy lifting in the background.
Currently I am using axios for the requests and pass the cookie through with the request and the new one back with the response. This works fine but feels very hacky and error prone. For example I have to split the returned setcookie string in a very weird way.
app.get('/api/myrequest', (req, res) => {
axios.get('backendserver/url', {
headers: {
Cookie: req.cookies['auth'],
},
responseType: 'json',
})
.then((response) => {
let tempCookie = response.headers['set-cookie'][0];
tempCookie = tempCookie.split(';')[0];
tempCookie = tempCookie.split('=');
res.cookie(tempCookie[0], tempCookie[1]);
res.send(response.data);
})
});
I suppose there is a much better way to handle this. I was looking at things like passportjs but am not sure if it fits this special use case as the auth isn't handled by express itself.
Maybe someone can point me in the right direction?

Using Express and Body-Parser in a Google Cloud Function (NOT Firebase Cloud Function)

I am trying to get my head around using GCF and Express together. All of the examples I have found give good info about Firebase CF but not straight up GCF.
Specifically, I need to use body-parser to get at some POSTed body info that is being sent via a content-type of 'x-www-form-urlencoded' rather than 'application/json'. I can see the data if I console.log the req.rawBody but haven't found a clean way to get at the body parts.
I found this article: https://mhaligowski.github.io/blog/2017/05/15/serving-functions-express.html but to me it is just a couple of code snippets that really isn't clear on how things actually hang together.
You can require body-parser and as long as you send the Content-Type: application/json header, it will parse as JSON automatically:
const bodyParser = require('body-parser');
exports.acceptJson = (req, res) => {
console.log(req.body);
res.status(200);
};

ExpressJS Middleware Composition

I'm working on a project which has a quite simple endpoint:
app.get('/transactions',
listTransactions(connectionPool),
addUser(connectionPool),
sendTransactions);
We get a list of MySQL rows, merge user-data into the response, and send it back to user. My question is, is there a "commonly accepted" place to store the response of listTransactions (in this case)? Do I store it on the req object?
Here's my take. I think you're abusing middleware in this case. The middleware is better at decoding, authenticating, etc. I think your example has reached the point where it would make a lot of sense to wrap these things in a function like so.
app.get('/transactions', function(req, res, next){
var transactionPromise = listTransactions(connectionPool)
.then(function(transactions){
return listTransactions(transactions, connectionPool);
})
.then(function(listedTransactions){
return addUser(connectionPool);
})
.then(function(addUserResponse){
res.send(addUserResponse);
});
transactionPromise.catch(function(error){
res.status(500).send("Something went wrong: " + error.toString());
}
}
I use promises here, but this could easily be done with something like async as well. This approach does a few things:
Allows you to handle errors at the router level, rather than inside each function. If you think about it, should a function called listTransactions really know how to respond to a server request?
In combination with the first point, it allows for better reusability by removing the dependency on the (req, res, next) signature.
Testability. Now you can test all the individual pieces without a reliance on the previous middleware, or a specific req format.
My 2ยข. Hope it helps!

Can I use multiparty for a single route in my express app?

I have an Express 3 app that uses bodyParser for most routes. (Most routes only accept multipart.) I have a single route that is going to be parsing files up to 1GB in size which bodyParser can't seem to handle. I would like to use multiparty for only this route so I don't have to rewrite the whole API. Is this possible?
You can supply middleware to a single route by doing this:
var multipartyMiddleware = function (req,res,next){
//put your code to parse multipart here and call "next" when done
}
app.post('/this/is/a/single/route', multipartyMiddleware, function(req,res){
//do normal business logic in this route and send the response
})
If you need to bypass the multipart parsing in the old bodyParser in express 3 you can replace this:
app.use(express.bodyParser())
with this:
app.use(express.json())
app.use(express.urlencoded())
This works because the source of the bodyParser middleware reveals that it is just a combo of three middleware parsers: multipart, json, and urlencoded.
see the connect 2.X source here: https://github.com/senchalabs/connect/blob/2.x/lib/middleware/bodyParser.js#L54