{"record":{"id":"1687e6d0c31c696e","repo":"rathole-org/rathole","slug":"proxy-url-should-have-host-field","errorCode":null,"errorMessage":"proxy url should have host field","messagePattern":"proxy url should have host field","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/helper.rs","lineNumber":118,"sourceCode":"            }\n        }\n    };\n    let s = UdpSocket::bind(bind_addr).await?;\n    s.connect(socket_addr).await?;\n    s.connect(socket_addr).await?;\n    Ok(s)\n}\n\n/// Create a TcpStream using a proxy\n/// e.g. socks5://user:pass@127.0.0.1:1080 http://127.0.0.1:8080\npub async fn tcp_connect_with_proxy(\n    addr: &AddrMaybeCached,\n    proxy: Option<&Url>,\n) -> Result<TcpStream> {\n    if let Some(url) = proxy {\n        let addr = &addr.addr;\n        let mut s = TcpStream::connect((\n            url.host_str().expect(\"proxy url should have host field\"),\n            url.port().expect(\"proxy url should have port field\"),\n        ))\n        .await?;\n\n        let auth = if !url.username().is_empty() || url.password().is_some() {\n            Some(async_socks5::Auth {\n                username: url.username().into(),\n                password: url.password().unwrap_or(\"\").into(),\n            })\n        } else {\n            None\n        };\n        match url.scheme() {\n            \"socks5\" => {\n                async_socks5::connect(&mut s, host_port_pair(addr)?, auth).await?;\n            }\n            \"http\" => {\n                let (host, port) = host_port_pair(addr)?;","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/rathole-org/rathole/blob/a292f7ed5402f840415fc6a53827da2f34337856/src/helper.rs#L100-L136","documentation":"tcp_connect_with_proxy connects to the SOCKS5 proxy itself using url.host_str().expect(...). If the proxy Url lacks a host component, this panics at src/helper.rs:118. A proxy URL without a host cannot be dialed, so the invariant is enforced with an expect.","triggerScenarios":"Passing a proxy option whose URL has no host — e.g. `socks5://:1080`, a malformed URL, or an empty proxy string parsed to a host-less Url.","commonSituations":"Typo in the proxy URL (missing host between scheme and port); environment variable ALL_PROXY/HTTP_PROXY set to a malformed value; templated configs where the proxy host variable was empty.","solutions":["Provide a complete proxy URL including host, e.g. `socks5://proxy.example.com:1080`.","Check the proxy environment variable / CLI flag value for typos or missing host.","Validate the URL with Url::parse and assert host_str().is_some() before starting connections.","If credentials are used, ensure the format `socks5://user:pass@host:port` is preserved."],"exampleFix":"// before\nlet proxy = \"socks5://:1080\"; // no host -> panic\n// after\nlet proxy = \"socks5://127.0.0.1:1080\";","handlingStrategy":"validation","validationCode":"let url = Url::parse(proxy_str).map_err(|e| anyhow!(\"bad proxy url: {}\", e))?;\nif url.host_str().is_none() {\n    anyhow::bail!(\"proxy url '{}' must include a host\", proxy_str);\n}","typeGuard":"fn valid_proxy_url(u: &Url) -> bool {\n    u.host_str().is_some()\n}","tryCatchPattern":null,"preventionTips":["Store full proxy URLs including scheme, host and port","Validate proxy env vars at startup","Avoid hand-editing proxy URLs in production configs"],"tags":["proxy","socks5","panic","url"],"backgroundTag":"invalid-url","analyzedSha":"a292f7ed5402f840415fc6a53827da2f34337856","analyzedAt":"2026-09-07T09:56:55.739Z","contentChangedAt":"2026-09-07T09:56:55.739Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}