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
问题原因
请求体格式错误:
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字段。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
相关产品推荐
相关产品推荐

