rails-apiでcookieを使う
最近、rails-apiでcookieを使うような機会が何度かあったので、その方法をメモしておきます。
tl;dr
rails-api with cookie · pocke/rails-api-with-cookie-sample@11ccaf1
前置き
rails-api
のデフォルトでは、cookieが無効化されています。
そのため、セッション管理などでcookieを有効にするにはひと手間必要です。
試してみる
では、実際に試してみましょう。
以下のコマンドでrails-api
の新規プロジェクトを開始します。
$ rails-api new rails-api-with-cookie-sample
例として、cookieを使用して訪問回数を返すAPIを作成します。
# app/controllers/application_controller.rb class ApplicationController < ActionController::API def root t = (cookies['count'] || 1).to_i cookies['count'] = t + 1 render text: "#{t} 回目の訪問です!\n" end end
# config/routes.rb Rails.application.routes.draw do root 'application#root' end
上記を一旦保存し、bin/rails s
でサーバーを起動します。
そして、APIらしくcurl
でhttp://localhost:3000
を叩いてみると、500エラーが返ってきてしまいます。
$ curl localhost:3000 -c cookie.txt -b cookie.txt # Rails のエラーページのHTMLが返ってくる…
Started GET "/" for ::1 at 2016-06-23 19:06:33 +0900 Processing by ApplicationController#root as */* Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.0ms) NameError (undefined local variable or method `cookies' for #<ApplicationController:0x00000003c7d398>): app/controllers/application_controller.rb:3:in `root' Rendered /home/pocke/.gem/ruby/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.8ms) Rendered /home/pocke/.gem/ruby/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.3ms) Rendered /home/pocke/.gem/ruby/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.5ms) Rendered /home/pocke/.gem/ruby/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (10.6ms)
どうやらcookies
メソッドが存在しないようですね。
cookies
メソッドを読み込んでみる
このメソッドはActionController::Cookies
で定義されているようなので、このモジュールをinclude
してみましょう。
# app/controllers/application_controller.rb class ApplicationController < ActionController::API include ActionController::Cookies # ココを追記! def root t = (cookies['count'] || 1).to_i cookies['count'] = t + 1 render text: "#{t} 回目の訪問です!\n" end end
$ curl localhost:3000 -c cookie.txt -b cookie.txt 1 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 1 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 1 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 1 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 1 回目の訪問です!
今度は500エラーは出なくなりましたが、何度アクセスしても1 回目の訪問です!
と言われてしまいますね。
また、cookie.txt
も作成されていないようです。
Rack middleware を読み込んでみる
cookieが有効になっていないのは、CookieをサポートするRack middlewareが読み込まれていないのが原因です。
config/application.rb
で対象のmiddlewareを読み込みましょう。
# config/application.rb module RailsApiWithCookieSample class Application < Rails::Application # ...... config.middleware.use ActionDispatch::Cookies end end
そして、railsサーバーを立ち上げ直してからもう一度curl
で叩いてみます。
$ curl localhost:3000 -c cookie.txt -b cookie.txt 1 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 2 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 3 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 4 回目の訪問です! $ curl localhost:3000 -c cookie.txt -b cookie.txt 5 回目の訪問です!
無事カウントアップされましたね!
結論
まとめると、rails-apiとcookieを同時に使うには以下の2ステップが必要です。
ApplicationController
でActionController::Cookies
をinclude- Rack middleware として
ActionDispatch::Cookies
を読み込み
別解
また、ActionDispatch::Cookies
を読み込む代わりに、config.api_only = false
とconfig/application.rb
に記述する方法もあります。
上記を実施するとActionDispatch::Cookies
が読み込まれる+セッションが有効になる効果があります。
もしセッションを使用するアプリケーションを作る場合は、api_only
をfalse
にする方法を取ったほうがよいでしょう。
See: rails-api/default_rails_four_middleware_stack.rb
参考リンク
今回作成したサンプルアプリケーション
参考にしたページなど