PHP 5.4 で導入されたビルトインサーバーはアプリの評価やテストに便利ですが、SSL/TLS に未対応なので、対策としては Swoole や Event (libevent) などの PHP エクステンションを導入して、自分でサーバーのコードを書く方法が挙げられます。
Swoole
インストール
ビルドオプションの --enable-openssl
を指定する必要があります。
git clone https://github.com/swoole/swoole-src.git
cd swoole-src
phpize
./configure --enable-openssl
make install
Mac OS X で試したところ、make install
に入る前に Makefile
を修正する必要がありました。次の行から -lcrypt
を削除します。
SWOOLE_SHARED_LIBADD = -lz -lssl -lcrypto
PHP コード
Swoole のトップページや examples ディレクトリにあるコードの例をもとに書きます。
server.php
$crt_dir = 'crt/';
$config = [
'ssl_cert_file' => $crt_dir.'server.crt',
'ssl_key_file' => $crt_dir.'server.key'
];
$server = new swoole_http_server('0.0.0.0', 5000, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$server->set($config);
$server->on('request', function ($request, $response) {
$response->header('Content-Type', 'text/html; charset=utf-8');
$response->end('Hello Swoole');
});
$server->start();
Event
インストール
pecl install event
PHP コード
マニュアルに掲載されているコードの例をもとに書きます。
$host = '127.0.0.1';
$port = 8765;
$base = new EventBase();
$listener = new EventListener(
$base,
'ssl_accept_cb',
$base,
EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
-1,
"$host:$port"
);
$base->dispatch();
function ssl_accept_cb($listener, $fd, $address, $base) {
EventUtil::sslRandPoll();
$crt = 'crt/server.crt';
$key = 'crt/server.key';
$ctx = new EventSslContext(
EventSslContext::SSLv3_SERVER_METHOD,
[
EventSslContext::OPT_LOCAL_CERT => $crt,
EventSslContext::OPT_LOCAL_PK => $key,
EventSslContext::OPT_VERIFY_PEER => false,
EventSslContext::OPT_ALLOW_SELF_SIGNED => true,
]
);
$bev = EventBufferEvent::sslSocket(
$base,
$fd,
$ctx,
EventBufferEvent::SSL_ACCEPTING,
EventBufferEvent::OPT_CLOSE_ON_FREE
);
$bev->enable(Event::READ);
$bev->setCallbacks(
'ssl_read_cb',
NULL,
NULL,
NULL
);
}
function ssl_read_cb($bev, $ctx)
{
$body = 'hello world';
$msg = sprintf(
"HTTP/1.1 200 OK\r\n".
"Content-Type: text/html; charset=utf-8\r\n".
"Content-Length: %d\r\n".
"Connection: Close\r\n".
"\r\n". $body,
strlen($body)
);
$buf = new EventBuffer();
$buf->add($msg);
$bev->input;
$bev->writeBuffer($buf);
$bev->free();
}