gensym

プログラミングと読書、勉強に関するメモ

Phoenix の check origin エラー [Elixir]

Phoenix の本番環境で Websocket をいじっていると、突然エラーを吐き動かなくなった。

[error] Could not check origin for Phoenix.Socket transport.

This happens when you are attempting a socket connection to
a different host than the one configured in your config/
files. For example, in development the host is configured
to "localhost" but you may be trying to access it from
"127.0.0.1". To fix this issue, you may either:

  1. update [url: [host: ...]] to your actual host in the
     config file for your current environment (recommended)

  2. pass the :check_origin option when configuring your
     endpoint or when configuring the transport in your
     UserSocket module, explicitly outlining which origins
     are allowed:

        check_origin: ["https://example.com",
											                        "//another.com:888", "//other.com"]

サーバサイドをいじっていなかったので不思議に思って色々調べてみると、config ファイルで指定したホスト名と違ったためエラーになっていたらしい。
よく見ると config では example.com だったが、ブラウザはいつの間にか www.example.com になっていた。
この食い違いが原因だ。

修正は Endpoint に check_origin を指定する。

# config/prod.exs
#...
config :example, Example.Endpoint,
  check_orign: ["https://example.com", "//*.example.com"], # これを指定

どちらでアクセスしても無事動いた。
参考: elixir - How to fix error 'Could not check origin for Phoenix.Socket transport'? (Phoenix 1.2.1) - Stack Overflow

Phoenix を本番環境で起動する [Elixir]

環境: ubuntu 16.04, Elixir 1.4.4, Phoenix 1.2.1

Phoenix は開発時とほぼ同じような感じで動かせるが、多少の前準備と設定が必要になる。
あらかじめ Phoenixmysql をインストールして、Letsencrypt 辺りで証明書を取得しておく。
sym.hateblo.jp

# config/prod.exs
use Mix.Config

config :example, Example.Endpoint,
  force_ssl: [port: 443, hsts: true, rewrite_on: [:x_forwarded_proto]],
  url: [scheme: "https", host: "example.com", port: 443],
  cache_static_manifest: "priv/static/manifest.json",
  http: [port: 80],
  https: [port: 443,
    keyfile: "/etc/letsencrypt/archive/example.com/privkey1.pem",
    certfile: "/etc/letsencrypt/archive/example.com/fullchain1.pem",
    cacertfile: "/etc/letsencrypt/archive/example.com/fullchain1.pem"]

......

https: 内部で証明書や秘密鍵の場所を指定し、 force_ssl: で https 通信を強制している。
以下のコマンドで依存ライブラリのインストールとアセットファイルのコンパイルをする。
Rails における Asset Pipeline と Bundle のようなものか。

# ライブラリのインストール、コンパイル
$ mix deps.get --only prod
$ MIX_ENV=prod mix compile

# アセットファイルのコンパイル
$ brunch build --production
$ MIX_ENV=prod mix phoenix.digest

# データベースのマイグレーション
$ MIX_ENV=prod mix ecto.migrate

# サーバの起動
$ MIX_ENV=prod mix phoenix.server

サーバはデーモン起動が面倒な感じなので、tmux で起動している。

参考: Introduction · Phoenix

プログラミングElixir

プログラミングElixir

CarrierWave で画像の exif 情報を削除する [Rails]

Carrierwave は Rails 用の画像アップローダで、元々のファイルに exif 情報が含まれていた場合はそのまま保存してしまう。
多くの人に公開する画像ならば、なるべくこれらの情報は削除しておくべきだ。
mini_magick の gem をインストールした後、下のように strip メソッドを追加する。

# app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  process :strip

  def strip
    manipulate! do |img|
      img.strip
      img = yield(img) if block_given?
      img
    end
  end
end

参考: http://stackoverflow.com/questions/4753408/how-to-remove-exif-camera-data-from-image-with-carrierwave

Web API: The Good Parts [読書メモ]

Web API: The Good Parts

Web API: The Good Parts


