使用Rust的reqwest获取URL真实可达状态的异常问题咨询
问题分析与解决
为什么请求未完成却显示200 OK?
HTTP请求的处理分为两个阶段:
- 服务器先返回包含状态码的响应头
- 再传输响应体内容
你的场景中,服务器已经成功返回了200状态码的响应头,但在传输响应体的过程中提前关闭了连接。reqwest会将这种情况判定为错误,但错误对象中会保留已经接收到的状态码——因为状态码已经被客户端成功解析,只是后续的响应体传输环节失败了。
如何获取URL的真实可达状态?
要确认URL的真实可达性,需要确保请求能完整完成(至少正常接收响应头和响应体),可以通过以下两种方案调整代码:
方案1:确保完整接收响应体
修改代码,在获取响应后显式读取完整响应体,以此确认传输无异常:
use reqwest::{Client, header::{HeaderValue, HeaderMap}}; #[tokio::main] async fn main() { let client = Client::builder() .danger_accept_invalid_certs(true) .build() .unwrap_or_default(); let response_result = client.get("http://mang0.me/atom.xml") .headers(construct_headers()) .send() .await; match response_result { Ok(mut resp) => { // 尝试读取完整响应体,验证传输过程 match resp.text().await { Ok(_) => println!("请求完全成功,状态码: {}", resp.status()), Err(e) => println!("状态码: {},但响应体传输失败: {}", resp.status(), e), } }, Err(err) => { // 此处为未收到响应头的场景 if let Some(status) = err.status() { println!("收到状态码: {},但请求过程出错: {}", status, err); } else { println!("请求完全失败(未收到响应头): {}", err); } }, } } fn construct_headers() -> HeaderMap { let mut headers = HeaderMap::new(); headers.insert("User-Agent", HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36")); headers.insert("Accept", HeaderValue::from_static("text/html")); headers.insert( "Referer", HeaderValue::from_static("https://www.google.com"), ); headers }
方案2:用HEAD请求简化判断
如果不需要响应体,仅需确认服务器能正常返回响应头且连接不中断,可以发送HEAD请求(服务器仅返回响应头,不传输响应体):
use reqwest::{Client, header::{HeaderValue, HeaderMap}}; #[tokio::main] async fn main() { let client = Client::builder() .danger_accept_invalid_certs(true) .build() .unwrap_or_default(); // 将GET请求替换为HEAD请求 let response_result = client.head("http://mang0.me/atom.xml") .headers(construct_headers()) .send() .await; match response_result { Ok(resp) => println!("请求成功,状态码: {}", resp.status()), Err(err) => { if let Some(status) = err.status() { println!("收到状态码: {},但请求出错: {}", status, err); } else { println!("请求失败: {}", err); } }, } } fn construct_headers() -> HeaderMap { let mut headers = HeaderMap::new(); headers.insert("User-Agent", HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36")); headers.insert("Accept", HeaderValue::from_static("text/html")); headers.insert( "Referer", HeaderValue::from_static("https://www.google.com"), ); headers }
核心判断逻辑
- 若
send().await成功且响应体读取正常:说明URL完全可达,服务运行正常 - 若
send().await成功但响应体读取失败:说明服务器能返回状态码,但响应体传输存在问题(如服务器配置异常、网络中断等) - 若
send().await直接失败且无状态码:说明未收到任何响应头,属于完全不可达(如DNS解析失败、连接超时、服务器拒绝连接等)
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

