使用 HttpWebRequest 通过 SSL 发送请求时出现错误 502(错误网关)

Posted

技术标签:

【中文标题】使用 HttpWebRequest 通过 SSL 发送请求时出现错误 502(错误网关)【英文标题】:Error 502 (Bad Gateway) when sending a request with HttpWebRequest over SSL 【发布时间】:2010-01-29 01:43:59 【问题描述】:

我在经典 ASP 中有以下 sn-p,用于发送命令并通过 SSL 检索响应:

Dim xmlHTTP
Set xmlHTTP = Server.CreateObject("Msxml2.ServerXMLHTTP.3.0")
xmlHTTP.open "POST", "https://www.example.com", False
xmlHTTP.setRequestHeader "Content-Type","application/x-www-form-urlencoded"
xmlHTTP.setRequestHeader "Content-Length", Len(postData)
xmlHTTP.Send postData
If xmlHTTP.status = 200 And Len(message) > 0 And Not Err Then
   Print xmlHTTP.responseText
End If

然后我使用this code作为参考,在c#中重新实现请求:

private static string SendRequest(string url, string postdata)

   WebRequest rqst = HttpWebRequest.Create(url);
   // We have a proxy on the domain, so authentication is required.
   WebProxy proxy = new WebProxy("myproxy.mydomain.com", 8080);
   proxy.Credentials = new NetworkCredential("username", "password", "mydomain");
   rqst.Proxy = proxy;
   rqst.Method = "POST";
   if (!String.IsNullOrEmpty(postdata))
   
       rqst.ContentType = "application/x-www-form-urlencoded";

       byte[] byteData = Encoding.UTF8.GetBytes(postdata);
       rqst.ContentLength = byteData.Length;
       using (Stream postStream = rqst.GetRequestStream())
       
           postStream.Write(byteData, 0, byteData.Length);
           postStream.Close();
       
   
   ((HttpWebRequest)rqst).KeepAlive = false;
   StreamReader rsps = new StreamReader(rqst.GetResponse().GetResponseStream());
   string strRsps = rsps.ReadToEnd();
   return strRsps;

问题是,在调用 GetRequestStream 时,我不断收到带有消息 "The remote server returned an error: (502) Bad Gateway." 的 WebException

起初我以为这与 SSL 证书验证有关。所以我添加了这一行:

ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();

在哪里

public class AcceptAllCertificatePolicy : ICertificatePolicy

    public bool CheckValidationResult(ServicePoint srvPoint, 
                                      System.Security.Cryptography.X509Certificate certificate,
                                      WebRequest request, 
                                      int certificateProblem)
    
        return true;
    

而且我不断收到相同的 502 错误。有什么想法吗?

【问题讨论】:

【参考方案1】:

读取错误响应的实体正文。它可能暗示正在发生的事情。

代码如下:

catch(WebException e)

if (e.Status == WebExceptionStatus.ProtocolError)

    WebResponse resp = e.Response;
    using(StreamReader sr = new StreamReader(resp.GetResponseStream()))
    
         Response.Write(sr.ReadToEnd());
    


这应该显示错误响应的全部内容。

【讨论】:

很好的建议!使用这个我发现了更多关于这个问题的信息并想出了一个解决方案。谢谢。【参考方案2】:

With the help of this我得到了更详细的问题描述:代理返回消息:“无法识别用户代理。”所以我手动设置。此外,我将代码更改为使用GlobalProxySelection.GetEmptyWebProxy(),如here 所述。最终的工作代码如下。

private static string SendRequest(string url, string postdata)

    if (String.IsNullOrEmpty(postdata))
        return null;
    HttpWebRequest rqst = (HttpWebRequest)HttpWebRequest.Create(url);
    // No proxy details are required in the code.
    rqst.Proxy = GlobalProxySelection.GetEmptyWebProxy();
    rqst.Method = "POST";
    rqst.ContentType = "application/x-www-form-urlencoded";
    // In order to solve the problem with the proxy not recognising the user
    // agent, a default value is provided here.
    rqst.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)";
    byte[] byteData = Encoding.UTF8.GetBytes(postdata);
    rqst.ContentLength = byteData.Length;

    using (Stream postStream = rqst.GetRequestStream())
    
        postStream.Write(byteData, 0, byteData.Length);
        postStream.Close();
    
    StreamReader rsps = new StreamReader(rqst.GetResponse().GetResponseStream());
    string strRsps = rsps.ReadToEnd();
    return strRsps;

【讨论】:

【参考方案3】:

缺少用户代理

例如: request.UserAgent = "Mozilla/4.0 (兼容; MSIE 7.0; Windows NT 5.1)";

【讨论】:

【参考方案4】:

这发生在我身上,因为如果 Java 应用程序没有及时响应,远程计算机上的 Java 代理会超时请求,从而使 .NET 默认超时有点无用。以下代码循环遍历所有异常并写出帮助我确定它实际上来自代理的响应:

static void WriteUnderlyingResponse(Exception exception)

    do
    
        if (exception.GetType() == typeof(WebException))
        
            var webException = (WebException)exception;
            using (var writer = new StreamReader(webException.Response.GetResponseStream()))
                Console.WriteLine(writer.ReadToEnd());
        
        exception = exception?.InnerException;
    
    while (exception != null);

来自代理的响应正文如下所示:

<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>502 Proxy Error</title>
</head><body>
<h1>Proxy Error</h1>
<p>The proxy server received an invalid
response from an upstream server.<br />
The proxy server could not handle the request <em><a href="/xxx/xxx/xxx">POST&nbsp;/xxx/xxx/xxx</a></em>.<p>
Reason: <strong>Error reading from remote server</strong></p></p>
</body></html>

【讨论】:

这揭示了我以前无法获得的大量服务器信息。【参考方案5】:

Web 服务的 wsdl 可能正在与域名和 SSL 证书“争论”。 IIS 将使用 IIS 注册的域名(默认情况下是本地域上的机器名,不一定是您的 Web 域)自动生成 Web 服务的 WSDL。如果证书域与 SOAP12 地址中的域不匹配,您将收到通信错误。

【讨论】:

以上是关于使用 HttpWebRequest 通过 SSL 发送请求时出现错误 502(错误网关)的主要内容,如果未能解决你的问题,请参考以下文章

在每个请求的.net HttpWebRequest上设置SecurityProtocol(Ssl3或TLS)

HttpWebRequest :: GetResponse-请求已中止:无法创建SSL / TLS安全通道

请求被中止:无法为 HttpWebRequest 创建 SSL/TLS 安全通道

请求中止无法创建 SSL/TLS 安全通道 - HttpWebRequest

PayPal API,HttpWebRequest 抛出 SSL WebException

将自签名证书与 .NET 的 HttpWebRequest/Response 一起使用