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, }