Portabilidade de aplicativos WinINet para WinHTTP

Os Serviços HTTP do Microsoft Windows (WinHTTP) são direcionados a aplicativos de servidor de camada intermediária e back-end que exigem acesso a uma pilha de clientes HTTP. A Internet do Microsoft Windows (WinINet) fornece uma pilha de clientes HTTP para aplicativos cliente, bem como acesso aos protocolos FTP (Protocolo de Transferência de Arquivo), SOCKSv4 e Gopher. Essa visão geral pode ajudar a determinar se a portabilidade de seus aplicativos WinINet para WinHTTP seria benéfica. Ele também descreve requisitos de conversão específicos.

O que considerar antes de portar seu aplicativo WinINet

Considere portar seu aplicativo WinINet para WinHTTP se seu aplicativo se beneficiar de:

  • Uma pilha de cliente HTTP segura para servidor.
  • Uso minimizado da pilha.
  • A escalabilidade de um aplicativo de servidor.
  • Menos dependências em APIs relacionadas à plataforma.
  • Suporte para representação de thread.
  • Uma pilha HTTP amigável ao serviço.
  • Acesso ao objeto WinHttpRequest com script.

Não considere portar seu aplicativo WinINet para WinHTTP se ele precisar dar suporte a um ou mais dos seguintes:

  • O protocolo FTP ou Gopher da pilha HTTP.
  • Suporte para protocolo SOCKSv4 para comunicação com proxies SOCKS.
  • Serviços de discagem automática.

Se você decidir portar seu aplicativo para WinHTTP, as seções a seguir orientarão você pelo processo de conversão.

Para um aplicativo de exemplo para WinINet e WinHTTP, compare o exemplo AsyncDemo para WinINet com o exemplo AsyncDemo para WinHTTP.

Equivalentes de WinHTTP para funções WinINet

A tabela a seguir lista as funções WinINet relacionadas à pilha de clientes HTTP junto com os equivalentes do WinHTTP.

Se o aplicativo exigir funções WinINet que não estão listadas, não faça a portabilidade do aplicativo para WinHTTP.

Função WinINet WinHTTP equivalente Alterações notáveis
HttpAddRequestHeaders WinHttpAddRequestHeaders Nenhum.
HttpEndRequest WinHttpReceiveResponse O valor de contexto é definido com WinHttpSendRequest ou WinHttpSetOption. As opções de solicitação são definidas com WinHttpOpenRequest. WinHttpReceiveResponse deve ser chamado após enviar uma solicitação.
HttpOpenRequest WinHttpOpenRequest O valor de contexto é definido com WinHttpSendRequest ou WinHttpSetOption.
HttpQueryInfo WinHttpQueryHeaders Nenhum.
HttpSendRequest WinHttpSendRequest O valor de contexto pode ser definido com WinHttpSendRequest.
HttpSendRequestEx WinHttpSendRequest Buffers não podem ser fornecidos.
InternetCanonicalizeUrl Sem equivalente As URLs agora são colocadas em forma canônica no WinHttpOpenRequest.
InternetCheckConnection Sem equivalente Não implementado no WinHTTP.
InternetCloseHandle WinHttpCloseHandle Fechar um identificador pai no WinHTTP não fecha recursivamente as alças filho.
InternetCombineUrl Sem equivalente As URLs podem ser montadas com a função WinHttpCreateUrl .
InternetConfirmZoneCrossing Sem equivalente Não implementado no WinHTTP.
Internetconnect WinHttpConnect O valor de contexto é definido com WinHttpSendRequest ou WinHttpSetOption. As opções de solicitação são definidas com WinHttpOpenRequest. As credenciais do usuário são definidas com WinHttpSetCredentials.
InternetCrackUrl WinHttpCrackUrl Comportamento oposto do sinalizador ICU_ESCAPE: com InternetCrackUrl, esse sinalizador faz com que sequências de escape (%xx) sejam convertidas em caracteres, mas com WinHttpCrackUrl, isso faz com que caracteres que devem ser escapados em uma solicitação HTTP sejam convertidos em sequências de escape.
InternetCreateUrl WinHttpCreateUrl Nenhum.
InternetErrorDlg Sem equivalente Como o WinHTTP é direcionado a aplicativos do lado do servidor, ele não implementa nenhuma interface do usuário.
InternetGetCookie Sem equivalente O WinHTTP não persiste dados entre sessões e não pode acessar cookies WinINet.
InternetOpen WinHttpOpen Nenhum.
Internetopenurl WinHttpConnect, WinHttpOpenRequest, WinHttpSendRequest, WinHttpReceiveResponse Essa funcionalidade está disponível nas funções WinHTTP listadas.
InternetQueryDataAvailable WinHttpQueryDataAvailable Nenhum parâmetro reservado.
InternetQueryOption WinHttpQueryOption O WinHTTP oferece um conjunto diferente de opções do WinINet. Para obter mais informações e opções oferecidas pelo WinHTTP, consulte Sinalizadores de opção.
InternetReadFile WinHttpReadData Nenhum.
InternetReadFileEx WinHttpReadData Em vez de uma estrutura, o buffer é uma região de memória endereçada com um ponteiro.
InternetSetOption WinHttpSetOption Nenhum.
InternetSetStatusCallback WinHttpSetStatusCallback Para obter mais informações, confira "Tratamento diferente de solicitações assíncronas" neste tópico.
InternetTimeFromSystemTime WinHttpTimeFromSystemTime Nenhum.
InternetTimeToSystemTime WinHttpTimeToSystemTime Nenhum.
InternetWriteFile WinHttpWriteData Nenhum.

 

