だ。ログ。

開発とかスノボとかやきうとか。

youtube埋め込みタグのレスポンシブ対応

あまりcssとhtmlに詳しくないので、とりあえずコピペできるようにする。

	<div>
		<iframe src="//www.youtube.com/embed/hogehogehoge" frameborder="0" width="560" height="315" allowfullscreen></iframe>
	</div>

iframeの典型的な埋め込みコード、このままコピペすればyoutube自体は参照が可能。
ただし、スマホで観た場合はiframeのサイズになってしまうので横幅がはみ出してしまいレスポンシブ対応が上手くいかない。

	<div style="position:relative; width:100%; padding-top:56.25%;">
		<iframe src="//www.youtube.com/embed/hogehogehoge" frameborder="0" width="560" height="315" allowfullscreen style="position:absolute;top:0;right:0;width:100%;height:100%;"></iframe>

直接スタイルに書いてしまっているが、スタイルでまとめればこのまま使えると言う感じ。

EC-CUBE3で現在のページを調べる

共通ヘッダーだけど見出しだけ変えたい。とか有るので結構必要となる「現在のページ」
$_SERVERから見るだけでなくEC-CUBEの機能でも備えている。

	$request = $app['request_stack']->getMasterRequest();
	$now_page = $request->attributes->get('_route');

$now_pageに現在表示されているページ名を取得できる。
変数の値によってタイトルを設定すれば動的にページの見出し等で使える。

EC-CUBE3でHTMLタグを使う

よく忘れる。
ページに設定された変数で特にありがちなのはフリーエリア部分。
そのままだとHTMLタグの囲み文字が&から始まる文字列に変換される。

{{ Product.free_area }}

これを

{{ Product.free_area|raw }}

とrawurlencodeを設定するとHTMLタグが適用される。

ELB配下のサーバーを指定して確認する

テスト段階でしか使えないネタ。
いまや複数台構成が当たり前となって時代、ロードバランサーを最上位に置いて下位に複数台のWebサーバー
ELB配下にあるサーバーはELBさんが割り振ったご機嫌次第なんてこともあったり。

スティッキーセッションを使って各サーバーに一定時間割り振られると言う事もあるのだが
基本的にELBの死活監視はpingパスを使うと

ping パス
	
HTTP または HTTPS リクエストの送信先。
HTTP または HTTPS GET リクエストが ping ポートと ping パス上のインスタンスに発行されます。ロードバランサーが応答タイムアウト時間内に "200 OK" 以外の応答を受信した場合、インスタンスは異常と見なされます。応答に本文が含まれている場合、アプリケーションは Content-Length ヘッダーを 0 以上の値に設定するか、値を "chunked" に設定した Transfer-Encoding を指定する必要があります。
デフォルト: /index.html

と書かれている。index.htmlにpingして応答があれば生きている。
応答がなければサーバーへの割り振りを止めて他のサーバーへ割り振りを行うと言う感じだ。

なので、エンジニア全員がA,B,Cのサーバーが有りBのサーバーにアクセスした状態でテストしたい場合、A,Cのサーバーのindex.htmlを抜いてしまえば死活監視からBに全てが割り振られる。
まあ当たり前な人には当たり前なのだろうが、自分みたくそこまでAWSのサービスに詳しく無い人間からすると、ルールを逆手に取った理にかなったやり方だなーと納得してしまった。

AWSのELBにSSLをインストールして、EC2にEC-CUBE3をインストールして運用するとSSLがおかしくなるはなし

f:id:rider_dice:20170929183753p:plain
図のようにシングルだろうが複数台構成だろうが構わないが、ELB上にSSL証明書をインストールするSSL Terminationと言う技法でELBまではSSL、そこから先は非SSLとして通信すると言うやり方が今のトレンドらしい。

この状況でEC-CUBE3をインストールすると問題が起こる。

インストールStep2のSSL強制が効かない

https://hogehoge.com/install.php/step2

このようなURLでSSLでアクセスする、しかし強制SSLのチェックが出来ない。ブラウザではhttpsで送信しているし鍵マークもついている。
でも、チェックが出来ない。仕方がないから後でconfig.ymlから強制すれば良いや。と放置してインストール自体は完了。

config.ymlからSSL設定をする

/app/config/eccube/config.yml

