循环调用外部Web API首次成功后续报404,换RestSharp遇Forbidden
问题分析与解决方案
原HttpWebRequest代码二次调用404的可能原因
- 资源未彻底释放:原代码手动关闭流和响应,但未利用
using语句处理HttpWebRequest/HttpWebResponse这类实现IDisposable的对象,循环中可能出现连接池耗尽或资源泄漏,导致服务器无法处理后续请求返回404。 - 请求参数意外变更:检查foreach循环中
apiUrl是否被修改,或是XML内容包含的动态参数(如路由标识)错误,导致API路由匹配失败。 - 服务器限流/拦截:部分API会限制同一客户端的请求频率,首次请求后后续请求被临时拦截,用404作为伪装的限流提示。
RestSharp报Forbidden的可能原因
- 认证编码不匹配:原代码用ISO-8859-1编码生成Basic认证字符串,RestSharp默认用UTF-8,导致认证信息不一致被服务器拒绝。
- 请求头/内容编码遗漏:原代码明确设置了
ContentType和ASCII编码的XML内容,迁移到RestSharp时可能未同步这些设置,导致服务器解析失败。
修正后的代码示例
改进版HttpWebRequest(用using确保资源释放)
foreach (var item in yourItems) { string xmlFileName = Path.GetFileName(xmlDocument.BaseURI); string response = string.Empty; using (HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(apiUrl)) { // 按原逻辑生成Basic认证头 string basicAuth = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes($"{apiUrlUsername}:{apiUrlUserPassword}")); httpWebRequest.Headers.Add("Authorization", $"Basic {basicAuth}"); httpWebRequest.Method = "POST"; httpWebRequest.ContentType = apiContentType; byte[] requestBytes = Encoding.ASCII.GetBytes(xmlDocument.InnerXml); httpWebRequest.ContentLength = requestBytes.Length; using (Stream requestStream = httpWebRequest.GetRequestStream()) { requestStream.Write(requestBytes, 0, requestBytes.Length); } using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse()) using (StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.Default)) { response = streamReader.ReadToEnd(); } // 处理返回结果 } }
匹配原逻辑的RestSharp实现
foreach (var item in yourItems) { var client = new RestClient(apiUrl); var request = new RestRequest(Method.POST); // 沿用ISO-8859-1编码生成认证头 var authBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes($"{apiUrlUsername}:{apiUrlUserPassword}"); request.AddHeader("Authorization", $"Basic {Convert.ToBase64String(authBytes)}"); // 同步原代码的ContentType设置 request.AddHeader("Content-Type", apiContentType); // 用ASCII编码发送XML内容 request.AddParameter(apiContentType, xmlDocument.InnerXml, ParameterType.RequestBody, Encoding.ASCII); IRestResponse response = client.Execute(request); // 处理返回结果 }
额外排查建议
- 抓包对比首次和二次请求的完整报文,确认URL、请求头、body内容是否存在差异。
- 检查原代码中获取的
xmlFileName是否需要作为请求参数/头传递给API(当前代码仅获取未使用)。 - 联系API提供方,确认是否存在请求频率限制、会话绑定等机制导致后续请求被拒绝。
内容的提问来源于stack exchange,提问作者ErnadJ
相关产品推荐
相关产品推荐

