web-dev-qa-db-fra.com

Erreur 502 (passerelle incorrecte) lors de l'envoi d'une demande avec HttpWebRequest sur SSL

J'ai l'extrait suivant en ASP classique, pour envoyer une commande et récupérer la réponse via 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

Ensuite, j'ai utilisé ce code comme référence pour réimplémenter la requête en 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;
}

Le problème est que, lorsque j'appelle GetRequestStream, je reçois une exception WebException avec le message "The remote server returned an error: (502) Bad Gateway."

Au début, je pensais que cela avait à voir avec la vérification du certificat SSL. J'ai donc ajouté cette ligne:

ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();

public class AcceptAllCertificatePolicy : ICertificatePolicy
{
    public bool CheckValidationResult(ServicePoint srvPoint, 
                                      System.Security.Cryptography.X509Certificate certificate,
                                      WebRequest request, 
                                      int certificateProblem)
    {
        return true;
    }
}

Et je continue à avoir la même erreur 502. Des idées?

23
Leonardo

Avec l'aide de ceci J'ai eu une description plus détaillée du problème: Le proxy renvoyait le message: "L'agent utilisateur n'est pas reconnu." Je l'ai donc réglé manuellement. De plus, j'ai changé le code pour utiliser GlobalProxySelection.GetEmptyWebProxy (), comme décrit ici . Le code de travail final est inclus ci-dessous.

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;
}
26
Leonardo

Lisez le corps d'entité de la réponse d'erreur. Cela pourrait laisser deviner ce qui se passe.

Le code à faire est le suivant:

catch(WebException e)
{
if (e.Status == WebExceptionStatus.ProtocolError)
{
    WebResponse resp = e.Response;
    using(StreamReader sr = new StreamReader(resp.GetResponseStream()))
    {
         Response.Write(sr.ReadToEnd());
    }
}
}

Cela devrait montrer le contenu complet de la réponse d'erreur.

31
feroze

Il est possible que le fichier WSDL du service Web "discute" avec le nom de domaine et le certificat SSL. IIS générera automatiquement le WSDL d'un service Web à l'aide du nom de domaine enregistré IIS (qui est par défaut le nom de l'ordinateur sur le domaine local, pas nécessairement votre domaine Web). Si le domaine du certificat ne correspond pas au domaine de l'adresse SOAP12, vous recevrez des erreurs de communication.

1
Joel Etherton

UserAgent est manquant

par exemple: request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)";

1
Jishnu Sukumaran

Cela se produisait pour moi car un proxy Java sur la machine distante arrêtait les requêtes si l'application Java ne répondait pas à temps, rendant les délais d'expiration par défaut .NET plutôt inutiles. Le code suivant parcourt toutes les exceptions et écrit les réponses qui m'ont aidé à déterminer que cela provenait en réalité du proxy:

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);
}

Le corps de la réponse du proxy ressemblait à ceci:

<!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>
0
Alexandru