Good code is its own best documentation. As you’re about to add a comment, ask yourself, ‘How can I improve the code so that this comment isn’t needed?’ Improve the code and then document it to make it even clearer. – Steve McConnell, Code Complete 作者
Rails 5.0 提供了 API mode 可以產生一個 Rails 專案「只 Only」作為 API server,但這是不必要的,除非你想擠一點效能出來,但是你會關掉整個 ActionView。
拆開到 /api/v1,例如:
scope :path => '/api/v1/', :module => "api_v1", :as => 'v1', :defaults => { :format => :json } do
resources :topics
end
params[:event][:name]
,前者則偏好簡單設計成 params[:name]
# app/controllers/api_controller.rb
class ApiController < ActionController::Base
end
rails g controller api_v1::events
# app/controllers/api_v1/events_controller.rb
class ApiV1::EventsController < ApiController
end
render :json => { :message => "your error message" }, :status => 400
400
時。重點包括:
手動測試的方式,參考 https://ihower.tw/cs/web-apis.html#sec3
JSON.parse
出來的時間物件,前者要多轉一次 as_json
,不然會差一點。不像瀏覽器有 cookie,每個 request 都必須帶有我們自行設計的 token 參數,我們才可以識別使用者。
首先是 Model 部分,主要新增一個欄位 authentication_token
欄位,並用 Devise.friendly_token 產生亂數 token:
產生 Migration,指令是 rails g migration add_token_to_users
class AddTokenToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :authentication_token, :string
add_index :users, :authentication_token, :unique => true
User.find_each do |u|
puts "generate user #{u.id} token"
u.generate_authentication_token
u.save!
end
end
end
修改 User Model 加上generate_authentication_token
方法:
class User < ApplicationRecord
#.....
before_create :generate_authentication_token
def generate_authentication_token
self.authentication_token = Devise.friendly_token
end
end
接著我們在 ApiController 上實作 before_action :authenticate_user_from_token!
,如果有帶auth_token
就進行登入(但這裡沒有強制一定要登入):
class ApiController < ActionController::Base
before_action :authenticate_user_from_token!
def authenticate_user_from_token!
if params[:auth_token].present?
user = User.find_by_authentication_token( params[:auth_token] )
# Devise: 設定 current_user
sign_in(user, store: false) if user
end
end
end
如果是強制一定要登入的action
,用法跟之前 Device 一樣,例如以下整個 EventsController 就一定要登入了,不然會回傳錯誤:
class ApiV1::EventsController < ApiController
before_action :authenticate_user!
end
上述的部分也可以安裝現成的套件 https://github.com/gonzalo-bulnes/simple_token_authentication
接下來實作 API 的登入和登出,讓使用者可以用帳號密碼,或是 facebook access_token 來登入,來換得上述的 authentication_token
。也就是 POST /api/v1/login
先用 email 帳號密碼登入,拿到 auth_token:
用戶端拿到 auth_token 後,之後的每個 request 都必須帶入 auth_token。
上述的作法是整合 Devise 和 omniauth-facebook,如果不想整合 Devise 的話,也可以自己把 current_user
做出來,例如這份 Example code