LoginSignup
2
2

More than 3 years have passed since last update.

HerokuにデプロイしたLaravelアプリのURLを正規化する

Last updated at Posted at 2020-07-26

はじめに

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を公開されている方がいたので使用させて頂きました。
- 参考:Laravel Middleware で URL を正規化する例です。

ダウンロードしたファイルを以下フォルダへコピーします。

.
├── 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へデプロイしリダイレクトが確認できれば完了です。

参考にしたサイト

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2