Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Organization

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

開発環境では起こらなかったのですが、本番にデプロイしたところ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 を作成する必要がある場合 (例えばメールの送信) 、自力で指定する必要があります。

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

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
2
Help us understand the problem. What are the problem?