curlでHTTP2をしたい
最近巷ではgRPCが流行っていますね。
gRPCといえば、Googleが2015年5月に開発したOSSのRPCフレームワークです。

Google社内でもこのフレームワークを使っているらしいですね。
そして、このgRPCはHTTP2を前提に作られています。
HTTPに関する説明は割愛しますが、curlでHTTP2のリクエストを投げるにはそのままでは実現が出来ません。
が、もちろん拡張を行うことで投げることが可能になるとのことでしたので試してみました。
手順
前提
macにはすでにHomebrewで入れたHTTP2に対応していないcurlがインストールされているものとします。
curl 7.43.0 (x86_64-apple-darwin15.0) libcurl/7.43.0 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz UnixSockets
ダメな例
curlをアンインストールしてから再インストール
gitなどをインストールしている状態でbrew uninstall curlを実行すると、以下のような依存関係によるエラーが出てしまいます。
Warning: Use zlib instead of deprecated homebrew/dupes/zlib
Error: Refusing to uninstall /usr/local/Cellar/curl/7.50.3
because it is required by git, which is currently installed.
You can override this and force removal with:
brew uninstall --ignore-dependencies curl
brew uninstall --ignore-dependencies curlで行けるとのことですが、依存関係を壊すのは怖いのでやめました。
正しいやり方
Homebrewでリインストール
すでにHomebrewでインストール済みのコマンドを再度インストールしたい場合はbrew reinstall XXXを使うようにしましょう。
今回で言うとbrew reinstall curl --with-nghttp2ですね。
すると、以下のログが出てインストールが完了します。
==> Reinstalling curl --with-nghttp2
==> Installing dependencies for curl: openssl, boost, c-ares, jansson, libev, libevent, jemalloc and nghttp2
==> Installing curl dependency: openssl
==> Downloading https://homebrew.bintray.com/bottles/openssl-1.0.2p.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring openssl-1.0.2p.el_capitan.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the SystemRoots
keychain. To add additional certificates (e.g. the certificates added in
the System keychain), place .pem files in
/usr/local/etc/openssl/certs
and run
/usr/local/opt/openssl/bin/c_rehash
openssl is keg-only, which means it was not symlinked into /usr/local,
because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries.
If you need to have openssl first in your PATH run:
echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.zshrc
For compilers to find openssl you may need to set:
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CPPFLAGS="-I/usr/local/opt/openssl/include"
For pkg-config to find openssl you may need to set:
export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig"
==> Summary
🍺 /usr/local/Cellar/openssl/1.0.2p: 1,793 files, 12.2MB
==> Installing curl dependency: boost
==> Downloading https://homebrew.bintray.com/bottles/boost-1.67.0_1.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring boost-1.67.0_1.el_capitan.bottle.tar.gz
🍺 /usr/local/Cellar/boost/1.67.0_1: 13,506 files, 429.0MB
==> Installing curl dependency: c-ares
==> Downloading https://homebrew.bintray.com/bottles/c-ares-1.14.0.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring c-ares-1.14.0.el_capitan.bottle.tar.gz
🍺 /usr/local/Cellar/c-ares/1.14.0: 70 files, 464.0KB
==> Installing curl dependency: jansson
==> Downloading https://homebrew.bintray.com/bottles/jansson-2.11.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring jansson-2.11.el_capitan.bottle.tar.gz
🍺 /usr/local/Cellar/jansson/2.11: 11 files, 155.8KB
==> Installing curl dependency: libev
==> Downloading https://homebrew.bintray.com/bottles/libev-4.24.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libev-4.24.el_capitan.bottle.tar.gz
🍺 /usr/local/Cellar/libev/4.24: 12 files, 431.1KB
==> Installing curl dependency: libevent
==> Downloading https://homebrew.bintray.com/bottles/libevent-2.1.8.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libevent-2.1.8.el_capitan.bottle.tar.gz
🍺 /usr/local/Cellar/libevent/2.1.8: 847 files, 2.2MB
==> Installing curl dependency: jemalloc
==> Downloading https://homebrew.bintray.com/bottles/jemalloc-5.1.0.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring jemalloc-5.1.0.el_capitan.bottle.tar.gz
🍺 /usr/local/Cellar/jemalloc/5.1.0: 16 files, 1.8MB
==> Installing curl dependency: nghttp2
==> Downloading https://homebrew.bintray.com/bottles/nghttp2-1.33.0.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring nghttp2-1.33.0.el_capitan.bottle.tar.gz
🍺 /usr/local/Cellar/nghttp2/1.33.0: 33 files, 6.3MB
==> Installing curl --with-nghttp2
==> Downloading https://curl.haxx.se/download/curl-7.61.1.tar.bz2
######################################################################## 100.0%
==> ./configure --disable-silent-rules --prefix=/usr/local/Cellar/curl/7.61.1 --with-ssl=/usr/local/opt/openssl --with-ca-bundle=/usr/local/etc/openssl/cert
==> make install
==> Caveats
curl is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.
If you need to have curl first in your PATH run:
echo 'export PATH="/usr/local/opt/curl/bin:$PATH"' >> ~/.zshrc
For compilers to find curl you may need to set:
export LDFLAGS="-L/usr/local/opt/curl/lib"
export CPPFLAGS="-I/usr/local/opt/curl/include"
For pkg-config to find curl you may need to set:
export PKG_CONFIG_PATH="/usr/local/opt/curl/lib/pkgconfig"
==> Summary
🍺 /usr/local/Cellar/curl/7.61.1: 433 files, 3.2MB, built in 2 minutes 54 seconds
==> Caveats
==> openssl
A CA file has been bootstrapped using certificates from the SystemRoots
keychain. To add additional certificates (e.g. the certificates added in
the System keychain), place .pem files in
/usr/local/etc/openssl/certs
and run
/usr/local/opt/openssl/bin/c_rehash
openssl is keg-only, which means it was not symlinked into /usr/local,
because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries.
If you need to have openssl first in your PATH run:
echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.zshrc
For compilers to find openssl you may need to set:
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CPPFLAGS="-I/usr/local/opt/openssl/include"
For pkg-config to find openssl you may need to set:
export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig"
==> curl
curl is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.
If you need to have curl first in your PATH run:
echo 'export PATH="/usr/local/opt/curl/bin:$PATH"' >> ~/.zshrc
For compilers to find curl you may need to set:
export LDFLAGS="-L/usr/local/opt/curl/lib"
export CPPFLAGS="-I/usr/local/opt/curl/include"
For pkg-config to find curl you may need to set:
export PKG_CONFIG_PATH="/usr/local/opt/curl/lib/pkgconfig"
curlのパスを変更
もし、curlコマンドがHomebrewで落としたものを見ていない場合、向き先を変える必要があります。
which curlコマンドで確認をして、/usr/bin/curlになっている場合は以下をシェルの設定ファイルに追加します。
筆者はzshを使っているので~/.zshrcとなります。
export PATH="/usr/local/opt/curl/bin:$PATH"
確認
では、もう一度以下のコマンドを実行してみてください。
curl 7.61.1 (x86_64-apple-darwin15.3.0) libcurl/7.61.1 OpenSSL/1.0.2p zlib/1.2.5 nghttp2/1.33.0
Release-Date: 2018-09-05
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy
HTTP2が追加されていますね。
以下のコマンドも実行してみましょう。
curl --http2 -I https://twitter.com/
すると以下の様なログが出ると思います。
HTTP/2 200
cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
content-length: 202511
content-type: text/html;charset=utf-8
date: Thu, 18 Oct 2018 08:59:39 GMT
expires: Tue, 31 Mar 1981 05:00:00 GMT
last-modified: Thu, 18 Oct 2018 08:59:39 GMT
pragma: no-cache
...
status: 200 OK
...
HTTP/2 200が出ているのでHttp2での通信が出来ているようですね。
終わりに
HTTPの登場によって、インターネットの世界が革新的に進化した様に、HTTP2の登場によってさらに進化すると筆者は思っています。
今のうちからHTTP2に触れておくことでスタートダッシュが切れるかもしれないので、触ってみてはいかがでしょうか♪
