見出し画像

Larval Vaporで自動的にwww.を付与するハック

あんまりないけど、URL先頭に自動でwww.を付与したい場合。

例)https://sample.com → https://www.sample.com

たとえば、Middlewareで自動的にwww.を付与する処理を記述する。

class Kernel extends HttpKernel
{
   /**
    * The application's global HTTP middleware stack.
    *
    * These middleware are run during every request to your application.
    *
    * @var array
    */
   protected $middleware = [
       // ...
       \App\Http\Middleware\RedirectToWwwUrl::class,
       // ...
   ];
class RedirectToWwwUrl
{
  /**
   * Handle an incoming request.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \Closure  $next
   * @return mixed
   */
  public function handle($request, Closure $next)
  {
      if ($request->getHost() === config('app.domain')) {
          return new RedirectResponse(str_replace(
              $request->getScheme() . '://',
              $request->getScheme() . '://www.',
              $request->fullUrl()
          ), 301);
      }

      return $next($request);
  }
}

このようなコードでVaporにデプロイし、アクセスしてみるとERR_TOO_MANY_REDIRECTSとなってしまう。

これは、Vaporの仕様で自動的にwww.を外し、ルートにリダイレクトするという処理が用意されているからだ。

vapor-core/src/Runtime/Http/Middleware/EnsureOnNakedDomain.php
class EnsureOnNakedDomain
{
   /**
    * Handle the incoming request.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  callable  $next
    * @return mixed
    */
   public function handle($request, $next)
   {
       if (strpos($request->getHost(), 'www.') === 0) {
           return new RedirectResponse(Str::replaceFirst(
               'www.', '', $request->fullUrl()
           ), 301);
       }

       return $next($request);
   }
}

解決方法としては、vapor-coreのバージョンをv2.8.2に上げる。すると、config/vapor.phpが追加され、EnsureOnNakedDomainのコードも以下のように変更されている。

<?php

use Illuminate\Support\Str;

return [

   /*
   |--------------------------------------------------------------------------
   | Redirect robots.txt
   |--------------------------------------------------------------------------
   |
   | When this option is enabled, Vapor will redirect requests to the
   | robots.txt file to the location in your assets S# bucket or
   | Cloudfront distribution.
   |
   */

   'redirect_robots_txt' => true,

   /*
   |--------------------------------------------------------------------------
   | Redirect www to the root domain
   |--------------------------------------------------------------------------
   |
   | When this option is enabled, Vapor will redirect requests to the
   | www subdomain to the root domain. If the option is disabled,
   | vapor will redirect the root domain to the www subdomain.
   |
   */

   'redirect_www' => true,
];
class EnsureOnNakedDomain
{
   /**
    * Handle the incoming request.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  callable  $next
    * @return mixed
    */
   public function handle($request, $next)
   {
       if ('https://'.$request->getHttpHost() === $_ENV['APP_VANITY_URL']) {
           return $next($request);
       }

       if (config('vapor.redirect_to_root') === true &&
           strpos($request->getHost(), 'www.') === 0) {
           return new RedirectResponse(Str::replaceFirst(
               'www.', '', $request->fullUrl()
           ), 301);
       }

       if (config('vapor.redirect_to_root') === false &&
           strpos($request->getHost(), 'www.') === false) {
           return new RedirectResponse(str_replace(
               $request->getScheme().'://',
               $request->getScheme().'://www.',
               $request->fullUrl()
           ), 301);
       }

       return $next($request);
   }
}

デフォルトでは、'redirect_to_root' => trueに設定されているため、www.が付与されていれば、自動的に除去されてしまう。そこで、'redirect_to_root' => falseにしてやれば、下の分岐に入るためオリジナルでwww.を付与するMiddleware(例ではRedirectToWwwUrl)を作成せずとも、vaporが自動的に行なってくれる。

ふつうに使う分には、これで解決なわけだが、ある特別な場合に問題が発生する。それは、サブドメインを使用する場合だ。

Route::domain(config('app.domain'))->group(function () {
   Route::get('/', 'HomeController')->name('home');
   // ...
});

Route::domain('sub.' . config('app.domain'))->group(function () {
   Route::get('/', 'Sub\HomeController')->name('sub.home');
   // ...
});

vapor-coreのコード(EnsureOnNakedDomain)を見れば分かると思うが、①www.を除去する、②www.を付与する、の2パターンしか存在しない。

つまり、sample.comにアクセスした場合は、問題なくwww.sample.comにリダイレクトされるが、sub.sample.comにアクセスした場合は、www.sub.sample.comとなってしまう。

このような問題を回避する方法を紹介しよう。

ここから先は

575字

¥ 1,000

この記事が気に入ったらサポートをしてみませんか?