{"record":{"id":"8bef8200dbcee7c8","repo":"DIYgod/RSSHub","slug":"invalid-column","errorCode":null,"errorMessage":"Invalid column","messagePattern":"Invalid column","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":null,"severity":"warning","filePath":"lib/routes/caixin/blog.ts","lineNumber":36,"sourceCode":"        requireConfig: false,\n        requirePuppeteer: false,\n        antiCrawler: false,\n        supportBT: false,\n        supportPodcast: false,\n        supportScihub: false,\n    },\n    name: '用户博客',\n    maintainers: ['Maecenas'],\n    handler,\n    description: '通过提取文章全文，以提供比官方源更佳的阅读体验.',\n};\n\nasync function handler(ctx) {\n    const column = ctx.req.param('column');\n    const { limit = 20 } = ctx.req.query();\n    if (column) {\n        if (!isValidHost(column)) {\n            throw new InvalidParameterError('Invalid column');\n        }\n        const link = `https://${column}.blog.caixin.com`;\n        const { data: response } = await got(link);\n        const $ = load(response);\n        const user = $('div.indexMainConri > script[type=\"text/javascript\"]')\n            .text()\n            .slice('window.user = '.length + 1)\n            .split(';', 1)[0]\n            .replaceAll(/\\s/g, '');\n        const authorId = user.match(/id:\"(\\d+)\"/)![1];\n        const authorName = user.match(/name:\"(.*?)\"/)![1];\n        const avatar = user.match(/avatar:\"(.*?)\"/)![1];\n        const introduce = user.match(/introduce:\"(.*?)\"/)![1];\n\n        const {\n            data: { data },\n        } = await got('https://blog.caixin.com/blog-api/post/posts', {\n            searchParams: {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/caixin/blog.ts#L18-L54","documentation":"Thrown by the Caixin blog route when `column` fails `isValidHost()`. The column becomes the subdomain (`https://${column}.blog.caixin.com`), so it must be a syntactically valid hostname label. Correctly uses `InvalidParameterError`. Note the `column` parameter is optional (`/blog/:column?`); when omitted the handler takes a different branch.","triggerScenarios":"Supplying a column containing characters illegal in a DNS label (e.g. spaces, slashes, uppercase with mixed punctuation, `..`, URL-encoded `%2F`), or an empty string after the colon.","commonSituations":"Pasting the full blog URL instead of just the slug (e.g. `https://zhangwuchang.blog.caixin.com` instead of `zhangwuchang`), or including a trailing path segment.","solutions":["Pass only the blog slug, e.g. `/caixin/blog/zhangwuchang`.","Strip protocol, `.blog.caixin.com`, and any path before submitting.","If omitting entirely, use `/caixin/blog` to hit the no-column branch."],"exampleFix":"// before\n/caixin/blog/https://zhangwuchang.blog.caixin.com\n// after\n/caixin/blog/zhangwuchang","handlingStrategy":"type-guard","validationCode":"import { isValidHost } from '@/utils/valid-host';\nif (column && !isValidHost(column)) {\n    // reject before building the URL\n    throw new Error(`'${column}' is not a valid blog slug / hostname label`);\n}","typeGuard":"function isBlogSlug(v: string): boolean {\n    // DNS-label-ish: lowercase, no protocol, no dots, no slashes\n    return /^[a-z0-9-]+$/.test(v);\n}","tryCatchPattern":null,"preventionTips":["Pass only the bare slug, never the full URL.","Strip `https://`, the `.blog.caixin.com` suffix, and any path before submitting.","Omit the param entirely to hit the default blog listing branch."],"tags":["validation","user-input","hostname-validation","subdomain"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}