Browsersync で XAMPP の PHP と `.htaccess` の挙動を確認する( `http-proxy` 使用)

経緯

PHP でプログラムを書いていますが、 npm パッケージも使っているし Browsersync を使いたい。

ついでに PHP だけではなくて .htaccess も併せて挙動を確認したい、という場面に遭遇したのでメモ。

XAMPP + Browsersync であれば以下のような形で proxy とPHPの実行エンジンを指定すれば PHP プログラムの挙動も併せて確認できます。

browsersync.js

const gulp = require('gulp');
const browserSync = require('browser-sync');
const connect = require('gulp-connect-php');
const dotenv = require('dotenv').config();

const browsersync = () => {
    connect.server({
        port: 8001,
        base: dir.dist.html,
        bin: process.env.PHP_BIN,
        ini: process.env.PHP_INI
    }, () =>{
        browserSync({
            proxy: process.env.PHP_PROXY
        });
    });
};

.env

PHP_BIN=C:/xampp/php/php.exe
PHP_INI=C:/xampp/php/php.ini
PHP_PROXY=localhost:8001

ここで、今回試したい PHP アプリケーションのディレクトリ階層は以下の通りとなります。

root/
    ├ src/                     //PHPアプリケーション本体
    ├ vendor/
    ├ root/                    //Dispatcher や静的リソースの置き場所
    │    └ index.php           //Dispatcher
    ├ .env                     //環境変数
    ├ .htaccess
    ├ composer.json
    └ readme.md

前提として、

  • サブディレクトリに展開することも視野に入れた構成
  • ./root/index.php がアプリケーションの起点プログラム
  • .htaccess には「 http://localhost/PATH/TO/APP/ へアクセスした際、 http://localhost/PATH/TO/APP/root/index.php にリダイレクトして応答させる」設定が既述されている
    • cssやjs、その他静的リソースファイルは除く

という構成とします。

このとき、冒頭のコードだと gulp-connect-php から PHP の実行エンジンを直接指定しているので .htaccess が動作していないのだろう、と思ったため別の方法として以下のスレッドに当たりました。

今回はこのスレッドに倣って http-proxy (node-http-proxy)を使用した方法について取り扱います。

備考

ただし、この記事を書く直前に gulp-connect-php を使用した別の方法を試したところ普通に動いたので、上述の想定は誤りで、実際は .htaccessRewriteBase の指定と Browsersync でアクセスするパスが不一致のためにエラーを起こしていただけのようです。

そのため、この記事で書いた方法は最終的には没になりました……が、後学のために書き留めておきます。

検証

上述のスレッドの書き方を真似て gulp-connect-php の代わりに http-proxy をローカルインストールし、以下のように Browsersync のタスクを書き換えます。

browsersync.js

const gulp = require('gulp');
const browserSync = require('browser-sync');
const httpProxy = require('http-proxy');
const dotenv = require('dotenv').config();

const browsersync = () => {
    let rootDir = '';
    for (let i = 0; i < process.env.ROOT_PATH.split('/').length; i++) {
        rootDir += '../';
    }

    const proxy =  httpProxy.createProxyServer({});
    browserSync({
        server: {
            baseDir: rootDir
        },
        startPath: process.env.ROOT_PATH,
        middleware: function (req, res, next) {
            proxy.web(req, res, { target: 'http://localhost' });
        }
    });
};

.env

ROOT_PATH=/PATH/TO/APP/

.env にはXAMPPのルートからプロジェクトへのパスを既述しておくものとします。

.htaccess の挙動のため、 http://localhost:3000/ のルートではなく、http://localhost:3000/PATH/TO/APP/ の形でアクセスしたいので、 .env のパラメータを使って以下のように指定します。

  • XAMPP のドキュメントルートである htdocs ディレクトリへ遡る相対パスを Browsersync の server オプションの baseDir として指定
  • 逆に htdocs からプロジェクトのルートディレクトリまでのパス(.env の辺りそのもの)を startPath に指定

これで意図した通りに PHP アプリケーションにアクセスできることを確認できました。


ただし、一点だけ気になることが。

この方法で http は確かにアクセスできましたが、折角なので(オレオレ証明書とはいえ) https での検証もしたいと考えました。

そこで、以下のように書き換えてみました。

browsersync.js

const gulp = require('gulp');
const browserSync = require('browser-sync');
const httpProxy = require('http-proxy');
const dotenv = require('dotenv').config();

const browsersync = () => {
    let rootDir = '';
    for (let i = 0; i < process.env.ROOT_PATH.split('/').length; i++) {
        rootDir += '../';
    }

    const proxy =  httpProxy.createProxyServer({
        ssl: {
            key:  `${process.env.XAMPP_PATH}${process.env.KEY_FILE}`,
            cert: `${process.env.XAMPP_PATH}${process.env.CERT_FILE}`
        },
        target: {
            protocol: 'https:',
            host: 'localhost',
            port: 443
        },
        secure: true
    });
    browserSync({
        server: {
            baseDir: rootDir
        },
        startPath: process.env.ROOT_PATH,
        middleware: function (req, res, next) {
            proxy.web(req, res, { target: 'http://localhost' });
        }
    });
};

.env

XAMPP_PATH=C:/xampp/
CERT_FILE=apache/conf/ssl.crt/server.crt
KEY_FILE=apache/conf/ssl.key/server.key
ROOT_PATH=/PATH/TO/APP/

変更したのは

  • httpProxy.createProxyServer 時にオプションで https アクセスを強制
  • SSL証明書のパスを指定

の2箇所。ただし、これで走らせてみると怒られてしまいました。その対処については別記事で。

参考

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。