Tratamento diferente de solicitações assíncronas

Lembre-se de que, no WinINet e no WinHTTP, algumas funções podem concluir solicitações assíncronas de forma síncrona ou assíncrona. Seu aplicativo deve lidar com qualquer situação. Há diferenças significativas em como WinINet e WinHTTP lidam com essas funções potencialmente assíncronas.

Wininet

  • Conclusão síncrona: se uma chamada de função WinINet potencialmente assíncrona for concluída de forma síncrona, os parâmetros OUT da função retornarão os resultados da operação. Quando ocorrer um erro, recupere o código de erro chamando GetLastError após a chamada da função WinINet.

  • Conclusão assíncrona: se uma chamada de função potencialmente assíncrona for concluída de forma assíncrona, os resultados da operação e quaisquer erros estarão acessíveis na função de retorno de chamada. A função de retorno de chamada é executada em um thread de trabalho, não no thread que fez a chamada de função inicial.

Em outras palavras, seu aplicativo deve duplicar a lógica para lidar com os resultados dessas operações em dois locais: imediatamente após a chamada de função e na função de retorno de chamada.

O WinHTTP simplifica esse modelo permitindo que você implemente a lógica operacional somente na função de retorno de chamada, que recebe uma notificação de conclusão, independentemente de a operação ter sido concluída de forma síncrona ou assíncrona. Quando a operação assíncrona está habilitada, os parâmetros OUT das funções WinHTTP não retornam dados significativos e devem ser definidos como NULL.

A única diferença significativa entre a conclusão assíncrona e síncrona no WinHTTP, da perspectiva do aplicativo, é em que a função de retorno de chamada é executada.

WinHTTP

  • Conclusão síncrona: quando uma operação é concluída de forma síncrona, os resultados são retornados em uma função de retorno de chamada que é executada no mesmo thread que a chamada de função original.

  • Conclusão assíncrona: quando uma operação é concluída de forma assíncrona, os resultados são retornados em uma função de retorno de chamada que é executada em um thread de trabalho.

Embora a maioria dos erros também possa ser tratada inteiramente dentro da função de retorno de chamada, os aplicativos WinHTTP ainda devem estar preparados para que uma função retorne FALSE devido a um ERROR_INVALID_PARAMETER ou outro erro semelhante recuperado chamando GetLastError.

Ao contrário do WinINet, que pode executar várias operações assíncronas simultaneamente, o WinHTTP impõe uma política de uma operação assíncrona pendente por identificador de solicitação. Se uma operação estiver pendente e outra função WinHTTP for chamada, a segunda função falhará e GetLastError retornará ERROR_INVALID_OPERATION.

O WinHTTP simplifica esse modelo permitindo que você implemente a lógica operacional somente na função de retorno de chamada, que recebe uma notificação de conclusão, independentemente de a operação ter sido concluída de forma síncrona ou assíncrona. Quando a operação assíncrona está habilitada, os parâmetros OUT das funções WinHTTP não retornam dados significativos e devem ser definidos como NULL.

Diferenças nas notificações de retorno de chamada do WinHTTP

A função de retorno de chamada status recebe atualizações no status de operações por meio de sinalizadores de notificação. No WinHTTP, as notificações são selecionadas usando o parâmetro dwNotificationFlags da função WinHttpSetStatusCallback . Use o sinalizador WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS para ser notificado de todas as atualizações status.

As notificações que indicam que uma operação específica está concluída são chamadas de notificações de conclusão ou apenas conclusões. No WinINet, cada vez que a função de retorno de chamada recebe uma conclusão, o parâmetro lpvStatusInformation contém uma estrutura INTERNET_ASYNC_RESULT . No WinHTTP, essa estrutura não está disponível para todas as conclusões. É importante examinar a página de referência para WINHTTP_STATUS_CALLBACK, que contém informações sobre notificações e que tipo de dados podem ser esperados para cada um.

No WinHTTP, uma única conclusão, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, indica que uma operação falhou. Todas as outras conclusões indicam uma operação bem-sucedida.

