はじめに
HerokuにデプロイしたLaravelのURLを正規化しようとしましたが、
.htaccessのリダイレクトが有効にならずにハマったのでMiddlewareでリダイレクトしました。
やりたいこと
- 「/index.php」を「/」にリダイレクトしたい
- Herokuドメイン「***.herokuapp.com」を独自ドメイン「***.com」にリダイレクトしたい
この記事で説明しないこと
- Herokuの独自ドメイン設定
- 独自ドメインSSL化
環境
Laravel
$ php artisan --version
Laravel Framework 7.19.0
作業内容
URL正規化用のMiddleware登録
GithubからMiddlewareをダウンロード
GithubにLaravelでURL正規化する為のMiddlewareを公開されている方がいたので使用させて頂きました。
ダウンロードしたファイルを以下フォルダへコピーします。
.
├── app
│ └── Http
│ └── Middleware
│ └── Normalize.php
Normalize.phpを変更
handle()
先頭に独自ドメインへのリダイレクトを追加します。
※ドメインの***の部分は読み替えてください。
/app/Http/Middleware/Normalize.php
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// ここから
if ($_SERVER['HTTP_HOST'] == '***.herokuapp.com') {
return redirect()->to('https://***.com' . $request->getRequestUri(), 301, [], $secure = true);
}
// ここまで
$url = $_SERVER['REQUEST_URI']; // PHP 標準のリクエストを使用
$normalized = $this->normalize($url);
if ($url != $normalized) {
header('Location: ' . $normalized, true, 301); // PHP 標準のリダイレクトを使用
exit();
}
....
normalize()
今回はパスの末尾をスラッシュで置き換える必要が無かったためスラッシュ追加部分をコメントアウトしました。
また、ローカルではlocalhost:8080ポートで動かしているためhostとportを追加しました。
/app/Http/Middleware/Normalize.php
/**
* @param $url
* @return string
*/
private function normalize($url)
{
// 'host'、'port'を追加
$elements = ['scheme', 'host', 'port', 'path', 'query', 'fragment'];
$isHtmlEncoded = $url !== ($decoded = htmlspecialchars_decode($url));
$url = $decoded;
$parsed = parse_url($url);
foreach ($elements as $element) {
$parsed[$element] = $parsed[$element] ?? '';
}
parse_str($parsed['query'], $params);
preg_match('/(.*)\/(.*)/', $parsed['path'], $matches);
$dirname = $matches[1] ?? '';
$dirname .= '/';
$basename = $matches[2] ?? '';
/* 今回不要のためコメントアウト
// パス末尾に / を追加
if ($basename !== '' && mb_strpos($basename, '.') === false) {
$dirname .= $basename . '/';
$basename = '';
}
*/
// index.* を削除
$basename = preg_replace('/^index\.(.*)/', '', $basename);
// パスの // -> / 置き換え
$dirname = preg_replace('/\/\/+/', '/', $dirname);
// クエリ並び替え
ksort($params);
$parsed['scheme'] .= empty($parsed['scheme']) ? '' : '://';
// 'port'を追加
$parsed['port'] = empty($parsed['port']) ? '' : ':'.$parsed['port'];
....
Middlewareを登録
Normalizeをグローバルミドルウェアとして登録します。
/app/Http/Kernel.php
protected $middleware = [
....
\App\Http\Middleware\Normalize::class, // <= 追記
];
確認
あとはHerokuへデプロイしリダイレクトが確認できれば完了です。