auth_magic: hogehogefugafuga
password_hash_algos: sha256
shop_name: だ。のしょっぷ。
force_ssl: null
admin_allow_host: {  }
cookie_lifetime: 0
cookie_name: eccube
locale: ja
timezone: Asia/Tokyo
pageinrange: false
trusted_proxies_connection_only: false
trusted_proxies: {  }
eccube_install: 1

この

force_ssl: 1

null -> 1に変更して、ページを表示させる。

SSLがリダイレクトしてしまい、ブラウザからページを表示する事が出来ない。

問題点

1. ELBまでは443のSSLプロトコルで来ているね。と言う事で証明書を確認する。
2. ELBはサーバーに通信をHTTPで行う。

ELB→EC2がHTTP通信になってしまう事が大きな問題。

var_dump($_SERVER);

##この辺を確認
  ["HTTP_X_FORWARDED_PORT"]=>
  string(3) "443"
  ["HTTP_X_FORWARDED_PROTO"]=>
  string(5) "https"
  ["HTTP_CONNECTION"]=>

これで確認すると解るが、通常のサーバーに証明書が突っ込まれたサーバーだと、通信がHTTPSだから
$_SERVER['HTTPS'] = onと言う設定が入っているが、この項目が見つからない。
そりゃそうだ、HTTP通信だからSSLじゃねーよとEC2は判断する。

解決策

EC-CUBEのコントローラとなるindex.phpに以下を記述する
/html/index.php

if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
    $_SERVER['HTTPS'] = 'on';
}

リダイレクトでも良いんだけど、カートの内容保持の問題もあるので問題としてはEC-CUBEのコントローラが$_SERVER['HTTPS']が存在するかを聞いて、SSL強制のチェックのフラグの可否をするので、HTTPSがありますよ。と言う事を$_SERVER変数に持たせる。

この設定を入れて管理画面にhttpsでアクセスすると、チェックボックスを選択する事ができてフロントページSSLの無限リダイレクトを回避する事ができた。
EC-CUBEと言う特性上、ELBまでSSLだから入り口出口は必ずSSLで暗号化されてるし問題無い。と言う判断も出来る事は出来るが見た目上の信頼もある。
それと、出来るのであればHTTPSですと明示させる事も必要だと思う。

今後AWSを使ったECサイト構築、それも複数台構成を考える人が多くなると思う。
多分みんなこの部分で引っ掛かる。HTTP_X_FORWARDED_PROTOでググれば文献は一発で出て来るが、サーバー屋、Web屋どちら共に長けている人も少ない。
と言う事でメモっておく。

この辺、もう少しEC-CUBE使ってる技術者の人間がノウハウとして共有すれば幸せなんだろうが、メシの種なのだろう。

EC-CUBE3のデータコミットタイミング

ちゃんとコアプログラムを読んでいない自分が悪いが、EC-CUBE標準の使い方をした場合のデータベースのコミットはページが遷移した後になる。
何が言いたいかと言うと、コントローラ上で処理が完了してリダイレクトの前に一旦ブレイクポイントを置いてデータベースを確認してもまだコミットされていない。

例として以下の会員登録のコントローラで説明する
/src/Eccube/Controller/EntryController.php

                case 'complete':
                    log_info('会員登録開始');
                    $Customer
                        ->setSalt(
                            $app['eccube.repository.customer']->createSalt(5)
                        )
                        ->setPassword(
                            $app['eccube.repository.customer']->encryptPassword($app, $Customer)
                        )
                        ->setSecretKey(
                            $app['eccube.repository.customer']->getUniqueSecretKey($app)
                        );

                    $CustomerAddress = new \Eccube\Entity\CustomerAddress();
                    $CustomerAddress
                        ->setFromCustomer($Customer);

                    $app['orm.em']->persist($Customer);
                    $app['orm.em']->persist($CustomerAddress);
                    $app['orm.em']->flush();

                    log_info('会員登録完了');

会員登録完了ページにてログとして会員登録開始と会員登録完了と言うログが書き込まれている。
ただ、このログでブレイクしてデータベースに会員情報は渡っていない。

                        log_info('本会員登録画面へリダイレクト');
                        return $app->redirect($activateUrl);

リダイレクトが終わった段階でデータが反映されるので、コミット自体はされておらず登録したデータからアレコレってのが出来ない。
基本的に現状あるEC-CUBEの骨子を変える事自体があまり良い事ではないからやりたくないが、やる場合は事後が基本となりそうなのでメモ。