{"record":{"id":"a085d1e91417ba27","repo":"DIYgod/RSSHub","slug":"invalid-language-a085d1","errorCode":null,"errorMessage":"Invalid language","messagePattern":"Invalid language","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":503,"severity":"error","filePath":"lib/routes/pornhub/users.ts","lineNumber":34,"sourceCode":"        requireConfig: false,\n        requirePuppeteer: false,\n        antiCrawler: false,\n        supportBT: false,\n        supportPodcast: false,\n        supportScihub: false,\n        nsfw: true,\n    },\n    radar: getRadarDomin('/users/:username'),\n    name: 'Users',\n    maintainers: ['I2IMk', 'queensferryme'],\n    handler,\n};\n\nasync function handler(ctx): Promise<Data> {\n    const { language = 'www', username, img } = ctx.req.param();\n    const link = `https://${language}.pornhub.com/users/${username}/videos`;\n    if (!isValidHost(language)) {\n        throw new InvalidParameterError('Invalid language');\n    }\n\n    const { data: response } = await got(link, { headers });\n    const $ = load(response);\n    const showImages = img === 'img=1';\n    const items = $('.videoUList .videoBox')\n        .toArray()\n        .map((e) => parseItems($(e), showImages));\n\n    return {\n        title: $('.profileUserName a').text(),\n        description: $('.aboutMeText').text().trim(),\n        link,\n        image: $('#getAvatar').attr('src'),\n        language: $('html').attr('lang') as any,\n        allowEmpty: true,\n        item: items,\n    };","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/pornhub/users.ts#L16-L52","documentation":"Identical pattern to pornstar.ts: the /pornhub/users/:username route injects the `:language` segment directly into the host portion of `https://${language}.pornhub.com/users/...`. `isValidHost` rejects anything that is not a known Pornhub locale subdomain before the request is sent. This protects against both typos and host-header injection through a path parameter.","triggerScenarios":"A request such as /pornhub/users/foo/xyz where `xyz` is not in the Pornhub subdomain allowlist. The check runs synchronously right after parameter destructuring, before `got(link)`.","commonSituations":"Wrong locale token supplied (e.g. `en` instead of `www`), user assumes ISO language codes work, or the segment is omitted in a way the router fills with garbage.","solutions":["Supply a recognized Pornhub subdomain token (`www`, `cn`, `jp`, …) as the language segment.","Drop the segment to fall back to the default `'www'`.","Validate via `isValidHost` before issuing the request."],"exampleFix":"// before\n/rsshub/pornhub/users/foo/en\n// after\n/rsshub/pornhub/users/foo/www","handlingStrategy":"validation","validationCode":"import isValidHost from '@/utils/valid-host';\nconst language = ctx.req.param('language') ?? 'www';\nif (!isValidHost(language)) {\n    return ctx.body(`Unsupported language '${language}'.`, 400);\n}","typeGuard":"const isPornhubLocale = (v: unknown): v is string => typeof v === 'string' && isValidHost(v);","tryCatchPattern":null,"preventionTips":["Treat the language segment as an internal subdomain token, not a free-form locale string.","Document the accepted values inline with the route so callers do not guess.","Prefer omitting the segment to rely on the 'www' default."],"tags":["invalid-parameter","route-validation","host-check"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}