概要
HHVM には HTTP サーバーライブラリの Proxygen が組み込まれており、コマンドラインから起動できます。Proxygen は TLS/SSL および HTTP/2 に対応しています。
PHP のビルトインサーバーは SSL/TLS、HTTP/2 に対応していないので、運用環境でHHVM を使わなくてもテスト環境での選択肢の1つとして考えることができます。HHVM のプロジェクトが配布している Docker イメージを利用することで、導入の敷居が下がります。
テスト環境のために SSL/TLS を利用するほかの選択肢として、Swoole や Event エクステンションを挙げます。コードの例はこちらの記事をご参照ください。
コマンドツールで Proxygen を起動させる
HHVM のコマンドツールから Proxygen を直接させる場合、オプションに -v Server.EnableH2C=true
を指定すれば HTTP/2 が利用できます。
hhvm -m server -v Server.Type=proxygen -v Server.EnableH2C=true -p 8080
このオプションは SSL/TSL なしで HTTP/2 を利用するためにあります。主要なブラウザーは SSL/TLS なしでの HTTP/2 通信を許可しないため、curl などのコマンドツールで確認する必要があります。
SSL/TLS もサポートしてみましょう。項目が多いので、ini 設定ファイルを用意して読み込むことにします。
hhvm -m server -c hhvm.prod.ini
hhvm.server.type = proxygen
hhvm.server.port = 8080
; http/2
hhvm.server.ssl_next_protocols[] = h2
hhvm.server.ssl_next_protocols[] = http/1.1
; http/2 without ssl/tls
hhvm.server.enable_h2c = true
hhvm.server.enable_ssl = true
hhvm.server.ssl_certificate_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
hhvm.server.ssl_certificate_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
Ubuntu の場合、テスト用の SSL/TLS の証明書は ssl-cert パッケージから入手できます。
Docker の公式イメージを利用する
今度は Docker Hub で配布されている Docker の公式イメージを利用してみましょう。
docker-compose.yml
、Dockerfile
、hhvm.prod.ini
、public/index.php
を用意します。
version: '2'
services:
hhvm:
build: ./
volumes:
- ./public:/var/www/public
ports:
- "80:80"
- "443:443"
FROM hhvm/hhvm-proxygen:latest
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y ssl-cert \
--no-install-recommends && rm -r /var/lib/apt/lists/*
ADD hhvm.prod.ini /etc/hhvm/site.ini
EXPOSE 80 443
; https://github.com/hhvm/hhvm-docker/blob/master/hhvm-latest-proxygen/server.ini
; php options
pid = /var/run/hhvm/pid
; php options
pid = /var/run/hhvm/pid
; hhvm specific
hhvm.server.port = 80
hhvm.server.type = proxygen
hhvm.server.default_document = index.php
hhvm.server.error_document404 = index.php
hhvm.repo.central.path = /var/run/hhvm/hhvm.hhbc
hhvm.server.source_root=/var/www/public
; default log location is stdout/err, which is good for docker
hhvm.log.use_log_file = true
; http/2
hhvm.server.ssl_next_protocols[] = h2
hhvm.server.ssl_next_protocols[] = http/1.1
; http/2 without ssl/tls
hhvm.server.enable_h2c = true
; ssl/tls
hhvm.server.enable_ssl = true
hhvm.server.ssl_certificate_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
hhvm.server.ssl_certificate_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
<?php
phpinfo();
Docker イメージを起動させる
Docker イメージをもとにサービスを起動させます。
docker-compose up --build -d
サービスを停止させるには次のコマンドを実行します。
docker-compose stop
phpinfo 関数で ini 設定を確認する
ブラウザーから hhvml.server
でページ内を検索して、ini
ファイルが反映されていることを確認します。じっくり眺めていると、公式マニュアルに掲載されていない項目があるかもしれません。
curl で確かめる
curl で HEAD リクエストを送信して HTTP/2 通信ができるか確かめてみましょう。
curl --http2 -I -v http://localhost:8080
レスポンスに Upgrade: h2c
、HTTP/2 200
が含まれていることを確認します。
> HEAD / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.50.3
> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAAQAAP__
>
< HTTP/1.1 101 Switching Protocols
HTTP/1.1 101 Switching Protocols
< Upgrade: h2c
Upgrade: h2c
< Date: Mon, 26 Sep 2016 21:41:14 GMT
Date: Mon, 26 Sep 2016 21:41:14 GMT
< Connection: upgrade
Connection: upgrade
* Received 101
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=52
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
HTTP/2 200
< vary: Accept-Encoding
vary: Accept-Encoding
< content-type: text/html
content-type: text/html
< x-powered-by: HHVM/3.15.0
x-powered-by: HHVM/3.15.0
< content-length: 50947
content-length: 50947
< date: Mon, 26 Sep 2016 21:41:14 GMT
date: Mon, 26 Sep 2016 21:41:14 GMT
今度は SSL/TLS で通信してみましょう。
curl --http2 -I -v https://localhost:8443
レスポンスに ALPN, offering h2
、HTTP/2 200
が含まれていることを確認します。
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /usr/local/etc/openssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* NPN, negotiated HTTP2 (h2)
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Unknown (67):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: CN=11687faae091
* start date: Sep 26 19:28:39 2016 GMT
* expire date: Sep 24 19:28:39 2026 GMT
* issuer: CN=11687faae091
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fbf7f008800)
> HEAD / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.50.3
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
HTTP/2 200
< vary: Accept-Encoding
vary: Accept-Encoding
< content-type: text/html
content-type: text/html
< x-powered-by: HHVM/3.15.0
x-powered-by: HHVM/3.15.0
< content-length: 50508
content-length: 50508
< date: Mon, 26 Sep 2016 21:44:20 GMT
date: Mon, 26 Sep 2016 21:44:20 GMT