Portabilidade de aplicativos WinINet para WinHTTP
O Microsoft Windows HTTP Services (WinHTTP) destina-se a aplicativos de servidor back-end e de camada intermediária que exigem acesso a uma pilha de cliente HTTP. Microsoft Windows Internet (WinINet) fornece uma pilha de cliente HTTP para aplicativos cliente, bem como acesso aos protocolos FTP (File Transfer Protocol), SOCKSv4 e Gopher. Esta visão geral pode ajudar a determinar se a portabilidade de seus aplicativos WinINet para WinHTTP seria benéfica. Também descreve requisitos de conversão específicos.
- coisas a considerar antes de portar seu aplicativo WinINet
- Os equivalentes de WinHTTP às funções de WinINet
- Tratamento diferente de solicitações assíncronas
- Diferenças nas notificações de retorno de chamada do WinHTTP
- Diferenças de autenticação
- Diferenças nas transações HTTP seguras
Coisas a considerar antes de portar seu aplicativo WinINet
Considere a portabilidade de seu aplicativo WinINet para WinHTTP se seu aplicativo se beneficiar de:
- Uma pilha de cliente HTTP segura para uso em servidores.
- Utilização minimizada da pilha.
- A escalabilidade de um aplicativo de servidor.
- Menos dependências em APIs relacionadas à plataforma.
- Suporte para representação de tópico.
- Uma pilha HTTP otimizada para serviços.
- Acesso programável ao objeto WinHttpRequest .
Não considere portar seu aplicativo WinINet para WinHTTP se ele deve suportar um ou mais dos seguintes:
- Os protocolos FTP ou Gopher fazem parte da pilha HTTP.
- Suporte para o protocolo SOCKSv4 para comunicação com proxies SOCKS.
- Serviços de acesso telefónico automático.
Se você decidir portar seu aplicativo para WinHTTP, as seções a seguir o guiarão 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 WinHTTP para funções WinINet
A tabela a seguir lista as funções WinINet relacionadas com a pilha do cliente HTTP juntamente com os equivalentes WinHTTP.
Se seu aplicativo requer funções WinINet que não estão listadas, não portar seu aplicativo para WinHTTP.
Função WinINet | Equivalente do WinHTTP | Mudanças notáveis |
---|---|---|
HttpAddRequestHeaders | WinHttpAddRequestHeaders | Nenhuma. |
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 o envio de uma solicitação. |
HttpOpenRequest | WinHttpOpenRequest | O valor de contexto é definido com WinHttpSendRequest ou WinHttpSetOption. |
HttpQueryInfo | WinHttpQueryHeaders | Nenhuma. |
HttpSendRequest | WinHttpSendRequest | O valor de contexto pode ser definido com WinHttpSendRequest. |
HttpSendRequestEx | WinHttpSendRequest | Não é possível fornecer buffers. |
InternetCanonicalizeUrl | Sem equivalente | URLs agora são colocados em forma canônica em WinHttpOpenRequest. |
InternetCheckConnection | Sem equivalente | Não implementado no WinHTTP. |
InternetCloseHandle | WinHttpCloseHandle | Fechar um identificador pai no WinHTTP não fecha recursivamente os respetivos identificadores filho. |
InternetCombineUrl | Sem equivalente | As URLs podem ser montadas com a funçãoWinHttpCreateUrl. |
ConfirmarTravessiaDeZonaInternet | 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 indicador ICU_ESCAPE: com InternetCrackUrl, este indicador faz com que sequências de escape (%xx) sejam convertidas em caracteres, mas com WinHttpCrackUrl, ele faz com que caracteres que precisam ser escapados numa solicitação HTTP sejam convertidos em sequências de escape. |
InternetCreateUrl | WinHttpCreateUrl | Nenhuma. |
InternetErrorDlg | Sem equivalente | Como o WinHTTP é direcionado a aplicativos do lado do servidor, ele não implementa nenhuma interface de usuário. |
InternetGetCookie | Sem equivalente | WinHTTP não persiste dados entre sessões e não pode acessar cookies WinINet. |
InternetOpen | WinHttpOpen | Nenhuma. |
InternetOpenUrl | WinHttpConnect, WinHttpOpenRequest, WinHttpSendRequest, WinHttpReceiveResponse | Essa funcionalidade está disponível nas funções WinHTTP listadas. |
InternetQueryDataAvailable | WinHttpQueryDataAvailable | Sem parâmetros reservados. |
InternetQueryOption | WinHttpQueryOption | 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 | Nenhuma. |
InternetReadFileEx | WinHttpReadData | Em vez de uma estrutura, o buffer é uma região de memória endereçada com um ponteiro. |
InternetSetOption | WinHttpSetOption | Nenhuma. |
InternetSetStatusCallback | WinHttpSetStatusCallback | Para obter mais informações, consulte "Tratamento diferente de solicitações assíncronas" neste tópico. |
InternetTimeFromSystemTime | WinHttpTimeFromSystemTime | Nenhuma. |
InternetTimeToSystemTime | WinHttpTimeToSystemTime | Nenhuma. |
InternetWriteFile | WinHttpWriteData | Nenhuma. |
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 de 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, a sua aplicação deve duplicar a lógica para lidar com os resultados de tais operações em dois locais: tanto imediatamente após a chamada da função como na função callback.
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 ser 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 perspetiva da aplicação, é onde 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 através de um callback que é executado no mesmo thread que a chamada original da função.
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 callback, os aplicativos WinHTTP ainda devem estar preparados para que uma função retorne FALSE devido a um erro como 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.
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 ser 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 feedback de status recebe atualizações sobre o status das operações por meio de sinalizadores de notificação. Em 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 de status.
As notificações que indicam que uma determinada operação está concluída são chamadas de notificações de conclusão ou apenas de conclusão. No WinINet, cada vez que o callback recebe uma conclusão, o parâmetro lpvStatusInformation contém uma estrutura INTERNET_ASYNC_RESULT. No caso do WinHTTP, essa estrutura não está disponível para todas as conclusões. É importante rever 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 uma.
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.
WinINet e WinHTTP utilizam um valor de contexto definido pelo utilizador para transferir informações da thread principal para a função de retorno de chamada de estado, que pode ser executada num thread de trabalho. No WinINet, o valor de contexto usado pela função callback de 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 utilizador são definidas chamando a função InternetSetOption , usando código semelhante ao seguinte exemplo de código fornecido.
// 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 fins de compatibilidade, as credenciais do usuário também podem ser definidas no WinHTTP usando a funçãoWinHttpSetOption, mas isso não é recomendado porque pode representar uma vulnerabilidade de segurança.
Em vez disso, quando um aplicativo recebe um código de status 401 no WinHTTP, o método recomendado de definir 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 de usuário devem fornecer sua própria interface.
Ao contrário do WinINet, o WinHTTP não armazena senhas em cache. Credenciais de usuário válidas devem ser fornecidas para cada solicitação.
WinHTTP não suporta o esquema de autenticação de senha distribuída (DPA) suportado pelo WinINet. WinHTTP, no entanto, suporta o Microsoft Passport 1.4. Para obter mais informações sobre como usar a autenticação do Passport no WinHTTP, consulte Passport Authentication in WinHTTP.
WinHTTP não depende das configurações do Internet Explorer para determinar a diretiva de logon automático. Em vez disso, a política de logon automático é definida com WinHttpSetOption. Para obter mais informações sobre autenticação no WinHTTP, incluindo a política de logon automático, consulte Authentication in WinHTTP.
Diferenças nas 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 de 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 falham com um erro de ERROR_WINHTTP_OPERATION_CANCELLED.
- No WinHTTP 5.0, erros em certificados de servidor não causam, por padrão, uma falha de solicitação. Em vez disso, os erros são relatados com a notificação WINHTTP_CALLBACK_STATUS_SECURE_FAILURE na função de retorno de chamada.
Em algumas plataformas anteriores, o WinINet suportava os protocolos PCT (Private Communication Technology) e/ou Fortezza, embora não no Windows XP.
WinHTTP não suporta os protocolos PCT e Fortezza em nenhuma plataforma e, em vez disso, depende de Secure Sockets Layer (SSL) 2.0, SSL 3.0 ou Transport Layer Security (TLS) 1.0.