| | import type { Response, NextFunction } from 'express' |
| |
|
| | import { ExtendedRequest } from '@/types' |
| | import statsd from '@/observability/lib/statsd' |
| | import { allTools } from '@/tools/lib/all-tools' |
| | import { allPlatforms } from '@/tools/lib/all-platforms' |
| | import { defaultCacheControl } from '@/frame/middleware/cache-control' |
| |
|
| | const STATSD_KEY = 'middleware.handle_invalid_querystring_values' |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | const RECOGNIZED_VALUES = { |
| | platform: allPlatforms as string[], |
| | tool: Object.keys(allTools), |
| | } |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | const RECOGNIZED_VALUES_KEYS = new Set(Object.keys(RECOGNIZED_VALUES)) |
| |
|
| | export default function handleInvalidQuerystringValues( |
| | req: ExtendedRequest, |
| | res: Response, |
| | next: NextFunction, |
| | ) { |
| | const { method, query } = req |
| | if (method === 'GET' || method === 'HEAD') { |
| | for (const [key, value] of Object.entries(query)) { |
| | if (RECOGNIZED_VALUES_KEYS.has(key)) { |
| | const validValues = RECOGNIZED_VALUES[key as keyof typeof RECOGNIZED_VALUES] |
| | const queryValue = query[key] |
| | const values = Array.isArray(queryValue) ? queryValue : [queryValue] |
| | if (values.some((val) => typeof val === 'string' && !validValues.includes(val))) { |
| | if (process.env.NODE_ENV === 'development') { |
| | console.warn( |
| | 'Warning! Invalid query string *value* detected. %O is not one of %O', |
| | query[key], |
| | validValues, |
| | ) |
| | } |
| | |
| | |
| | const sp = new URLSearchParams(query as any) |
| | sp.delete(key) |
| |
|
| | defaultCacheControl(res) |
| | let newURL = req.path |
| | if (sp.toString()) newURL += `?${sp}` |
| | res.redirect(302, newURL) |
| |
|
| | const tags = ['response:302', `url:${req.url}`, `path:${req.path}`, `key:${key}`] |
| | statsd.increment(STATSD_KEY, 1, tags) |
| |
|
| | return |
| | } |
| | } |
| |
|
| | |
| | if (value instanceof Object && !Array.isArray(value)) { |
| | const message = `Invalid query string key (${key})` |
| | defaultCacheControl(res) |
| | res.status(400).send(message) |
| |
|
| | const tags = ['response:400', `path:${req.path}`, `key:${key}`] |
| | statsd.increment(STATSD_KEY, 1, tags) |
| | return |
| | } |
| | } |
| | } |
| |
|
| | return next() |
| | } |
| |
|