Apacheの前にNginxを置いた際にApache側で行う設定例

サーバーは一度設定するとなかなか次に設定することがなく、設定方法を忘れてしまいます。
今回はApacheが走っているサーバーの前段としてNginxを用意した場合にするであろう設定例です。
※ファイルの場所はUbuntuの例です。他のディストリビューションの場合はパスが変わってくるので適宜読み替えてください。

Apacheの設定

ポートを80から8080へ変更します。※例ではついでにIPv4のみにしています。
/etc/apache2/ports.conf

Listen 80
Listen 127.0.0.1:8080

Apacheのアクセスログに残すIPがリモートのIPになるようremoteipモジュールを設定します。
※何も設定しないと全てNginxの走っているサーバーのIPになってしまいます。

このモジュールの設定ファイルを作成します。
/etc/apache2/mods-available/remoteip.conf

RemoteIPInternalProxy 127.0.0.1
RemoteIPHeader        X-Forwarded-For
RemoteIPProxiesHeader X-Forwarded-By

モジュールと設定を有効化します。

$ sudo a2enmod remoteip

一般的にログフォーマットの設定では%hのほうがデフォルトで使われているのでこれを%aへ変更します。log_config

LogFormat "%v:%p %a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined

ここまでの設定を有効化します。

$ sudo apache2ctl restart

これでApache側でリモートのIPが取得できるようになります。

お疲れさまでした。


スタイルガイドをFractalで作ってみよう!

「Fractal」とはスタイルガイドジェネレーターの一種です。複数人でwebサイトを作る際に一貫性を持ってデザインやコーディングができるようにまとめたものです。
スタイルガイドにはこの他に「sc5-styleguide」「Storybook」などがあります。

今回はFractalを使ってスタイルガイドを作成してみます。
すぐにデモを作成することができるので、比較的、簡単に導入ができるかと思います。


まずは任意の箇所にディレクトリを作成します。

mkdir fractal_test

作成したディレクトリに移動します。

cd fractal_test

プロジェクトを開始するためpackage.jsonを作成します。
「package name」などと聞かれますが、自由に入力して大丈夫です。

npm init

プロジェクトにFractalをインストールします。

npm install --save @frctl/fractal

グローバルにFractalCLIツールをインストールします。

npm i -g @frctl/fractal

Fractalのセットアップをします。
質問に答えていくと「fractal_test_01(または回答したプロジェクトタイトル名)」が表示されると思います。

fractal new fractal_test_01

「fractal_test_01」に移動し、Fractalを起動します。

cd fractal_test01/
fractal start --sync

「Fractal web UI server is running!」と表示されるので、Local URLをブラウザで表示します。

Local URL: http://localhost:3000

以下の画像のようにスタイルガイドが表示されたと思います。

これでスタイルガイドの準備ができました。
それでは、ボタンのコンポーネントを登録していきます。

「components」ディレクトリ内に「btn」ディレクトリを作成し、その中に「btn_default.hbs」を作成します。

「btn_default.hbs」の中に次のコードを記載します。

<a href="#" class="btn btn_default">Default</a>

左メニューが追加されたと思います。
btn
└Btn Default

同様に「btn_primary.hbs」「btn_success.hbs」を作成します。

btn_primary.hbs

<a href="#" class="btn btn_primary">Primary</a>

btn_success.hbs

<a href="#" class="btn btn_success">Primary</a>

同様に左メニューが追加されたと思います。
このままでは、cssが適用されてませんので、componentsディレクトリに「_preview.hbs」を作成し次のコードをコピーします。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link media="all" rel="stylesheet" href="{{ path '/css/style.css' }}">
<title>Preview Layout</title>
</head>
<body>
{{{ yield }}}
</body>
</html>

その後、「public」ディレクトリの中に「/css/style.css」を作成し、cssを記載します。

すると、スタイルが適用されたと思います。

これがFractalの基本的な使い方となります。
さらに便利な使い方がわかりましたら改めて記事にしようと思います。

公式ガイド
https://fractal.build/guide/


苺が好きすぎる今日この頃

こんにちわ。
リエです。

今日から4月ですね🌸
世の中はコロナウイルスが猛威を振るっていますが、皆様体調を崩されてはいませんでしょうか。

コロナウイルスの事もありいつも以上に体調管理に努めた結果、なんと今年は1度も風邪を引いておりません。もちろんインフルエンザにもなっていません。
予防の一環ではないですが、苺をたくさん食べているのも健康に過ごせている理由の一つなんじゃないかなと思っています。

