Defines the Phoenix router. A router is the heart of a Phoenix application. It has three main responsibilities: * It defines a plug pipeline responsible for handling upcoming requests and dispatch those requests to controllers and other plugs * It hosts configuration for the router and related entities (like plugs) * It provides a wrapper for starting and stopping the router in a specific web server We will explore those responsibilities next. ## Routing The router provides a set of macros for generating routes that dispatches to a specific controller and action. Those macros are named after HTTP verbs. For example: defmodule MyApp.Router do use Phoenix.Router pipe_through :browser get "/pages/:page", PageController, :show end The `get/3` macro above accepts a request of format "/pages/VALUE" and dispatches it to the show action in the `PageController`. Phoenix's router is extremely efficient, as it relies on Elixir pattern matching for matching routes and serving requests. ### Helpers Phoenix automatically generates a module `Helpers` inside your router which contains named helpers to help developers generate and keep their routes up to date. Helpers are automatically generated based on the controller name. For example, the route: get "/pages/:page", PageController, :show will generate a named helper: MyApp.Router.Helpers.page_path(:show, "hello") "/pages/hello" MyApp.Router.Helpers.page_path(:show, "hello", some: "query") "/pages/hello?some=query" The named helper can also be customized with the `:as` option. Given the route: get "/pages/:page", PageController, :show, as: :special_page the named helper will be: MyApp.Router.Helpers.special_page_path(:show, "hello") "/pages/hello" ### Scopes and Resources The router also supports scoping of routes: scope path: "/api/v1", as: :api_v1 do get "/pages/:id", PageController, :show end For example, the route above will match on the path `"/api/v1/pages/:id" and the named route will be `api_v1_page_path`, as expected from the values given to `scope/2` option. Phoenix also provides a `resources/4` macro that allows developers to generate "RESTful" routes to a given resource: defmodule MyApp.Router do use Phoenix.Router pipe_through :browser resources "/pages", PageController, only: [:show] resources "/users", UserController, except: [:destroy] end Finally, Phoenix ships with a `mix phoenix.router` task that nicely formats all routes in a given router. We can use it to verify all routes included in the router above: $ mix phoenix.router page_path GET /pages/:id PageController.show/2 user_path GET /users UserController.index/2 user_path GET /users/:id/edit UserController.edit/2 user_path GET /users/new UserController.new/2 user_path GET /users/:id UserController.show/2 user_path POST /users UserController.create/2 PUT /users/:id UserController.update/2 PATCH /users/:id UserController.update/2 One can also pass a router explicitly as argument to the task: $ mix phoenix.router MyApp.Router Check `scope/2` and `resources/4` for more information. ## Pipelines and plugs Once a request arrives to the Phoenix router, it performs a series of transformations through pipelines until the request is dispatched to a desired end-point. Such transformations are defined via plugs, as defined in the [Plug](http://github.com/elixir-lang/plug) specification. Once a pipeline is defined, it can be piped through per scope. For example: defmodule MyApp.Router do use Phoenix.Router scope path: "/" do pipe_through :browser # browser related routes and resources end scope path: "/api" do pipe_through :api # api related routes and resources end end By default, Phoenix ships with three pipelines: * `:before` - a special pipeline that is always invoked before any route matches * `:browser` - a pipeline for handling browser requests * `:api` - a pipeline for handling api requests All pipelines are invoked after a matching route is found, with exception of the `:before` pipeline which is dispatched before any attempt to match a route. ### :before pipeline Those are the plugs in the `:before` pipeline in the order they are defined. How each plug is configured is defined in a later sections. * `Plug.Static` - serves static assets. Since this plug comes before the router, serving of static assets is not logged * `Plug.Logger` - logs incoming requests * `Plug.Parsers` - parses the request body when a known parser is available. By default parsers urlencoded, multipart and json (with poison). The request body is left untouched when the request content-type cannot be parsed * `Plug.MethodOverride` - converts the request method to `PUT`, `PATCH` or `DELETE` for `POST` requests with a valid `_method` parameter * `Plug.Head` - converts `HEAD` requests to `GET` requests and strips the response body * `Plug.Session` - a plug that sets up session management. Note that `fetch_session/2` must still be explicitly called before using the session as this plug just sets up how the session is fetched * `Phoenix.CodeReloader` - a plug that enables code reloading for all entries in the `web` directory. It is configured directly in the Phoenix application ### :browser pipeline The following plugs are in the browser pipeline: * `:fetch_session` - calls the `Plug.Conn.fetch_session/2` that effectively fetches the session and makes it available in the connection ### :api pipeline Currently there are no plugs in the `:api` pipeline. ### Customizing pipelines You can define new pipelines at any moment with the `pipeline/2` macro: pipeline :secure do plug :token_authentication end And then in a scope (or at root): pipe_through [:api, :secure] Pipelines are always defined as overridable functions which means they can be easily extended. For example, we can extend the api pipeline directly and add security: pipeline :api do plug :super plug :token_authentication end Where `plug :super` will invoke the existing pligs in the api pipeline. In general though, it is preferred to define new pipelines then modify existing ones. ## Router configuration All routers are configured directly in the Phoenix application environment. For example: config :phoenix, YourApp.Router, secret_key_base: "kjoy3o1zeidquwy1398juxzldjlksahdk3" Phoenix configuration is split in two categories. Compile-time configuration means the configuration is read during compilation and changed it at runtime has no effect. Most of the compile-time configuration is related to pipelines and plugs. On the other hand, runtime configuration is accessed during or after your application is started and can be read through the `config/2` function: YourApp.Router.config(:port) YourApp.Router.config(:some_config, :default_value) ### Compile-time * `:session` - configures the `Plug.Session` plug. Defaults to `false` but can be set to a keyword list of options as defined in `Plug.Session`. For example: config :phoenix, YourApp.Router, session: [store: :cookie, key: "_your_app_key"] * `:parsers` - sets up the request parsers. Accepts a set of options as defined by `Plug.Parsers`. If parsers are disabled, parameters won't be explicitly fetched before matching a route and functionality dependent on parameters, like the `Plug.MethodOverride`, will be disabled too. Defaults to: [accept: ["*/*"], json_decoder: Poison, parsers: [:urlencoded, :multipart, :json]] * `:static` - sets up static assets serving. Accepts a set of options as defined by `Plug.Static`. Defaults to: [at: "/", from: Mix.Project.config[:app]] ### Runtime * `:http` - the configuration for the http server. Currently uses cowboy and accepts all options as defined by `Plug.Adapters.Cowboy`. Defaults to: [port: 4000] * `:https` - the configuration for the https server. Currently uses cowboy and accepts all options as defined by `Plug.Adapters.Cowboy`. Defaults to: [port: 4040] * `:secret_key_base` - a secret key used as base to generate secrets to encode cookies, session and friends. Defaults to nil as it must be set per application * `:url` - configuration for generating URLs throughout the app. Accepts the host, scheme and port. Defaults to: [host: "localhost"] ## Web server Starting a router as part of a web server can be done by invoking `YourApp.Router.start/0`. Stopping the router is done with `YourApp.Router.stop/0`. The web server is configured with the `:http` and `:https` options defined above.