これまでそれほど Web API に関心があったわけではないが、最近 OpenStack 辺りの http ベースのサービスを触る機会が多かったので何となく手に取った。
表紙を見たときは Java 辺りでサーバサイドのプログラムを延々と書き連ねてあるような内容を想像したが、実際はその逆だった。
ありがちなプログラムコードやサーバソフトウェアの設定法などは全くなく、API の設計それ自体に焦点を当てていて、現在主流のウェブサービスの例も豊富に紹介されている。
運営の違いによる設計の違いとその理由、著者の考えや推奨などが詳しく書いてあり、分かりやすい内容となっている。
適切な url の命名、パスの構造、セキュアで堅牢な運用方法などは Web API に限らず Web サービス全般で重要なことで、これまで曖昧なままでやってきたことを詳細に知ることが出来た。
少し前に Rails を使っていてパスとクエリパラメータどちらにしようかを悩んだことがあってちょうどその辺りも詳しく書いてあって非常に参考になった。
それほど厚くなく、値段も技術書にしては手軽だ。

ただ本書はプログラミングやサーバソフトウェアについての本ではない。
これだけ読めば直ちに Web API が作れるわけではないし、そう言う意味では全くの初心者向けの本とは言えないだろう。
すでに Web API を作っているがいまいち確信が持てないままに運用している人や、Web サービスを運用していて API が有った方が良いと思いつつも何をしたらいいのか分からない、といった人にうってつけだろうと思う。
結果的に API を作ることがなかったとしても、堅牢な Web サービスを作る上で大いに役立つだろう。

良い本だと思う。

ルーティングで文字列をモデルのパスに使用する[Rails]

rails で resources を使うと自動でパスと関連したメソッドが作られる。
例えば name 要素を持つ User モデルを作ったとして、

# config/routes.rb
...
  resources :users
...

のようにすると、id が 1 の User のパスは、
www.example.com/users/1
のようになる。
これは分かりやすくて良いのだけれど、少々不格好でスクレイピングのコントロールもしにくい。
理想としては
www.example.com/example_user
のように、モデル名を無くして、ユーザ名でアクセス出来るようにしたい。
有名どころだと TwitterGithub はこのようにしているようだ。

まずは routes.rb を書き換える。

# config/routes.rb
...
  get '/:id', to: 'users#show'
...

デフォルトの id は整数なので、to_param メソッドをオーバーライドして name を使うようにする。

# app/model/user.rb
...
  def to_param
    name
  end
...

user_path メソッドもオーバーライドする。

# app/helper/application_helper.rb
...
  def user_path(user)
    "/#{user.name}"
  end
...

test を使うときは test_helper でもオーバーライドする必要があるだろう。
とりあえず show だけだが、edit や destroy も同様に出来る。
文字列をパスに使う場合は一意性が必要になるので、インデックスは必須だ。
また、デフォルトの id を使う場合に比べて検索のパフォーマンスも低下するだろう。

Ruby の管理に rbenv を導入する

環境: macOS Sierra, Ubuntu 16.04

rbenv は ruby のバージョン管理ソフトで、変化の速い ruby 界隈では必須と言えるだろう。
まずはインストール。

brew install rbenv

このままだとパスが通っていないので、.bash_profile に追加する。

# .bash_profile
export PATH="$HOME/.rbenv/shims:$PATH"
# バージョン一覧
rbenv install -l
# バージョンを指定してインストール
rbenv install 2.4.0
# global で使うバージョンを指定する
rbenv global 2.4.0
ruby -v

でバージョンを確認して、問題なし。
参考 : http://qiita.com/Chrowa3/items/34904262f7589a60aead

  • 追記- 17/2/4

Ubuntu だと若干違う

sudo aptitude install rbenv

で rbenv をインストールできるが、このままだと ruby のインストールリストは空っぽだ。

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

ruby-build をインストールすると、一覧が得られる。
あとは Mac と同様に

rbenv install 2.4.0

から設定できる。

参考:
https://github.com/rbenv/ruby-build

Webサイトを作ったときの評価ツール

web サイトを作ったときに、効率的なレスポンスやセキュリティ、SEO などがきちんと出来ているかを調べるツール。

PageSpeed Insights
アクセスする際の効率性を調べてくれる。
リクエスト最適化やファイルの圧縮、キャッシュの利用などが出来ているか。

SSL Server Test (Powered by Qualys SSL Labs)
セキュリティをチェック。
最高スコアにするのは結構大変。
nginx ならばここが参考になる。
NginxでHTTPS : ゼロから始めてSSLの評価をA+にするまで Part 1 | インフラ・ミドルウェア | POSTD

Website Grader
パフォーマンスやセキュリティ、SEO 全て調べてくれるが、上記のサイトに比べて評価が甘め。

どのサイトもアドレスを入力するだけでよく手軽で、改善方法もある程度教えてくれる。