Help us understand the problem. What is going on with this article?

CakePHP3でリバースプロキシ経由のアクセスだとCake\Routing\Router::urlのアドレスがプライベートIPになる

More than 1 year has passed since last update.

開発環境では起こらなかったのですが、本番にデプロイしたところURLがプライベートIPになってしまいました。

問題のコード

src/Template/Layout/default.ctp
$this->assign('requestFullUrl', \Cake\Routing\Router::url(NULL, true));

テンプレートでCake\Routing\Router::urlを使ってカレントのURLを取得していました。
このURLをog:urlなどに設定していたのですが、本番でプライベートIPアドレスになったのでFacebookでシェアされた時にリンク切れになってしまいました。

原因調査

CakePHPのコードを見てみるとこちらのコードになっていました。

vendor/cakephp/cakephp/src/Routing/Router.php
    public static function url($url = null, $full = false)
    {
        ...

        if (empty($url)) {
            $output = isset($here) ? $here : $base . '/';
            if ($full) {
                $output = static::fullBaseUrl() . $output;
            }

            return $output;
        }

static::fullBaseUrl()という関数が呼び出されていて、ここに正しいドメインが指定できれば良さそうです。
更にコードを追ってみると。

vendor/cakephp/cakephp/src/Routing/Router.php
...
    /**  
     * Contains the base string that will be applied to all generated URLs
     * For example `https://example.com`
     *
     * @var string
     */
    protected static $_fullBaseUrl;
...
    public static function fullBaseUrl($base = null)
    {   
        if ($base !== null) {
            static::$_fullBaseUrl = $base;
            Configure::write('App.fullBaseUrl', $base);
        }
        if (empty(static::$_fullBaseUrl)) {
            static::$_fullBaseUrl = Configure::read('App.fullBaseUrl');
        }

        return static::$_fullBaseUrl;
    }

static::$_fullBaseUrlが空の時、config/app.phpファイルのApp.fullBaseUrlを代入するになってました。

解決方法

なので、下記の箇所を修正

config/app.php
    'App' => [
         'namespace' => 'App',
         'encoding' => env('APP_ENCODING', 'UTF-8'),
         'defaultLocale' => env('APP_DEFAULT_LOCALE', 'ja-JP'),
         'base' => false,
         'dir' => 'src',
         'webroot' => 'webroot',
         'wwwRoot' => WWW_ROOT,
         // 'baseUrl' => env('SCRIPT_NAME'),
-        'fullBaseUrl' => false,
+        'fullBaseUrl' =>  env('PROTOCOL', 'http')
+            . '://'. env('DOMAIN', 'localhost:8888'),
         'imageBaseUrl' => 'img/',

余談

念の為リファレンスを確認してみると下記のことが書かれています。
https://book.cakephp.org/3.0/ja/development/configuration.html

App.fullBaseUrl
アプリケーションのルートまでの (プロトコルを含む) 完全修飾ドメイン名です。 これは完全な URL を生成する際 に利用されます。デフォルトでは、この値は $SERVER の環境情報から生成されます。しかし、パフォーマンスを最適化したり、 他人が Host ヘッダーを操作するのを心配するならば、自分で指定すべきでしょう。CLI 環境 (シェル) ではウェブサーバーとの関連が無いので fullBaseUrl を $SERVER から読むことができません。もしシェルから URL を作成する必要がある場合 (例えばメールの送信) 、自力で指定する必要があります。

想定されていないわけ無いですよね・・・。

kgws
個人的な作業記録です。
https://giginc.co.jp
gig-inc
クリエイティブとテクノロジーでセカイをより良くする スタートアップ企業
https://giginc.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした