You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust的reqwest获取URL真实可达状态的异常问题咨询

问题分析与解决

为什么请求未完成却显示200 OK?

HTTP请求的处理分为两个阶段:

  1. 服务器先返回包含状态码的响应头
  2. 再传输响应体内容
    你的场景中,服务器已经成功返回了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:45:54