苺は元々大好きですが、去年苺の食べ比べをしてからますます好きになり、今年に入ってからほぼ毎日苺を食べていました。洗ってすぐに食べれる手軽さもいい✨

最近は普通のスーパーでも珍しい品種の苺が売っていたりと色んな苺を手軽に食べれるようになって嬉しい限りです💕

その中で私が好きな苺ベスト5をご紹介したいと思います🍓

あまおう(福岡県)

言わずと知れた苺の王様あまおう。
「あ」かい、「ま」るい、「お」おきい、「う」まい の頭文字をとって名前をつけられたそうです。名前の通り身は大きくてジューシー。甘くて味も濃い苺です。
スーパーで手軽に買えるのも嬉しいポイント☺

いちごさん(佐賀県)

いちごさんは2018年に品種登録されたばかりのかなり新しい品種です。
かわいい名前だなとスーパーで見つけて食べたのがきっかけだったのですが、今では大好きでよく買う苺の一つです。大ぶりでみずみずしくてそれでいてやさしい甘さが特徴です。あまおう同様スーパーで手軽に買えるのもありがたいです。

淡雪(鹿児島県)

淡雪は白い苺です。白い苺の先駆けとしては「初恋の香り」という品種が有名ですが、淡雪は初恋の香りに比べるとまだ手の届きやすい価格かなという感じです。(それでも高級苺ですが)身は真っ白ではなくほんのり桜色の部分がありその見た目がかわいいのです💕味は酸味が少なく甘いです。

紅ほっぺ(静岡県)

紅ほっぺはあまおう同様、馴染みのある苺ではないでしょうか。
果実は中まで赤く酸味と甘味のバランスがいい苺だと思います。
この苺もスーパーで手軽に買えるのがいいですよね♪

古都華(奈良県)

奈良県の新しいオリジナル品種です。
割と新しい品種なので他の苺に比べると知名度はまだ低いかもしません。(私も苺の食べ比べをした時に古都華のことを知りました)
果実は硬めでしっかりとしていて上品な甘さです。
古都華はお高いので💰たまにしか食べられないご褒美苺です。


まだまだ苺はシーズンなので、引き続きたくさん食べたいと思います🍓


Laravelのエラーログに情報を追加する方法

ログの拡張

開発中であればエラーはそのまま表示されるので解決は比較的容易ですが、運用中に発生した場合はエラーログから調査するので少し時間がかかります。

エラーログにはデフォルトで発生時ログインしているuserIdが一緒に出力されエラーが発生したファイル名や行番号も出力されるので基本的にはそちらからエラーの調査は行えますが、特定のレコード時だけ発生したなどになるとそれだけでは時間がかかる時があります。

なので出力されるログの内容を拡張できないかフレームワークのソースを調べたところ

Illuminate/Foundation/Exceptions/Handler.php
にcontextと目的の関数があり

contextの関数をオーバーライドすればいい様子

以下実装例

app/Exceptions/Handler.php
/**
 * ログに記載する追加情報
 */
