fish2018/pansou · error

应用代理失败

Error message

应用代理失败: %w

What it means

The gying plugin wraps cloudscraper (used to bypass Cloudflare challenges) for its HTTP requests. After creating the scraper it calls applyProxyToScraper, which configures the scraper's internal http.Client transport to route through the user-configured proxy. If that configuration fails (typically because the proxy URL cannot be parsed or the transport cannot be built), the error is wrapped with '应用代理失败: %w' and returned instead of a scraper.

Solutions

  1. Check the plugin's proxy configuration value and make sure it is a full URL with scheme, e.g. http://host:port or socks5://host:port.
  2. URL-encode any username/password in the proxy string (special chars like @ : / break parsing).
  3. Temporarily clear the proxy setting and re-run; if it works, the proxy value itself is invalid.
  4. If the error persists, verify the scraper's http.Client/transport creation path (applyProxyToScraper) against the installed cloudscraper version — an upstream API change can break reflection-based proxy injection.

Example fix

// before (config)
proxy = "127.0.0.1:7890"
// after
proxy = "http://127.0.0.1:7890"
Defensive patterns

Strategy: validation

Validate before calling

// validate proxy config before invoking login
u, err := url.Parse(cfg.Proxy)
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("invalid proxy %q: need scheme://host:port", cfg.Proxy)
}

Prevention

When it happens

Trigger: Calling any gying login/fetch path (e.g. p.login flow that creates a cloudscraper) while a proxy is configured for the plugin and applyProxyToScraper returns an error — most commonly an unparseable proxy address set in the plugin's proxy config.

Common situations: User set a malformed proxy string (missing scheme, e.g. '127.0.0.1:7890' instead of 'http://127.0.0.1:7890'); proxy env/config edited by hand; proxy config field picked up whitespace or credentials with special characters that need URL-encoding.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at plugin/gying/gying.go:1976

}

// createScraperWithCookies 创建一个带有指定cookies的cloudscraper实例
// 使用反射访问内部的http.Client并设置cookies到cookiejar
// 关键:禁用session refresh以防止cookies被清空
func (p *GyingPlugin) createScraperWithCookies(cookieStr string) (*cloudscraper.Scraper, error) {
	// 创建cloudscraper实例,配置以保护cookies不被刷新
	scraper, err := cloudscraper.New(
		cloudscraper.WithSessionConfig(
			false,            // refreshOn403 = false,禁用403时自动刷新
			365*24*time.Hour, // interval = 1年,基本不刷新
			0,                // maxRetries = 0
		),
	)
	if err != nil {
		return nil, fmt.Errorf("创建cloudscraper失败: %w", err)
	}
	if err := p.applyProxyToScraper(scraper); err != nil {
		return nil, fmt.Errorf("应用代理失败: %w", err)
	}

	// 如果有保存的cookies,使用反射设置到scraper的内部http.Client
	if cookieStr != "" {
		cookies := parseCookieString(cookieStr)

		if DebugLog {
			fmt.Printf("[Gying] 正在恢复 %d 个cookie到scraper实例\n", len(cookies))
		}

		// 使用反射访问scraper的unexported client字段
		scraperValue := reflect.ValueOf(scraper).Elem()
		clientField := scraperValue.FieldByName("client")

		if clientField.IsValid() && !clientField.IsNil() {
			// 使用反射访问client (需要使用Elem()因为是指针)
			clientValue := reflect.NewAt(clientField.Type(), unsafe.Pointer(clientField.UnsafeAddr())).Elem()
			client, ok := clientValue.Interface().(*http.Client)

View on GitHub (pinned to beaa561337)