使用RestSharp时是否需要HttpUtility.UrlEncode编码请求参数?
问题
我注意到不少开发者会对每一个请求参数调用HttpUtility.UrlEncode进行编码,请问在下方基于RestSharp实现的GetCashBalanceAsync方法中,是否也需要执行相同的参数编码操作?
你提供的自定义查询串构造方法代码如下:
private static string BuildQueryString(Dictionary<string, object> queryParameters) { return string.Join("&", queryParameters.Select(kvp => string.Format("{0}={1}", kvp.Key, HttpUtility.UrlEncode(kvp.Value.ToString())))); }
相关实现代码
public async Task<AccountInformation?> GetCashBalanceAsync() { var queryString = $"timestamp={GetNonce()}"; var endpoint = $"/api/v3/account?{queryString}&signature={AuthenticationToken(queryString)}"; RestRequest request = new(endpoint); request.AddHeader("X-MBX-APIKEY", _apiKey); var response = await ExecuteRestRequestAsync(request).ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.OK) { throw new Exception( $"GetCashBalance: request failed: [{(int)response.StatusCode}] {response.StatusDescription}, Content: {response.Content}, ErrorMessage: {response.ErrorMessage}"); } var deserialized = JsonSerializer.Deserialize<AccountInformation>(response.Content!); return deserialized; }
答案
当前这段实现必须手动对参数做URL编码,RestSharp不会帮你处理这部分逻辑,核心原因如下:
- 你是提前把查询参数、签名拼好组成完整endpoint字符串,再传入
RestRequest构造函数。这种用法下RestSharp会把传入的字符串当做最终的资源路径原样发起请求,不会对路径里已拼接的查询参数做任何转义编码。 - 你的接口需要做签名校验,签名生成逻辑依赖原始查询串
$"timestamp={GetNonce()}",如果参数值包含&、=、空格、中文、+这类特殊字符,不做编码会直接导致两个问题:- 服务端解析查询串时会把特殊字符识别为参数分隔符,拿到的参数值和实际传入值不符
- 服务端接收到的参数串和你本地生成签名用的参数串不一致,直接触发验签失败
- 你写的
BuildQueryString方法思路是对的,但有两个需要修正的细节:- 不要只编码参数值,如果参数名可能包含特殊字符,也需要同步做编码
- 不建议用
HttpUtility.UrlEncode,它默认遵循application/x-www-form-urlencoded规则,会把空格编码为+,而URL查询参数的标准编码要求空格转义为%20,更稳妥的选择是用Uri.EscapeDataString做编码处理。
补充说明:如果改用RestSharp自带的
AddQueryParameter方法逐个添加查询参数,RestSharp会自动完成参数编码工作。但这种写法要注意签名生成顺序:必须先把所有业务参数按规则拼接成待签名原串,生成签名后,再把业务参数、签名逐个通过AddQueryParameter传入请求,否则自动编码后的参数串和本地签名用的原串不一致,依然会出现验签失败的问题。
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

