每個連線要求進來都會先在 Phoenix 找找看有沒有相對應的位置,我們先來看看我們目前的 Router 長怎樣,
打開 lib/blog_web/router.ex
這邊 use BlogWeb, :router 讓他可以使用 pipeline, scope 等特殊寫法 (其實是 macro 但不在我們的範圍內)
defmodule BlogWeb.Router do
use BlogWeb, :router
這邊定義了叫 :browser 的這個 pipeline 要通過哪些 plug,
就是給瀏覽器連線用的 pipeline
代表只要有 pipe_through 的連線要求都會執行這些 plug,
這邊稍微看過大概在幹嘛就可以了
pipeline :browser do
plug :accepts, ["html"] # 檢查連線要求的 content-types 來判斷要不要允許
plug :fetch_session # 從連線讀取 session 與 cookies
plug :fetch_live_flash # 從 cookies 裡拿出 flash store
plug :put_root_layout, {BlogWeb.LayoutView, :root} # 設定最外層的 layout
plug :protect_from_forgery # 防止 CSRF(跨站請求偽造) 等攻擊
plug :put_secure_browser_headers # 加上增加安全性的 headers
end
這一個 pipeline 是給 api 使用的,跟上面的比少了很多限制
pipeline :api do
plug :accepts, ["json"]
end
每一個連線進來的時候,由上而下開始檢查 scope 裡的路徑
先從最上面的這一個 scope "/"
開始
scope "/", BlogWeb do
pipe_through :browser
resources "/notes", NoteController
get "/", PageController, :index
end
拿我們首頁來說,當我們一打開 http://localhost:4000
就是路徑 /
他會從 scope 比對到 scope "/"
然後進來比對到 get "/"
,
所以他會去執行 BlogWeb.PageController
這個模組裡面的 index
方法
假如我們想要在 http://localhost:4000/posts
列出所有的 posts 我們可以寫一行get "/posts", PostController, :index
並把要顯示的內容寫在 BlogWeb.PostController
模組的 index
方法內。
另外他有提供一個把一套 CRUD 要用到的路徑整理成一個方法
resources
拿產生器生的resources "/notes", NoteController
來說,這裡面包含了這些get "/notes", NoteController, :index get "/notes/new", NoteController, :new post "/notes", NoteController, :create get "/notes/:id", NoteController, :show get "/notes/:id/edit", NoteController, :edit patch "/notes/:id", NoteController, :update put "/notes/:id", NoteController, :update delete "/notes/:id", NoteController, :delete
這邊有預設關閉的 API 專用路徑 /api
# Other scopes may use custom stacks.
# scope "/api", BlogWeb do
# pipe_through :api
# end
其他後面的這個系列還不會用到,
這系列所有的東西都會在 scope "/", BlogWeb
內。
這邊要注意的是,
因為他是從上面比對下來的,所以順序很重要
所以寫
get "users/:id" UserController, :show
get "users/new" UserController, :new
那 "users/new" 將永遠不會被連到,因為他會優先比對第一個,並把 "new" 成 :id 變數帶進去 controller