chenhg5/cc-connect · warning

POST only

Error message

POST only

What it means

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.

Source

Thrown at core/api.go:205

			slog.Debug("api server close failed", "error", err)
		}
	}
	if err := os.Remove(s.socketPath); err != nil && !os.IsNotExist(err) {
		slog.Debug("api server remove socket failed", "error", err)
	}
}

func apiJSON(w http.ResponseWriter, status int, v any) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	if err := json.NewEncoder(w).Encode(v); err != nil {
		slog.Error("api server: write JSON failed", "error", err)
	}
}

func (s *APIServer) handleSend(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	// Attachments travel base64-encoded inside the JSON body (~4/3 expansion)
	// plus the request envelope, so size the reader to fit one max-size
	// attachment with overhead to spare. The previous hard-coded 52 MB cap was
	// smaller than a single 50 MB attachment after base64 encoding and would
	// reject valid sends; deriving it from maxAttachmentBytes keeps the body
	// limit in step with the configured attachment limit.
	var req SendRequest
	if err := json.NewDecoder(io.LimitReader(r.Body, s.sendBodyLimit())).Decode(&req); err != nil {
		http.Error(w, "invalid JSON: "+err.Error(), http.StatusBadRequest)
		return
	}
	if req.Message == "" && strings.TrimSpace(req.TTSText) == "" && len(req.Images) == 0 && len(req.Files) == 0 && len(req.Audios) == 0 && len(req.Videos) == 0 {
		http.Error(w, "message, tts_text, or attachment is required", http.StatusBadRequest)
		return
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Send the request with POST: `curl -X POST http://127.0.0.1:<port>/send -d '{...}'`.
  2. In client code use http.NewRequest("POST", url, body) instead of http.Get.
  3. If a monitoring probe hit the route, point the probe at a GET-safe health endpoint instead.
  4. Check for redirects: a 301/302 from http to https can downgrade POST to GET — use the correct scheme directly.

Example fix

// before
resp, err := http.Get("http://127.0.0.1:8080/send")
// after
resp, err := http.Post("http://127.0.0.1:8080/send", "application/json",
    strings.NewReader(`{"message":"hi"}`))
Defensive patterns

Strategy: validation

Validate before calling

if req.Method != http.MethodPost {
    panic("/send requires POST")
}

Try / catch

resp, err := client.Do(req)
if resp.StatusCode == http.StatusMethodNotAllowed {
    // fix client to use POST and retry once
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/cd1b99004ac31da1. Report an issue: GitHub.