fish2018/pansou · warning

[ ] 请求被限流

Error message

[%s] 请求被限流

What it means

The yuhuage upstream returned HTTP 429 Too Many Requests. searchImpl sets the rateLimited flag for 60 seconds (subsequent searches fail fast with "rate limited") and returns "[%s] 请求被限流" for the current call. It signals the site is actively throttling this client.

Solutions

  1. Back off — the plugin already pauses new searches for 60s; avoid hammering retries meanwhile.
  2. Reduce request concurrency or add a global rate limiter in front of the plugin.
  3. Distribute outbound traffic across proxies/IPs if volume is legitimately high.
  4. Skip this plugin for the throttle window in aggregation logic instead of surfacing errors to users.

Example fix

// before
if resp.StatusCode == 429 {
    atomic.StoreInt32(&p.rateLimited, 1)
    go func() {
        time.Sleep(60 * time.Second)
        atomic.StoreInt32(&p.rateLimited, 0)
    }()
    return nil, fmt.Errorf("[%s] 请求被限流", p.Name())
}
// after
if resp.StatusCode == 429 {
    atomic.StoreInt32(&p.rateLimited, 1)
    if retryAfter := resp.Header.Get("Retry-After"); retryAfter != "" {
        if secs, e := strconv.Atoi(retryAfter); e == nil && secs > 0 && secs <= 600 {
            rateLimitResetAt = time.Now().Add(time.Duration(secs) * time.Second)
        }
    }
    return nil, fmt.Errorf("[%s] 请求被限流", p.Name())
}
Defensive patterns

Strategy: retry

Validate before calling

// Pace calls proactively to avoid 429:
if time.Since(lastCall) < 1*time.Second {
    time.Sleep(time.Second - time.Since(lastCall))
}

Try / catch

results, err := plugin.Search(keyword, ext)
if err != nil {
    if strings.Contains(err.Error(), "请求被限流") {
        time.Sleep(65 * time.Second)
        results, err = plugin.Search(keyword, ext)
    }
}

Prevention

When it happens

Trigger: A search request completed and resp.StatusCode == 429; triggered by sending too many requests in a short window from the same IP.

Common situations: Bursty search traffic from many users; multiple pansou instances sharing one outbound IP; the site tightened its rate limits.

Related errors


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

Appendix: source

Thrown at plugin/yuhuage/yuhuage.go:109

	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Referer", BaseURL+"/")
	
	// 发送HTTP请求
	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode == 429 {
		atomic.StoreInt32(&p.rateLimited, 1)
		go func() {
			time.Sleep(60 * time.Second)
			atomic.StoreInt32(&p.rateLimited, 0)
		}()
		return nil, fmt.Errorf("[%s] 请求被限流", p.Name())
	}
	
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("[%s] HTTP错误: %d", p.Name(), resp.StatusCode)
	}
	
	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("[%s] 读取响应失败: %w", p.Name(), err)
	}
	
	// 解析搜索结果
	results, err := p.parseSearchResults(string(body))
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to beaa561337)