{"record":{"id":"cd1b99004ac31da1","repo":"chenhg5/cc-connect","slug":"post-only","errorCode":null,"errorMessage":"POST only","messagePattern":"POST only","errorType":"http","errorClass":null,"httpStatus":405,"severity":"warning","filePath":"core/api.go","lineNumber":205,"sourceCode":"\t\t\tslog.Debug(\"api server close failed\", \"error\", err)\n\t\t}\n\t}\n\tif err := os.Remove(s.socketPath); err != nil && !os.IsNotExist(err) {\n\t\tslog.Debug(\"api server remove socket failed\", \"error\", err)\n\t}\n}\n\nfunc apiJSON(w http.ResponseWriter, status int, v any) {\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tw.WriteHeader(status)\n\tif err := json.NewEncoder(w).Encode(v); err != nil {\n\t\tslog.Error(\"api server: write JSON failed\", \"error\", err)\n\t}\n}\n\nfunc (s *APIServer) handleSend(w http.ResponseWriter, r *http.Request) {\n\tif r.Method != http.MethodPost {\n\t\thttp.Error(w, \"POST only\", http.StatusMethodNotAllowed)\n\t\treturn\n\t}\n\n\t// Attachments travel base64-encoded inside the JSON body (~4/3 expansion)\n\t// plus the request envelope, so size the reader to fit one max-size\n\t// attachment with overhead to spare. The previous hard-coded 52 MB cap was\n\t// smaller than a single 50 MB attachment after base64 encoding and would\n\t// reject valid sends; deriving it from maxAttachmentBytes keeps the body\n\t// limit in step with the configured attachment limit.\n\tvar req SendRequest\n\tif err := json.NewDecoder(io.LimitReader(r.Body, s.sendBodyLimit())).Decode(&req); err != nil {\n\t\thttp.Error(w, \"invalid JSON: \"+err.Error(), http.StatusBadRequest)\n\t\treturn\n\t}\n\tif req.Message == \"\" && strings.TrimSpace(req.TTSText) == \"\" && len(req.Images) == 0 && len(req.Files) == 0 && len(req.Audios) == 0 && len(req.Videos) == 0 {\n\t\thttp.Error(w, \"message, tts_text, or attachment is required\", http.StatusBadRequest)\n\t\treturn\n\t}","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/api.go#L187-L223","documentation":"The cc-connect local HTTP API's /send endpoint only accepts POST requests; any other method (GET, PUT, DELETE) is rejected with 405 and the body \"POST only\". Sending a message requires a request body, so GET-style access is not supported by design.","triggerScenarios":"Calling the API server's send route with r.Method != http.MethodPost — e.g. opening the URL in a browser (GET) or using a client that defaults to GET.","commonSituations":"Testing the endpoint in a browser address bar, curl without -X POST and without -d, a script using http.Get on the send path, health-check probes configured with GET against the send route.","solutions":["Send the request with POST: `curl -X POST http://127.0.0.1:<port>/send -d '{...}'`.","In client code use http.NewRequest(\"POST\", url, body) instead of http.Get.","If a monitoring probe hit the route, point the probe at a GET-safe health endpoint instead.","Check for redirects: a 301/302 from http to https can downgrade POST to GET — use the correct scheme directly."],"exampleFix":"// before\nresp, err := http.Get(\"http://127.0.0.1:8080/send\")\n// after\nresp, err := http.Post(\"http://127.0.0.1:8080/send\", \"application/json\",\n    strings.NewReader(`{\"message\":\"hi\"}`))","handlingStrategy":"validation","validationCode":"if req.Method != http.MethodPost {\n    panic(\"/send requires POST\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.Do(req)\nif resp.StatusCode == http.StatusMethodNotAllowed {\n    // fix client to use POST and retry once\n}","preventionTips":["Use POST for every /send call; never http.Get","Point GET-based health probes at a health endpoint, not /send","Beware redirects downgrading POST to GET — call the final URL directly"],"tags":["http","api","method-not-allowed"],"backgroundTag":"unexpected-http-status","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}