Express middleware for blocking and throttling inspired by rack-attack
npm install express-attacksh
$ yarn install express-attack
`Usage
`js
const express = require('express')
const expressAttack = require('express-attack')
const requestIp = require('request-ip')
const app = express()function localReq(req) {
const clientIp = requestIp.getClientIp(req)
return clientIp === '127.0.0.1' || clientIp === '::1'
}
const BAD_BOTS = ['bad-bot', 'evil-bot']
function badBot(req) {
const userAgent = req.headers['user-agent'] || 'unknown'
const found = BAD_BOTS.find(function(badBot) {
return userAgent.indexOf(badBot) >= 0
})
return !!found
}
app.use(
expressAttack({
safelist: [localReq],
blocklist: [badBot]
})
)
app.get('/foo', function(req, res, next) {
res.json({ msg: 'bar' })
})
app.listen(3000, function() {
console.log('The server is running at http://localhost:3000')
})
`Throttling
GCRA is used for throttling. Default store is memoryStore, you can create your own store.`js
// If I want to allow 2 request per second and at most 6 requests simultaneously, then:
// emissionInterval = period / rate => 1000 milliseconds / 2 reqs => 500
// burst => 6function throttleByIp(req) {
const clientIp = requestIp.getClientIp(req)
return {
key: clientIp
burst 6,
emissionInterval: 500
}
}
app.use(
expressAttack({
throttles: [throttleByIp]
})
)
`$3
Create an object with below methods:
get(key): retrun value according to key, if key doesn't exsits return undefined.
set(key, timestamp, period): assign timestamp to key, and expire the key after period milliseconds.
`js
function dummyStore() {
const store = {}
const get = async function(key) {
return store[key]
}
const set = async function(key, timestamp, period) {
store[key] = timestamp
} return {
get,
set
}
}
app.use(
expressAttack({
throttles: [throttleByIp],
store: dummyStore()
})
)
`Customizing responses
`js
// do what ever you want with response.
const blocklistedResponse = (req, res) => {
return res.status(503).send('Service Unavailable')
}const throttledResponse = (req, res) => {
return res.status(503).send('Service Unavailable')
}
app.use(
expressAttack({
blocklistedResponse
throttledResponse
})
)
`Options
* safelist: array of safe request functions, if one of the fucntion return true, ths request is allowed to go.
* blocklist: array of block request functions, if one of the function reutrn true, the request is blocked.
* throttles: array of throttle functions, check Throttling for detail.
* safelistedResponse(req, res, next): custom your response when request is mark as safelisted.
* blocklistedResponse(req, res): custom your response when request is mark as blocklisted.
* throttledResponse(req, res): custom your response when request is mark as throttled.
* normalResponse(req, res, next): custom your response when request not in above situation.
* errorResponse(req, res, next, error): custom your response when exception raise during check request phase.
* store`: check Custom your store for detail.