protected function context()
{
$context = parent::context(); try { return array_merge($context, [ // 一緒に記録したい情報 'uri' => env('REQUEST_URI'), ]); } catch (Throwable $e) { return $context; } }

以上!


SolrのUAX29URLEmailTokenizerを使う

Solrにはさまざまなトークナイザーが用意されており、その中に UAX29URLEmailTokenizer があります。
このトークナイザーは基本的には StandardTokenizer と同じ挙動なのですが、以下の要素をトークンとして切り出してくれるという特徴があります。

  • ドメイン名
  • URL(http(s)://, file://, ftp://)
  • Eメールアドレス
  • IPアドレス(IPv4とIPv6)

UAX29URLEmailTokenizer を使うフィールドタイプとフィールドを定義して動作を確認してみます。

<fieldType name="text_url" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <tokenizer class="solr.UAX29URLEmailTokenizerFactory"/>
  </analyzer>
</fieldType>                                                                                                            
<field name="url_test" type="text_url" stored="true"/>

この設定で「http://www.example.com/example/です。」をトークナイズした結果は以下の通りです。

日本語の文書を扱う場合、通常の文章の部分が StandardTokenizer 相当でトークナイズされるといろいろ使い勝手が悪いので、たとえば形態素解析のトークナイザーと組み合わせることを考えます。

<fieldType name="url" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.UAX29URLEmailTokenizerFactory"/>
    <filter class="solr.TypeTokenFilterFactory" types="url_whitelist.txt" useWhitelist="true"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.KeywordTokenizerFactory"/>
  </analyzer>
</fieldType>

<field name="body" type="text_ja" stored="true"/>
<field name="url" type="url" stored="true"/>
<copyField source="body" dest="url"/>

UAX29URLEmailTokenizer の後ろに TypeTokenFilter を追加することで、必要なトークンタイプだけを残すことができます。TypeTokenFilter のホワイトリストとして url_whitelist.txt に以下の1行だけを記述して、URLだけを残すようにします。

<URL>

クエリ用のアナライザを別に定義したのは、URLのフィールドの検索では余計なトークナイズをさせずに文字列マッチ相当の動作にしたいからです。
urlフィールドをurlフィールドタイプとして定義し、text_jaフィールドタイプであるbodyフィールドのコピーフィールドにしています。

以下の文書を投入します。

[
    {"id":"1",
     "body":"昨日 http://blog.splout.co.jp/ をみた。"
    },
    {"id":"2",
     "body":"明後日は http://splout.co.jp/ をみる。"
    }
]

各フィールドにどういうトークンが納められたのかを確認します。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/terms?terms.fl=url&terms.limit=-1&omitHeader=true&wt=json'
{
  "terms":{
    "url":[
      "http://blog.splout.co.jp/",1,
      "http://splout.co.jp/",1]}}

urlフィールドにはURLだけが納められています。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/terms?terms.fl=body&terms.limit=-1&omitHeader=true&wt=json'
{
  "terms":{
    "body":[
      "co",2,
      "http",2,
      "jp",2,
      "splout",2,
      "みる",2,
      "blog",1,
      "明後日",1,
      "昨日",1]}}

bodyフィールドには通常の形態素解析結果が納められています。

この状態で検索してみます。まずは body フィールドを “http://splout.co.jp/” で。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/select?q=body%3Ahttp%5C%3A%5C%2F%5C%2Fsplout.co.jp%5C%2F'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"body:http\\:\\/\\/splout.co.jp\\/"}},
  "response":{"numFound":2,"start":0,"docs":[
      {
        "id":"2",
        "body":"明後日は http://splout.co.jp/ をみる。",
        "url":"明後日は http://splout.co.jp/ をみる。",
        "_version_":1656715432355168256},
      {
        "id":"1",
        "body":"昨日 http://blog.splout.co.jp/ をみた。",
        "url":"昨日 http://blog.splout.co.jp/ をみた。",
        "_version_":1656715432353071104}]
  }}

“http”, “splout”, “co”, “jp” がバラバラにトークンとして扱われるので、”http://blog.splout.co.jp/” も “http://splout.co.jp/” も両方がヒットしています。
次に url フィールドを同じく “http://splout.co.jp/” で。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/select?q=url%3Ahttp%5C%3A%5C%2F%5C%2Fsplout.co.jp%5C%2F'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"url:http\\:\\/\\/splout.co.jp\\/"}},
  "response":{"numFound":1,"start":0,"docs":[
      {
        "id":"2",
        "body":"明後日は http://splout.co.jp/ をみる。",
        "url":"明後日は http://splout.co.jp/ をみる。",
        "_version_":1656715432355168256}]
  }}

“http://splout.co.jp/” の方だけがヒットします。

urlフィールドの検索ではワイルドカードを使うこともできます。”http://*.splout.co.jp/” を指定して splout.co.jp のサブドメインだけを検索してみます。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/select?q=url%3Ahttp%5C%3A%5C%2F%5C%2F*.splout.co.jp%5C%2F'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":1,
    "params":{
      "q":"url:http\\:\\/\\/*.splout.co.jp\\/"}},
  "response":{"numFound":1,"start":0,"docs":[
      {
        "id":"1",
        "body":"昨日 http://blog.splout.co.jp/ をみた。",
        "url":"昨日 http://blog.splout.co.jp/ をみた。",
        "_version_":1656715432353071104}]
  }}

文章に含まれるURLやメールアドレスの扱いは案外面倒なものです。
UAX29URLEmailTokenizer をうまく使えば、自前でURLやメールアドレスを抽出してstringフィールドに格納するよりもバグも少なく取り扱うことができるでしょう。