何年も前に社内向けにシンプルなアプリをRailsで作っていたのだけれど、長いことメンテナンスできずにいた。 Rubyのバージョンも古いし、Railsのバージョンも古かったので、バージョンアップをしないとなぁと思っていたのだけれど、やったところでまた数年後に同じ思いをすることになりそうだなぁ…と思ったので、もっとバージョンアップのしやすいSinatraに書き換えることにした。
実はSinatraを試したことくらいはあったけれど、ちゃんとデプロイまでしたことはなかったので、よい経験になった。
作ったもの
シンプルなWebAPIを作った。JSONを返すだけ。
使ったgem
- sinatra
- 言わずもがな
- sinatra-contrib
- sinatra-activerecord
- ActiveRecordを使いたかったから。
- sinatra-cors
- WebAPIなのでCORSでのアクセスを許可したかった。
- puma
- rack-bearer_auth
- Bearer認証を使いたかった。
- rerun
- ホットリロードしたかった。
ハマったところ
CORSをするための設定
CORSをするときに、Bearer認証を使っていたため、Authorizationヘッダーを追加しているのでpreflight requestが発生するようになり、エラーが発生していた。
Before
# app.rb require 'sinatra' require 'sinatra/activerecord' require 'sinatra/contrib' require "sinatra/cors" require 'rack/bearer_auth' use Rack::BearerAuth::Middleware do match path: "/api/v1/foos", via: [:all] do |token| AccessToken.exists?(token: token) end end set :database_file, 'config/database.yml' set :allow_origin, '*' set :allow_methods, 'GET' set :allow_headers, 'content-type,if-modified-since' set :allow_credentials, true # 略
After
調査をした結果、以下の修正が必要だった。
- preflight requestが発生しているので、OPTIONSメソッドの許可が必要になった
- カスタムヘッダーとしてAuthorizationを追加することを明示すること
- OPTIONSメソッドへのリクエストは不要なヘッダーが削除されるのでBearer認証は除外しないといけない
# app.rb require 'sinatra' require 'sinatra/activerecord' require 'sinatra/contrib' require "sinatra/cors" require 'rack/bearer_auth' use Rack::BearerAuth::Middleware do match path: "/api/v1/foos", via: [:get] do |token| # <= via: [:get]に変更してoptionsの場合を対象外に変更 AccessToken.exists?(token: token) end end set :database_file, 'config/database.yml' set :allow_origin, '*' set :allow_methods, 'GET,OPTIONS' # <= OPTIONSを追加 set :allow_headers, 'content-type,if-modified-since,authorization' # <= authorizationを追加 set :allow_credentials, true # 略
これでCORSできるようになった!
最初のCORSの設定を行ったとき、当初はBearer認証を実装してない状態だったのでシンプルなCORSでpreflight requestが発生していなかったので気づかなかった。 Bearer認証を実装したときには、CORSを試さずに単にREST Clientで試して問題なかったので、気づかなかった。 普通にデプロイ後に一応手動テストを行ったらCORSに失敗して非常に焦った…😅
pumaコマンドでsinatraの起動
pumaコマンドで起動する場合、config.ruファイルが必要。
# config.ru require './app' run Sinatra::Application
ホットリロードの導入
単にpumaで起動した場合、ファイルを修正しても反映されないので、一旦pumaを止めてまた起動しなければならない。
bundle exec puma
rerunを使うことで、ファイルを修正したらホットリロードされるようになる。
bundle exec rerun puma
修正が即反映されてとっても捗る。
まとめ
これでRailsアプリを1つメンテナンスしなくて済むようになったのでよかった。Sinatraならメンテ不要というわけでもないけれど、まぁ基本的にbundle updateだけで済みそうでしょう。
久々にブログを書いたけれど、やっぱりメモ的な内容でもいいからアウトプットしていかないとなぁ〜と思った。管理職になってからコードを書く量がめちゃ減っているので頑張っていきたい。