{"record":{"id":"164610438a1a1b23","repo":"DIYgod/RSSHub","slug":"invalid-url","errorCode":null,"errorMessage":"Invalid URL","messagePattern":"Invalid URL","errorType":"validation","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/wordpress/index.ts","lineNumber":21,"sourceCode":"import { config } from '@/config';\nimport ConfigNotFoundError from '@/errors/types/config-not-found';\nimport type { Data, Route } from '@/types';\nimport got from '@/utils/got';\nimport { parseDate } from '@/utils/parse-date';\nimport parser from '@/utils/rss-parser';\n\nimport { apiSlug, bakeFilterSearchParams, bakeFiltersWithPair, bakeUrl, fetchData, getFilterParamsForUrl, parseFilterStr } from './util';\n\nasync function handler(ctx) {\n    const { url = 'https://wordpress.org/news', filter } = ctx.req.param();\n    const limit = ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 50;\n\n    if (!config.feature.allow_user_supply_unsafe_domain) {\n        throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);\n    }\n\n    if (!/^https?:\\/\\/[^\\s#$./?].\\S*$/i.test(url)) {\n        throw new Error('Invalid URL');\n    }\n\n    const cdn = config.wordpress.cdnUrl;\n    const rootUrl = url;\n\n    const filters = parseFilterStr(filter);\n    const filtersWithPair = await bakeFiltersWithPair(filters, rootUrl);\n\n    const searchParams = bakeFilterSearchParams(filters, 'name', false);\n    const apiSearchParams = bakeFilterSearchParams(filtersWithPair, 'id', true);\n\n    apiSearchParams.append('_embed', 'true');\n    apiSearchParams.append('per_page', String(limit));\n\n    const apiUrl = bakeUrl(`${apiSlug}/posts`, rootUrl, apiSearchParams);\n    const currentUrl = bakeUrl(getFilterParamsForUrl(filtersWithPair) ?? '', rootUrl, searchParams);\n\n    try {","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/wordpress/index.ts#L3-L39","documentation":"The url parameter is validated against ^https?:\\/\\/[^\\s#$./?].\\S*$ (case-insensitive) before any fetch. It requires an http/https scheme, no whitespace/fragment/query metacharacters in the first character, and at least one more character after the scheme prefix. A non-match throws a plain Invalid URL.","triggerScenarios":"Passing a url without a scheme (example.com), with spaces, with a leading # or ? , a single-char host, or a malformed/encoded value that breaks the pattern at wordpress/index.ts:20.","commonSituations":"User forgot to URL-encode the value, passed a bare domain, or the leading char is one of the excluded set (#$./?).","solutions":["Ensure the url starts with http:// or https:// and has no spaces.","URL-encode the whole url when placing it in the route path (encodeURIComponent).","Use the documented default by omitting url, or pass a fully-qualified wordpress root."],"exampleFix":"// before\n/wordpress/wordpress.org/news\n// after\n/wordpress/https%3A%2F%2Fwordpress.org%2Fnews","handlingStrategy":"validation","validationCode":"function isValidWordpressUrl(u: string): boolean {\n    return /^https?:\\/\\/[^\\s#$./?].\\S*$/i.test(u);\n}\nif (!isValidWordpressUrl(url)) {\n    throw new InvalidParameterError('url must be a fully-qualified http(s) URL');\n}","typeGuard":"function isWordpressInvalidUrlError(e: unknown): boolean {\n    return e instanceof Error && e.message === 'Invalid URL';\n}","tryCatchPattern":"try {\n    return await wordpressHandler(ctx);\n} catch (e) {\n    if (isWordpressInvalidUrlError(e)) {\n        return ctx.json({ error: 'Invalid url parameter. Encode it with encodeURIComponent and include the scheme.' }, 400);\n    }\n    throw e;\n}","preventionTips":["Always encodeURIComponent the url before placing it in the route path.","Include the http:// or https:// scheme — the regex requires it.","Throw InvalidParameterError (not generic Error) so RSSHub returns 4xx for bad input."],"tags":["wordpress","validation","url","route-parameter"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}