Tanto WinINet quanto WinHTTP usam um valor de contexto definido pelo usuário para passar informações do thread main para a função de retorno de chamada status, que pode ser executada em um thread de trabalho. No WinINet, o valor de contexto usado pela função de retorno de chamada status é definido chamando uma das várias funções. No WinHTTP, o valor de contexto é definido apenas com WinHttpSendRequest ou WinHttpSetOption. Por isso, é possível no WinHTTP que uma notificação ocorra antes que um valor de contexto seja definido. Se a função de retorno de chamada receber uma notificação antes que o valor de contexto seja definido, o aplicativo deverá estar preparado para receber NULL no parâmetro dwContext da função de retorno de chamada.

Diferenças de autenticação

No WinINet, as credenciais do usuário são definidas chamando a função InternetSetOption , usando um código semelhante ao fornecido no exemplo de código a seguir.

// Use the WinINet InternetSetOption function to set the 
// user credentials to the user name contained in strUsername 
// and the password to the contents of strPassword.
       
InternetSetOption( hRequest, INTERNET_OPTION_PROXY_USERNAME, 
                   strUsername, strlen(strUsername) + 1 );

InternetSetOption( hRequest, INTERNET_OPTION_PROXY_PASSWORD, 
                   strPassword, strlen(strPassword) + 1 );

Para compatibilidade, as credenciais do usuário podem ser definidas da mesma forma no WinHTTP usando a função WinHttpSetOption , mas isso não é recomendado porque pode representar uma vulnerabilidade de segurança.

Em vez disso, quando um aplicativo recebe um código 401 status no WinHTTP, o método recomendado de configuração de credenciais é primeiro identificar um esquema de autenticação usando WinHttpQueryAuthSchemes e, em segundo lugar, definir as credenciais usando WinHttpSetCredentials. O exemplo de código a seguir mostra como fazer isso.

DWORD dwSupportedSchemes;
DWORD dwPrefered;
DWORD dwTarget;

// Obtain the supported and first schemes.
WinHttpQueryAuthSchemes( hRequest, &dwSupportedSchemes, &dwPrefered, &dwTarget );

// Set the credentials before resending the request.
WinHttpSetCredentials( hRequest, dwTarget, dwPrefered, strUsername, strPassword, NULL );

Como não há equivalente a InternetErrorDlg no WinHTTP, os aplicativos que obtêm credenciais por meio de uma interface do usuário devem fornecer sua própria interface.

Ao contrário do WinINet, o WinHTTP não armazena senhas em cache. As credenciais de usuário válidas devem ser fornecidas para cada solicitação.

O WinHTTP não dá suporte ao esquema DPA (Autenticação de Senha Distribuída) com suporte do WinINet. No entanto, o WinHTTP dá suporte ao Microsoft Passport 1.4. Para obter mais informações sobre como usar a autenticação do Passport no WinHTTP, consulte Autenticação do Passport no WinHTTP.

O WinHTTP não depende das configurações de Explorer da Internet para determinar a política de logon automático. Em vez disso, a política de logon automático é definida com WinHttpSetOption. Para obter mais informações sobre a autenticação no WinHTTP, incluindo a política de logon automático, consulte Autenticação no WinHTTP.

Diferenças em transações HTTP seguras

No WinINet, inicie uma sessão segura usando HttpOpenRequest ou InternetConnect, mas no WinHTTP, você deve chamar WinHttpOpenRequest usando o sinalizador WINHTTP_FLAG_SECURE .

Em uma transação HTTP segura, os certificados de servidor podem ser usados para autenticar um servidor no cliente. No WinINet, se um certificado de servidor contiver erros, HttpSendRequest falhará e fornecerá detalhes sobre os erros de certificado.

No WinHttp, os erros de certificado do servidor são tratados de acordo com a versão da seguinte maneira:

  • A partir do WinHttp 5.1, se um certificado do servidor falhar ou contiver erros, a chamada para WinHttpSendRequest relatará um WINHTTP_CALLBACK_STATUS_SECURE_FAILURE na função de retorno de chamada. Se o erro gerado por WinHttpSendRequest for ignorado, as chamadas subsequentes para WinHttpReceiveResponse falharão com um erro de ERROR_WINHTTP_OPERATION_CANCELLED.
  • No WinHTTP 5.0, erros em certificados de servidor não causam, por padrão, falha na solicitação. Em vez disso, os erros são relatados na função de retorno de chamada com a notificação WINHTTP_CALLBACK_STATUS_SECURE_FAILURE .

Em algumas plataformas anteriores, a WinINet dá suporte aos protocolos PCT (Private Communication Technology) e/ou Fortezza, embora não no Windows XP.

O WinHTTP não dá suporte aos protocolos PCT e Fortezza em nenhuma plataforma e, em vez disso, depende do Protocolo SSL 2.0, SSL 3.0 ou TLS (Transport Layer Security) 1.0.