{"record":{"id":"e09d16b6f9705fee","repo":"mihomo-party-org/clash-party","slug":"request-headers-too-large","errorCode":null,"errorMessage":"Request headers too large","messagePattern":"Request headers too large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/resolve/plugin/http-client.ts","lineNumber":32,"sourceCode":"  // 走代理时由代理负责解析/连接目标，本地 SSRF guarded lookup 不再适用（安全保证降级）\n  proxy?: { host: string; port: number }\n}\n\nexport interface PluginResponse {\n  status: number\n  headers: http.IncomingHttpHeaders\n  body: string\n}\n\nconst FORBIDDEN_HEADERS = new Set(['host', 'content-length', 'connection', 'transfer-encoding'])\nconst MAX_HEADERS = 32\nconst MAX_HEADER_NAME_LEN = 128\nconst MAX_HEADER_VALUE_LEN = 4096\nconst MAX_HEADER_BYTES = 16 * 1024\n\nfunction validateHeaders(input: Record<string, string>): Record<string, string> {\n  const entries = Object.entries(input)\n  if (entries.length > MAX_HEADERS) throw new Error('Request headers too large')\n\n  const headers: Record<string, string> = {}\n  let total = 0\n  for (const [k, v] of entries) {\n    if (FORBIDDEN_HEADERS.has(k.toLowerCase())) {\n      throw new Error(`Forbidden header: ${k}`)\n    }\n    const nameBytes = Buffer.byteLength(k, 'utf-8')\n    const valueBytes = Buffer.byteLength(v, 'utf-8')\n    if (nameBytes > MAX_HEADER_NAME_LEN || valueBytes > MAX_HEADER_VALUE_LEN) {\n      throw new Error('Request headers too large')\n    }\n    total += nameBytes + valueBytes\n    headers[k] = v\n  }\n  if (total > MAX_HEADER_BYTES) throw new Error('Request headers too large')\n  return headers\n}","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/main/resolve/plugin/http-client.ts#L14-L50","documentation":"validateHeaders() enforces limits before sending: at most MAX_HEADERS entries per request. Exceeding the count throws 'Request headers too large' — a guard keeping outgoing requests small and predictable for the gateway/proxy chain.","triggerScenarios":"Calling the HTTP client (via requestOnce) with a headers record containing more than MAX_HEADERS entries (e.g. >16 headers).","commonSituations":"Programmatically forwarding all incoming request headers, merging default headers repeatedly so they accumulate, or signing code that adds many metadata headers.","solutions":["Trim the header set to only what the gateway requires.","Deduplicate/merge headers before calling — many come from default header sets.","Move bulk data into the request body instead of headers."],"exampleFix":"// before\nheaders: { ...incomingHeaders, ...defaultHeaders } // may exceed MAX_HEADERS\n// after\nconst allowed = ['content-type', 'accept', 'user-agent']\nconst headers = Object.fromEntries(\n  Object.entries(incomingHeaders).filter(([k]) => allowed.includes(k.toLowerCase()))\n)","handlingStrategy":"validation","validationCode":"const MAX_HEADERS = 16\nif (Object.keys(headers).length > MAX_HEADERS) {\n  throw new Error(`Too many headers: ${Object.keys(headers).length} > ${MAX_HEADERS}`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await request(url, { headers })\n} catch (e) {\n  if ((e as Error).message === 'Request headers too large') {\n    // rebuild a minimal header set and retry once\n  } else throw e\n}","preventionTips":["Whitelist only the headers you need instead of forwarding everything.","Avoid repeated spread-merging of default header objects that accumulate entries.","Centralize header construction so limits are checked in one place."],"tags":["http","headers","validation"],"backgroundTag":"request-headers-too-large","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}