WinHTTPにHTTP/2の対応が入ったようです。そこで、簡単にですが確かめてみました。
WinHTTPは、Windowsの汎用的なHTTPとWebSocketのAPIです。そんなわけで、自身でときどき使ったり、使っているアプリをたまに見かけたりします。
フラグをMSDNライブラリで見つけた
この前、WinHttpSetOption関数で指定するOption Flagsを見ていたところ、WINHTTP_PROTOCOL_FLAG_HTTP2というものが増えていることに気付きました。
WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL Sets a DWORD bitmask of acceptable advanced HTTP versions. Supported on Windows 10, version 1607 and newer. Possible values are:
- WINHTTP_PROTOCOL_FLAG_HTTP2 (0x1). Supported on Windows 10, version 1607 and newer
Legacy versions of HTTP (1.1 and prior) cannot be disabled using this option. The default is 0x0.
WINHTTP_PROTOCOL_FLAG_HTTP2の意味が書かれていませんが、どう考えてもHTTP/2を使うというフラグに違いありません。
使ってみる
というわけでさっそくコードを書いてみます。
#include <iostream> #include <memory> #include <string> #include <cstdlib> #include <windows.h> #include <winhttp.h> struct winhttp_deleter { using pointer = HINTERNET; void operator()(_In_ HINTERNET h) const noexcept { WinHttpCloseHandle(h); } }; using unique_hinternet = std::unique_ptr<HINTERNET, winhttp_deleter>; int main() { unique_hinternet session(WinHttpOpen( nullptr, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, nullptr, nullptr, 0)); if (session == nullptr) { std::quick_exit(1); } // ~~ ここから ~~ DWORD protocolOption = WINHTTP_PROTOCOL_FLAG_HTTP2; if (!WinHttpSetOption( session.get(), WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &protocolOption, sizeof protocolOption)) { std::wclog << "HTTP/2 is not supported." << std::endl; } // ~~ ここまで ~~ unique_hinternet connect(WinHttpConnect( session.get(), L"www.yahoo.co.jp", INTERNET_DEFAULT_PORT, 0)); if (connect == nullptr) { std::quick_exit(1); } unique_hinternet request(WinHttpOpenRequest( connect.get(), L"HEAD", L"/", nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE)); if (connect == nullptr) { std::quick_exit(1); } if (!WinHttpSendRequest( request.get(), WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) { std::quick_exit(1); } if (!WinHttpReceiveResponse(request.get(), nullptr)) { std::quick_exit(1); } WCHAR buffer[256]; DWORD size = sizeof buffer; if (WinHttpQueryHeaders( request.get(), WINHTTP_QUERY_VERSION, WINHTTP_HEADER_NAME_BY_INDEX, buffer, &size, WINHTTP_NO_HEADER_INDEX)) { std::wcout << buffer << std::endl; } std::quick_exit(0); } |
HTTP/2になっていることを確かめる(その1)
さて、どうやってHTTP/2であることを確認しよう?と少し悩みました。ウェブサイトでHTTP/2を使うとなれば、TLS (HTTPS)併用が事実上必須です。TLSで暗号化されていては、内容の確認は難しいです。
考えた結果「WiresharkでTLSの様子を見て、ALPNでh2が入っていたら良し」ということにしました。これがその結果です。
良さそうですね。h2になっているので、HTTP/2でしょう。
HTTP/2になっていることを確かめる(その2)
よくよく考えたら私はwww.activebasic.comのアクセスを見られます。というわけで、www.activebasic.comにアクセスさせて、アクセスログでHTTP/2であることを確認できることに気付きました。
分かりやすいように、User Agentを指定します。
--- a/http.cpp +++ b/http.cpp @@ -21,3 +21,3 @@ unique_hinternet session(WinHttpOpen( - nullptr, + L"WinHTTP-Test-App/0.0", WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, @@ -43,3 +43,3 @@ session.get(), - L"www.yahoo.co.jp", + L"www.activebasic.com", INTERNET_DEFAULT_PORT, |
実際のアクセスログの該当行はこんなです。LTSVです。protocol:HTTP/2.0かつagent:WinHTTP-Test-App/0.0となっています。
domain:www.activebasic.com host:153.203.0.68 server:160.16.87.113 user:- time:30/Apr/2017:01:09:27 +0900 method:HEAD path:/index.html protocol:HTTP/2.0 status:200 size:7312 referer:- agent:WinHTTP-Test-App/0.0 response_time:1207 cookie:- set_cookie:-
WinHTTPが報告するバージョンは1.1
上記プログラムではWINHTTP_QUERY_VERSIONを使って、通信に使ったHTTPのバージョンを取得し、それをwcoutに出力するようにしています。その出力は、上記2つの確認時、いずれも以下のようになりました。
HTTP/1.1
びっくりです。実際には、HTTP/2で通信しているにもかかわらず、WINHTTP_QUERY_VERSIONでは、HTTP/1.1という文字列を返してきました。なお、WINHTTP_QUERY_RAW_HEADERS_CRLFでも同様にHTTP/1.1となっていました。
以上、Windows 10 1607で、WinHTTPにHTTP/2への対応が入っていることを見つけた話でした。
なお、ずっと前から関数WinHttpSetOption用の定数WINHTTP_OPTION_HTTP_VERSIONと構造体HTTP_VERSION_INFOがあるのに、新たな定数WINHTTP_OPTION_ENABLE_HTTP_PROTOCOLを追加してくるあたり、苦労が窺えます。
スポンサード リンク |