fish2018/pansou · error

不支持的请求方法

Error message

不支持的请求方法: %s

What it means

requestWithChallengeRetry only supports GET and POST for its cloudscraper-backed retry loop; any other HTTP method reaches the default branch and is rejected. This is a deliberate capability limit of the challenge-retry wrapper.

Solutions

  1. Use GET or POST for requests routed through the challenge-retry wrapper.
  2. Extend the switch with a scraper.Do(...) case for other verbs if you control the code.
  3. Route non-GET/POST requests through a plain HTTP client outside the challenge logic if the endpoint doesn't need anti-bot handling.

Example fix

// before
client.Do(req) // method=PUT hits default branch
// after
req.Method = http.MethodPost // or add a case for PUT backed by scraper
resp, err = scraper.Post(requestURL, contentType, strings.NewReader(requestBody))
Defensive patterns

Strategy: validation

Validate before calling

if method != http.MethodGet && method != http.MethodPost { return fmt.Errorf("challenge-retry path supports only GET/POST, got %s", method) }

Try / catch

if err != nil { if strings.Contains(err.Error(), "不支持的请求方法") { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) } }

Prevention

When it happens

Trigger: Calling the plugin's request path (requestWithChallengeRetry) with method set to e.g. http.MethodPut, DELETE, PATCH, or HEAD.

Common situations: Caller code generating dynamic HTTP methods (REST clients) passed through the plugin, or upstream code changed from GET/POST to another verb.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/535e3a7b7990d0f4. Report an issue: GitHub.

Appendix: source

Thrown at plugin/gying/gying.go:1919

	return nil
}

func (p *GyingPlugin) requestWithChallengeRetry(scraper *cloudscraper.Scraper, method, requestURL, contentType, requestBody string) ([]byte, int, http.Header, error) {
	for attempt := 0; attempt < 2; attempt++ {
		var (
			resp *http.Response
			err  error
		)

		switch method {
		case http.MethodGet:
			// Use cloudscraper for GET as well as POST so the challenge page,
			// verification request, and retry share the same browser-like headers.
			resp, err = scraper.Get(requestURL)
		case http.MethodPost:
			resp, err = scraper.Post(requestURL, contentType, strings.NewReader(requestBody))
		default:
			return nil, 0, nil, fmt.Errorf("不支持的请求方法: %s", method)
		}
		if err != nil {
			return nil, 0, nil, err
		}

		statusCode := resp.StatusCode
		headers := resp.Header.Clone()
		body, readErr := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if readErr != nil {
			return nil, statusCode, headers, readErr
		}

		if DebugLog {
			fmt.Printf("[Gying] requestWithChallengeRetry: method=%s attempt=%d status=%d url=%s bodyLen=%d challenge=%v loginShell=%v\n",
				method, attempt+1, statusCode, requestURL, len(body), isBotChallengePage(body), isLoginShell(body))
		}

View on GitHub (pinned to beaa561337)