honojs-middleware/packages/ua-blocker/src/index.ts

50 lines
1.5 KiB
TypeScript
Raw Normal View History

import { createMiddleware } from 'hono/factory'
import { escape } from './escape'
/**
* Converts a list of strings into a regular expression group.
* Each string in the list is escaped using `RegExp.escape()` or polyfill
* and then joined by a '|' (OR) operator. The entire result is wrapped in
* parentheses to form a capturing group.
*
* @param list An array of strings to include in the regex.
* @returns A RegExp matching any of the strings in the capture group.
*/
function listToRegex(list: string[]): RegExp | undefined {
let regex
if (list.length > 0) {
const formatted = list.map((item) => escape(item.toUpperCase())).join('|')
regex = new RegExp(`(${formatted})`)
}
return regex
}
/**
*
* @param params - `blocklist`: An array of user-agents to block, or a RegExp to match against. NOTE: If passing a RegExp, it should match on UPPERCASE User Agents.
* @returns the Hono middleware to block requests based on User-Agent header.
*/
export function uaBlocker(params = { blocklist: [] as string[] | RegExp }) {
const regex = Array.isArray(params.blocklist) ? listToRegex(params.blocklist) : params.blocklist
return createMiddleware(async (c, next) => {
const userAgent = c.req.header('User-Agent')?.toUpperCase()
if (userAgent && regex && userAgent.match(regex)) {
return c.text('Forbidden', 403)
}
await next()
return
})
}
export default uaBlocker
// Export for testing purposes
export const __test = {
listToRegex,
}