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

Rust中Reqwest POST请求失败:提示未提供grant_type(form-urlencoded格式)

问题分析:Reqwest POST请求提示grant_type参数缺失

问题描述

使用Reqwest发送POST请求时,通过serde_urlencoded生成application/x-www-form-urlencoded格式的请求体,但服务端返回错误,提示grant_type参数缺失。已通过curl验证请求数据本身正确,怀疑请求体或请求头存在问题,需排查原因。

错误返回

{"error":"unsupported_grant_type","error_description":"grant_type parameter is missing"}

相关代码

请求体与请求头构建代码

// application/x-www-form-urlencoded Mime type body
let body = serde_urlencoded::to_string([
    ("grant_type", "authorization_code"),
    ("code", "authcode"),
    ("redirect_uri", "redirect.com"),
    ("code_verifier", "workingVerifier" ),
    ("client_id", "SomeID"),
    ("client_secret", "SomeSecret"),
])?;

let body = serde_json::to_vec(&body)?;

 let mut headers: HeaderMap = HeaderMap::new();
headers.insert(
    "Authorization".to_string(),
    vec![format!("Basic {}", generate_auth_string(conf).await?)],
);
headers.insert(
    "Content-Type".to_string(),
    vec!["application/x-www-form-urlencoded".to_string()],
);

Reqwest请求代码

let response = reqwest::Client::new()
        .request(method, &req.url)
        .headers(headers)
        .body(body)
        .send()
        .await

问题原因

  1. 请求体格式错误:
    serde_urlencoded::to_string已经生成了符合application/x-www-form-urlencoded标准的字符串(如grant_type=authorization_code&code=authcode...),但你额外调用了serde_json::to_vec(&body),这会把整个urlencoded字符串序列化为JSON字符串(最终请求体变成带引号的"grant_type=authorization_code&...")。服务端解析时会把整个内容当成一个字符串参数,自然找不到grant_type字段。

  2. HeaderMap使用错误:
    Reqwest的HeaderMap并非等价于HashMap<String, Vec<String>>,直接用字符串作为key、Vec作为value插入,不符合HeaderMap的类型要求,可能导致头信息无法被正确识别。


解决方案

方案1:修正请求体与请求头构建

use reqwest::header::{HeaderMap, HeaderName, HeaderValue};

// 生成正确的urlencoded字符串,直接转成字节数组
let body = serde_urlencoded::to_string([
    ("grant_type", "authorization_code"),
    ("code", "authcode"),
    ("redirect_uri", "redirect.com"),
    ("code_verifier", "workingVerifier" ),
    ("client_id", "SomeID"),
    ("client_secret", "SomeSecret"),
])?.into_bytes();

// 正确构建HeaderMap
let mut headers = HeaderMap::new();
headers.insert(
    HeaderName::from_static("authorization"),
    HeaderValue::from_str(&format!("Basic {}", generate_auth_string(conf).await?))?,
);
headers.insert(
    HeaderName::from_static("content-type"),
    HeaderValue::from_static("application/x-www-form-urlencoded"),
);

方案2:使用Reqwest内置方法简化代码

Reqwest提供了form和basic_auth方法,可以自动处理urlencoded序列化和认证头,避免手动处理出错:

let response = reqwest::Client::new()
    .request(method, &req.url)
    .basic_auth("SomeID", Some("SomeSecret")) // 自动生成Basic Auth头
    .form(&[
        ("grant_type", "authorization_code"),
        ("code", "authcode"),
        ("redirect_uri", "redirect.com"),
        ("code_verifier", "workingVerifier" ),
    ]) // 自动序列化并设置Content-Type头
    .send()
    .await?;

内容的提问来源于stack exchange,提问作者andar1an

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:54:58