{"record":{"id":"f6c411c631e0b2bc","repo":"siyuan-note/siyuan","slug":"unsupported-method-s","errorCode":null,"errorMessage":"unsupported method: %s","messagePattern":"unsupported method: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/httprequest.go","lineNumber":143,"sourceCode":"\n\treturn statusCode, contentType, truncateRunes(string(respBody), maxHTTPRequestChars), nil\n}\n\n// sendByMethod 按 method 分发请求，统一走 NewBrowserRequest 返回的 *req.Request。\nfunc sendByMethod(request *req.Request, method, rawURL string) (*req.Response, error) {\n\tswitch method {\n\tcase \"GET\", \"\":\n\t\treturn request.Get(rawURL)\n\tcase \"POST\":\n\t\treturn request.Post(rawURL)\n\tcase \"PUT\":\n\t\treturn request.Put(rawURL)\n\tcase \"DELETE\":\n\t\treturn request.Delete(rawURL)\n\tcase \"PATCH\":\n\t\treturn request.Patch(rawURL)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported method: %s\", method)\n\t}\n}\n\n// isTextContentType 判断 Content-Type 是否为可直接展示给智能体的文本类响应。\n// 覆盖 text/*、application/json、application/xml、application/*+json 等。\nfunc isTextContentType(contentType string) bool {\n\tct := strings.ToLower(strings.TrimSpace(strings.SplitN(contentType, \";\", 2)[0]))\n\tif ct == \"\" {\n\t\treturn false\n\t}\n\tif strings.HasPrefix(ct, \"text/\") {\n\t\treturn true\n\t}\n\tswitch ct {\n\tcase \"application/json\", \"application/xml\":\n\t\treturn true\n\t}\n\tif strings.HasPrefix(ct, \"application/\") && (strings.HasSuffix(ct, \"+json\") || strings.HasSuffix(ct, \"+xml\")) {","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/util/httprequest.go#L125-L161","documentation":"Raised by sendByMethod when the HTTP method is not one of GET, POST, PUT, DELETE, PATCH (empty string defaults to GET). The method is uppercased and trimmed in HTTPRequest before dispatch, so any other verb (HEAD, OPTIONS, CONNECT, TRACE) or typo falls through to the default case and returns this fmt.Errorf.","triggerScenarios":"An agent or caller passes method=\"HEAD\", \"OPTIONS\", \"CONNECT\", \"TRACE\", a lowercase variant that still isn't in the allow-list after ToUpper, or a misspelling like \"POTS\". The MCP http_request tool forwards args[\"action\"] verbatim, so a malformed action reaches sendByMethod.","commonSituations":"An LLM agent invents a method string; a caller expects HEAD support for a lightweight existence check; a typo in a scripted action; integration code reusing a generic 'method' field that permits arbitrary values.","solutions":["Restrict the method to the allow-list {GET, POST, PUT, DELETE, PATCH} (empty defaults to GET) before calling HTTPRequest.","If you only need headers, use GET and ignore the body rather than HEAD.","Validate/normalize the action string in the MCP tool layer so unsupported verbs are rejected with a clearer upstream message."],"exampleFix":"// before\nutil.HTTPRequest(\"HEAD\", rawURL, headers, body)\n\n// after: whitelist the method\nallowed := map[string]bool{\"GET\": true, \"POST\": true, \"PUT\": true, \"DELETE\": true, \"PATCH\": true}\nmethod = strings.ToUpper(strings.TrimSpace(method))\nif method == \"\" {\n    method = \"GET\"\n}\nif !allowed[method] {\n    return fmt.Errorf(\"unsupported method: %s\", method)\n}\nutil.HTTPRequest(method, rawURL, headers, body)","handlingStrategy":"validation","validationCode":"allowed := map[string]bool{\"GET\": true, \"POST\": true, \"PUT\": true, \"DELETE\": true, \"PATCH\": true}\nmethod = strings.ToUpper(strings.TrimSpace(method))\nif method == \"\" {\n    method = \"GET\"\n}\nif !allowed[method] {\n    return fmt.Errorf(\"unsupported method: %s\", method)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whitelist methods at the MCP/tool boundary before forwarding action to HTTPRequest.","Treat empty method as GET explicitly.","Do not surface arbitrary HTTP verbs to LLM agents without validation."],"tags":["http","validation","mcp","agent-tool"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}