1 什麼是 API 應用程式?
傳統上,當人們說他們使用 Rails 作為“API”時,他們的意思是 在其 Web 應用程式旁邊提供可透過程式設計訪問的 API。 例如,GitHub 提供了 一個 API,你 可以從您自己的自定義客戶端使用。
隨著客戶端框架的出現,越來越多的開發人員開始使用 Rails 構建一個在他們的 Web 應用程式和其他本地應用程式之間共享的後端 應用程式。
例如,Twitter 在其網站中使用其 公共 API 應用程式,它構建為消耗 JSON 資源的靜態站點。
而不是使用 Rails 生成與伺服器通訊的 HTML 透過表單和連結,許多開發人員將他們的 Web 應用程式視為 只是一個 API 客戶端,以 HTML 形式使用 JavaScript 交付,使用 JSON API。
本指南包含了構建一個為 JSON 資源提供服務的 Rails 應用程式。 API 客戶端,包括客戶端框架。
2 為什麼要為 JSON API 使用 Rails?
很多人在考慮構建 JSON API 時遇到的第一個問題 使用 Rails 是:“不是使用 Rails 來吐出一些 JSON 矯枉過正嗎?我不應該 只使用像 Sinatra 這樣的東西?”。
對於非常簡單的 API,這可能是正確的。然而,即使在很網頁吃重的(HTML-heavy) 應用程式,應用程式的大部分邏輯都在 view 之外 層。
大多數人使用 Rails 的原因是它提供了一組預設值 允許開發人員快速啟動和執行,而無需做很多瑣碎的工作 決定。
讓我們來看看 Rails 提供的一些開箱即用的東西 仍然適用於 API 應用程式。
在中介軟體層處理:
- 重新載入:Rails 應用程式支援透明重新載入。即使 您的應用程式變大並且為每個請求重新啟動伺服器變得 不可行。
- 開發模式:Rails 應用程式帶有用於開發的智慧預設值, 在不影響生產時間效能的情況下使開發愉快。
- 測試模式:同上開發模式。
- 日誌記錄:Rails 應用程式記錄每個請求,並具有一定的詳細程度 適合當前模式。開發中的 Rails 日誌包含資訊 關於請求環境、資料庫查詢、基本效能 資訊。
- 安全性:Rails 檢測並阻止 IP 欺騙 攻擊 和控制代碼 時序中的加密簽名 攻擊 感知方式。不知道什麼 IP欺騙攻擊還是定時攻擊?確切地。
- 引數解析:想要將您的引數指定為 JSON 而不是作為
URL 編碼的字串?沒問題。 Rails 將為您解碼 JSON 並製作
它在
params
中可用。想要使用巢狀的 URL 編碼引數嗎?那 也有效。 - 條件獲取:Rails 處理條件
GET
(ETag
和Last-Modified
) 處理請求頭並返回正確的回應頭和狀態 程式碼。您需要做的就是使用stale?
簽入您的 controller,Rails 將為您處理所有 HTTP 詳細資訊。 - HEAD 請求:Rails 會透明地將
HEAD
請求轉換為GET
請求, 並在出路時僅返回標題。這使得HEAD
在 所有 Rails API。
雖然您顯然可以根據現有的 Rack 中介軟體來構建這些, 這個列表展示了預設的 Rails 中介軟體堆疊提供了很多 value 的,即使您“只是生成 JSON”。
在 Action Pack 層處理:
- Resourceful Routing:如果您正在構建 RESTful JSON API,您希望成為 使用 Rails 路由器。從 HTTP 到 controllers 的乾淨和正常對映 意味著不必花時間考慮如何 model 你的 API 的 HTTP。
- URL 生成:路由的另一面是 URL 生成。根據良好的 API 在 HTTP 上包含 URL(參見 GitHub Gist API 例如)。
- 標頭和重定向回應:
head :no_content
和redirect_to user_url(current_user)
派上用場。當然,你可以手動 新增回應頭,但為什麼呢? - 快取:Rails 提供頁面、action 和片段快取。片段快取 在構建巢狀的 JSON 物件時特別有用。
- 基本、摘要和 Token 身份驗證:Rails 提供開箱即用的支援 用於三種 HTTP 身份驗證。
- 檢測:Rails 有一個檢測 API,可以觸發註冊 各種事件的處理程式,例如 action 處理、傳送檔案或 資料、重定向和資料庫查詢。每個事件的有效載荷都帶有 相關資訊(對於action處理事件,payload包括 controller、action、引數、請求格式、請求方法、 請求的完整路徑)。
- 生成器:生成資源並獲取 model 通常很方便, controller、測試存根和在單個命令中為您建立的路由 進一步調整。 migrations 和其他的也一樣。
- 外掛:許多第三方庫都支援 Rails,減少了 或消除設定和粘合圖書館和圖書館的成本 網路框架。這包括覆蓋預設生成器、新增 Rake 任務,並尊重 Rails 選擇(如記錄器和快取後端)。
當然,Rails 啟動過程也將所有註冊的元件粘合在一起。
例如,Rails 啟動過程就是使用您的 config/database.yml
檔案
設定 Active Record 時。
簡短的版本是:你可能沒有想過 Rails 的哪些部分 即使您刪除 view 層仍然適用,但答案是 成為其中的大部分。
3 基本設定
如果您正在構建一個首先作為 API 伺服器的 Rails 應用程式,並且 最重要的是,您可以從更有限的 Rails 子集開始並新增功能 如所須。
3.1 建立一個新的應用程式
您可以生成一個新的 api Rails 應用程式:
$ rails new my_api --api
這將為您做三件事:
- 設定您的應用程式以從一組更有限的中介軟體開始 比正常。具體來說,它將不包括任何主要有用的中介軟體 預設用於瀏覽器應用程式(如 cookies 支援)。
- 使
ApplicationController
繼承自ActionController::API
而不是ActionController::Base
。與中介軟體一樣,這將忽略任何 Action Controller modules 提供主要由瀏覽器使用的功能 應用程式。 - 將生成器設定為跳過生成 views、helpers 和資產時 你生成了一個新資源。
3.2 更改現有應用程式
如果您想採用現有應用程式並將其設為 API 應用程式,請閱讀 以下步驟。
在 config/application.rb
中,在 Application
的頂部新增以下行
類定義:
config.api_only = true
在 config/environments/development.rb
中,設定 config.debug_exception_response_format
設定在開發模式下發生錯誤時回應中使用的格式。
要呈現帶有除錯資訊的 HTML 頁面,請使用 value :default
。
config.debug_exception_response_format = :default
要呈現保留回應格式的除錯資訊,請使用 value :api
。
config.debug_exception_response_format = :api
預設情況下,當 config.api_only
設定為 true 時,config.debug_exception_response_format
設定為 :api
。
最後,在 app/controllers/application_controller.rb
內部,而不是:
class ApplicationController < ActionController::Base
end
做:
class ApplicationController < ActionController::API
end
4 選擇中介軟體
預設情況下,API 應用程式帶有以下中介軟體:
ActionDispatch::HostAuthorization
Rack::Sendfile
ActionDispatch::Static
ActionDispatch::Executor
ActiveSupport::Cache::Strategy::LocalCache::Middleware
ActionDispatch::RequestId
ActionDispatch::RemoteIp
Rails::Rack::Logger
ActionDispatch::ShowExceptions
ActionDispatch::DebugExceptions
ActionDispatch::ActionableExceptions
ActionDispatch::Reloader
ActionDispatch::Callbacks
ActiveRecord::Migration::CheckPending
Rack::Head
Rack::ConditionalGet
Rack::ETag
請參閱內部中介軟體 機架指南的部分以獲取有關它們的更多資訊。
其他外掛,包括 Active Record,可能會新增額外的中介軟體。在 一般而言,這些中介軟體與您所使用的應用程式型別無關 構建,並在僅 API 的 Rails 應用程式中有意義。
您可以透過以下方式獲取應用程式中所有中介軟體的列表:
$ bin/rails middleware
4.1 使用快取中介軟體
預設情況下,Rails 會新增一箇中間件,該中介軟體提供根據 應用程式的設定(預設為 memcache)。這意味著 內建的 HTTP 快取將依賴它。
例如,使用 stale?
方法:
def show
@post = Post.find(params[:id])
if stale?(last_modified: @post.updated_at)
render json: @post
end
end
對 stale?
的呼叫將比較請求中的 If-Modified-Since
標頭
與 @post.updated_at
。如果標頭比上次修改的要新,則此
action 將返回“304 Not Modified”回應。否則,它將呈現
回應並在其中包含 Last-Modified
標頭。
通常,此機制根據每個客戶端使用。快取中介軟體
允許我們在客戶端之間共享這種快取機制。我們可以啟用
對 stale?
的呼叫中的跨客戶端快取:
def show
@post = Post.find(params[:id])
if stale?(last_modified: @post.updated_at, public: true)
render json: @post
end
end
這意味著快取中介軟體將儲存 Last-Modified
value
獲取 Rails 快取中的 URL,並將 If-Modified-Since
標頭新增到任何
對同一 URL 的後續入站請求。
將其視為使用 HTTP 語義的頁面快取。
4.2 使用 Rack::Sendfile
當您在 Rails controller 中使用 send_file
方法時,它會設定
X-Sendfile
標頭。 Rack::Sendfile
負責實際傳送
檔案。
如果你的前端伺服器支援加速檔案傳送,Rack::Sendfile
將實際的檔案傳送工作解除安裝到前端伺服器。
您可以設定前端伺服器使用的標頭名稱
這個目的在適當的使用 config.action_dispatch.x_sendfile_header
環境的設定檔案。
您可以瞭解有關如何使用 Rack::Sendfile
的更多資訊
the Rack::Sendfile 中的前端
文件。
這是一些流行伺服器的此標頭的一些 values,一旦這些伺服器設定為支援 加速檔案傳送:
# Apache 和 lighttpd
config.action_dispatch.x_sendfile_header = "X-Sendfile"
# Nginx
config.action_dispatch.x_sendfile_header = "X-Accel-Redirect"
確保設定您的伺服器以支援以下選項
Rack::Sendfile
文件中的說明。
4.3 使用 ActionDispatch::Request
ActionDispatch::Request#params
將從客戶端獲取 JSON 中的引數
格式並使它們在 params
內的 controller 中可用。
要使用它,您的客戶端需要使用 JSON 編碼的引數發出請求
並將 Content-Type
指定為 application/json
。
這是 jQuery 中的一個示例:
jQuery.ajax({
type: 'POST',
url: '/people',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({ person: { firstName: "Yehuda", lastName: "Katz" } }),
success: function(json) { }
});
ActionDispatch::Request
會看到 Content-Type
和你的引數
將會:
{ :person => { :firstName => "Yehuda", :lastName => "Katz" } }
4.4 使用 Session 中介軟體
以下用於會話管理的中介軟體被排除在 API 應用程式之外,因為它們通常不需要 sessions。如果您的 API 客戶端之一是瀏覽器,您可能需要將其中之一添加回:
ActionDispatch::Session::CacheStore
ActionDispatch::Session::CookieStore
ActionDispatch::Session::MemCacheStore
重新新增這些的技巧是,預設情況下,它們透過 session_options
新增時(包括 session key),所以你不能只新增一個 session_store.rb
初始值設定項,新增
use ActionDispatch::Session::CookieStore
並讓 sessions 照常執行。 (要明確:sessions
可能有效,但您的 session 選項將被忽略 - 即 session key 將預設為 _session_id
)
您必須在中介軟體之前的某處設定相關選項,而不是初始化程式
構建(如 config/application.rb
)並將它們傳遞給您首選的中介軟體,如下所示:
# 這也設定了 session_options 供下面使用
config.session_store :cookie_store, key: '_interslice_session'
# 所有 session 管理都需要(不考慮 session_store)
config.middleware.use ActionDispatch::Cookies
config.middleware.use config.session_store, config.session_options
4.5 其他中介軟體
Rails 附帶了許多其他中介軟體,您可能希望在 API 應用程式,尤其是當您的 API 客戶端之一是瀏覽器時:
Rack::MethodOverride
ActionDispatch::Cookies
ActionDispatch::Flash
可以透過以下方式新增任何這些中介軟體:
config.middleware.use Rack::MethodOverride
4.6 刪除中介軟體
如果您不想使用預設包含在僅 API 中的中介軟體 中介軟體集,您可以使用以下方法將其刪除:
config.middleware.delete ::Rack::Sendfile
請記住,刪除這些中介軟體將刪除對某些 Action Controller 中的功能。
5 選擇 Controller Modules
API 應用程式(使用 ActionController::API
)帶有以下內容
controller modules 預設:
-
ActionController::UrlFor
:使url_for
和類似的 helpers 可用。 -
ActionController::Redirecting
:支援redirect_to
。 -
AbstractController::Rendering
和ActionController::ApiRendering
:對渲染的基本支援。 -
ActionController::Renderers::All
:支援render :json
和好友。 -
ActionController::ConditionalGet
:支援stale?
。 -
ActionController::BasicImplicitRender
:如果沒有明確的回應,請確保返回空回應。 -
ActionController::StrongParameters
:支援引數過濾與 Active Model 質量分配相結合。 -
ActionController::DataStreaming
:支援send_file
和send_data
。 -
AbstractController::Callbacks
:支援before_action
和 類似的 helpers。 -
ActionController::Rescue
:支援rescue_from
。 -
ActionController::Instrumentation
:支援儀表 由 Action Controller 定義的掛載機制(參見 the instrumentation 指南 用於 有關此的更多資訊)。 -
ActionController::ParamsWrapper
:將引數雜湊包裝成巢狀雜湊, 這樣您就不必指定傳送 POST 請求的根元素。 -
ActionController::Head
:支援返回沒有內容,只有標題的回應。
其他外掛可能會新增額外的 modules。您可以獲得所有modules的列表
包含在 rails 控制檯中的 ActionController::API
中:
irb> ActionController::API.ancestors - ActionController::Metal.ancestors
=> [ActionController::API,
ActiveRecord::Railties::ControllerRuntime,
ActionDispatch::Routing::RouteSet::MountedHelpers,
ActionController::ParamsWrapper,
... ,
AbstractController::Rendering,
ActionView::ViewPaths]
5.1 新增其他 Module
所有的Action Controller modules都知道他們的依賴modules,所以你可以感覺到 可以自由地將任何 modules 包含到您的 controllers 中,並且所有依賴項都將被 包括並設定。
您可能想要新增一些常見的 modules:
-
AbstractController::Translation
:支援l
和t
本地化 和翻譯方法。 - 支援基本、摘要或 token HTTP 身份驗證:
ActionController::HttpAuthentication::Basic::ControllerMethods
ActionController::HttpAuthentication::Digest::ControllerMethods
ActionController::HttpAuthentication::Token::ControllerMethods
-
ActionView::Layouts
:渲染時支援佈局。 -
ActionController::MimeResponds
:支援respond_to
。 -
ActionController::Cookies
:支援cookies
,其中包括 支援簽名和加密的 cookies。這需要 cookies 中介軟體。 -
ActionController::Caching
:支援為API controller快取view。請注意 您需要像這樣手動指定 controller 內的快取儲存:class ApplicationController < ActionController::API include ::ActionController::Caching self.cache_store = :mem_cache_store end
Rails 不會自動傳遞此設定。
新增 module 的最佳位置是在您的 ApplicationController
中,但您可以
還將 modules 新增到單個 controllers。
回饋
我們鼓勵您幫助提高本指南的品質。
如果您發現任何拼寫錯誤或資訊錯誤,請提供回饋。 要開始回饋,您可以閱讀我們的 回饋 部分。
您還可能會發現不完整的內容或不是最新的內容。 請務必為 main 新增任何遺漏的文件。假設是 非穩定版指南(edge guides) 請先驗證問題是否已經在主分支上解決。 請前往 Ruby on Rails 指南寫作準則 查看寫作風格和慣例。
如果由於某種原因您發現要修復的內容但無法自行修補,請您 提出 issue。
關於 Ruby on Rails 的任何類型的討論歡迎提供任何文件至 rubyonrails-docs 討論區。