MFC + Wininet + authentification proxy = problèmes

J’ai du code (c’est en fait pour envoyer des SMS via une interface web, mais cela n’est pas pertinent). Le code fonctionne correctement en l’ absence d’un serveur proxy, mais un client souhaite utiliser cette configuration. J’ai testé avec notre proxy, mais je ne peux pas le faire fonctionner. En parcourant l’aide, j’ai trouvé l’article 195650 de MSKB (Comment gérer l’autorisation de proxy avec WinInet), qui contient cette perle de sagesse:

There are several ways to handle HTTP_STATUS_PROXY_AUTH_REQ without displaying a user interface. By far the easiest way to do this is by using the InternetSetOption function with the flags INTERNET_OPTION_PROXY_PASSWORD and INTERNET_OPTION_PROXY_USERNAME... ...The same functionality can be accomplished in an MFC application by detecting HTTP_STATUS_PROXY_AUTH_REQ, calling CHttpConnection::SetOption, then re-calling CHttpFile::SendRequest. 

J’ai donc implémenté cette solution dans mon code, détectant l’erreur 407 d’un proxy nécessitant une authentification, puis fournissant l’authentification de base via les appels SetOption:

  if (AfxParseURL (m_csServerUrl, dwServiceType, csServerName, csObjectName, nPort)) { CSsortingng csProxy = m_pOwner->GetProxyServerSetting(); if (csProxy.GetLength() > 0) { pSession = new CMyInternetSession (TEXT("SmGen"), 1, INTERNET_OPEN_TYPE_PROXY, csProxy, NULL, INTERNET_FLAG_KEEP_CONNECTION); } else { pSession = new CMyInternetSession (TEXT("SmGen"), 1, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); } if (pSession) { pSession->SetOwnerDialog (m_pOwner); pHttpConn = pSession->GetHttpConnection (csServerName, (INTERNET_PORT)nPort, NULL, NULL); if (pHttpConn) { dwFlags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE; pHttpFile = pHttpConn->OpenRequest (CHttpConnection::HTTP_VERB_GET, csObjectName + TEXT("?") + csHTTP, NULL, 1, NULL, NULL, dwFlags); if (pHttpFile) { pHttpFile->AddRequestHeaders (csHeaders); if (pHttpFile->SendRequest ()) { pHttpFile->QueryInfoStatusCode (dwResult); bRetryWithAuth = FALSE; switch (dwResult) { case HTTP_STATUS_OK: // log success break; case HTTP_STATUS_PROXY_AUTH_REQ: bRetryWithAuth = TRUE; break; default: // log failure break; } if (bRetryWithAuth) { csProxyUsr = m_pOwner->GetProxyUsername(); csProxyPwd = m_pOwner->GetProxyPassword(); pHttpConn->SetOption (INTERNET_OPTION_PROXY_USERNAME, csProxyUsr.GetBuffer(1), csProxyUsr.GetLength()); csProxyUsr.ReleaseBuffer(); pHttpConn->SetOption (INTERNET_OPTION_PROXY_PASSWORD, csProxyPwd.GetBuffer(1), csProxyPwd.GetLength()); csProxyPwd.ReleaseBuffer(); if (pHttpFile->SendRequest ()) { // ... TIMEOUT 

Maintenant pour le problème. Le problème est que le deuxième SendRequest n’échoue pas ou ne lance pas une autre erreur, il arrive juste à expirer. Après un petit moment, je reçois CInternetException 12002 (timeout) via mon gestionnaire de wrapper. C’est un peu gênant. Inutile de dire que le SMS n’arrive jamais.

L’adresse du serveur proxy est de la forme abcd: 8080 pour éliminer le DNS en tant que facteur causal. Mon département MIS m’assure que le nom d’utilisateur et le mot de passe que je fournis sont valides (si je passe un mauvais uid / pwd, cela revient simplement à une erreur 407, donc je sais qu’ils vont au moins au proxy).

J’ai traversé tout ce que je peux trouver ici et en ligne, et je ne vais nulle part. Utiliser simplement INTERNET_OPEN_TYPE_PRECONFIG et espérer que le système ira chercher tout ce dont il a besoin automatiquement ne fonctionne pas, malheureusement, tout ce que vous avez est un proxy.

Rappelez-vous, il n’y a rien de mal avec la fonctionnalité non-proxy du code, car si j’élimine le proxy en effaçant l’entrée de registre qui fournit le serveur ip: port, tout reprend vie.

Je suis complètement déconcerté. Quelqu’un a-t-il déjà vu cela avant? Je ne suis pas optimiste, étant donné le nombre de requêtes sur l’authentification proxy sans réponses …

Modifier:

J’ai converti ce code pour utiliser WinHttp, car il existe un exemple MS qui couvre le proxy (avec authentification), et WinInet est de toute façon déconseillé. Tout va bien maintenant.

En général, une connexion HTTP est fermée après que le client ait reçu une réponse. Donc, au moment où vous envoyez votre deuxième demande avec les détails de l’authentification, le proxy aura fermé la connexion (ou au moins arrêté de recevoir).

Donc, vous devrez appeler à nouveau OpenRequest pour établir une nouvelle connexion.