Combo.Router (combo v0.10.0)
View SourceDefines a router.
The router provides a set of macros for defining routes which dispatch requests to specific plugs.
Examples
defmodule MyApp.Web.Router do
use Combo.Router
get "/health", MyApp.Web.HealthCheck, []
get "/pages/:page", MyApp.Web.PageController, :show
endRoutes
get/3, post/3, put/3, and other macros named after HTTP verbs are used
to define routes. For example:
get "/", MyApp.Web.PageController, :homedefines a route that matches a GET request to / and dispatches the request
to plug MyApp.Web.PageController with opts :home.
Path parameters
Path parameters capture values from the URL. There're several types of them:
- segment parameters
- partial segment parameters
- catch-all parameters
Segment parameters
Segment parameters capture an entire path segment.
Define them in the route path with : followed by a name. And, the captured
values are strings, cast them yourself if you need other data types.
For example:
get "/pages/:page", MyApp.Web.PageController, :showWhen a request hits the route with the URL "/pages/hello", the router
populates conn.path_params["page"] with "hello".
Partial segment parameters
Partial segment parameters capture a trailing portion from within a single path segment.
Define them in the route path with : followed by a name. And, the captured
values are strings, cast them yourself if you need other data types.
For example:
get "/user-:name", MyApp.Web.UserController, :showWhen a request hits the route with the URL "/user-john", the router
populates conn.path_params["name"] with "john".
Catch-all parameters
Catch-all parameters capture one or more remaining path segments.
Define them in the route path with * followed by a name. And, the captured
values are a list of strings - one per path segment, cast them yourself if
you need other data types.
For example:
get "/files/*path", MyApp.Web.FileController, :showWhen a request hits the route with the URL "/files/images/logo.png", the
router populates conn.path_params["path"] with ["images", "logo.png"].
Accessing path parameters
To access path parameters, use conn.params or conn.path_params.
Or, pattern match directly in the controller's action:
defmodule MyApp.Web.PageController do
def show(conn, %{"page" => page}) do
# ...
end
endCombining different types of path parameters
All these types of path parameters can be combined, with the only restriction being that catch-all parameters must appear at the end.
Ordering routes
Routes are matched from top to bottom.
For example, the request with the URL "/pages/hello" will never hit the second route, because it always hits the first route.
get "/pages/:page", MyApp.Web.PageController, :show
get "/pages/hello", MyApp.Web.PageController, :helloRoute helpers
Combo generates a Helpers module that provides helper functions for building
paths or URLs from your routes.
Helpers are automatically generated based on the module name of plug. For example, the route:
get "/pages/:page", PageController, :showwill generate the following helper:
MyApp.Web.Router.Helpers.page_path(conn, :show, "hello")
"/pages/hello"
MyApp.Web.Router.Helpers.page_path(conn, :show, "hello", some: "query")
"/pages/hello?some=query"
MyApp.Web.Router.Helpers.page_url(conn, :show, "hello")
"http://example.com/pages/hello"
MyApp.Web.Router.Helpers.page_url(conn, :show, "hello", some: "query")
"http://example.com/pages/hello?some=query"If the route contains catch-all parameters, parameters for those should be given as a list:
MyApp.Web.Router.Helpers.file_path(conn, :show, ["images", "logo.png"])
"/file/images/logo.png"The helper can also be customized with the :as option. Given the route:
get "/pages/:page", PageController, :show, as: :special_pagethe helper will be:
MyApp.Web.Router.Helpers.special_page_path(conn, :show, "hello")
"/pages/hello"See Combo.Router.Helpers for more information.
Scopes
It is very common to namespace routes under a scope. For example:
scope "/", MyApp.Web do
get "/users/:id", UserController, :show
get "/posts/:id", PostController, :show
endThis syntax is convenient to use, since you don't have to repeat MyApp.Web.
prefix on all routes.
You can also use path parameters. For example:
scope "/api/:version", MyApp.Web do
get "/pages/:id", PageController, :show
endSee scope/2 for more information.
Pipes
Once a request arrives at the router, it passes through a series of pipes before being dispatched to the matched route.
Pipes are only invoked if a route is matched. If no route matches, no pipe is invoked.
A pipe can be either a plug, or a pipeline.
Pipe names
Every pipe has a name.
- For function plugs, the pipe name is the atom name of the function.
- For module plugs, the pipe name is the module name.
- For pipelines, the pipe name is the atom name of the pipeline.
Defining pipes
To define a plug, see Plug for more information.
To define a pipeline, see pipeline/2 for more information.
Using pipes
See pipe_through/1 for more information.
Resources
Combo.Router doesn't provide resources related macro that allows to generate
"RESTful" routes to a given resource. For clarity, we recommend defining them
explicitly.
An example for resources:
get "/users", UserController, :index
get "/users/new", UserController, :new
post "/users", UserController, :create
get "/users/:id", UserController, :show
get "/users/:id/edit", UserController, :edit
patch "/users/:id", UserController, :update
put "/users/:id", UserController, :update
delete "/users/:id", UserController, :deleteAn example for singleton resources:
get "/user/new", UserController, :new
post "/user", UserController, :create
get "/user", UserController, :show
get "/user/edit", UserController, :edit
patch "/user", UserController, :update
put "/user", UserController, :update
delete "/user", UserController, :deleteListing routes
Combo ships with a mix combo.routes task that formats all routes in a given
router. We can use it to list all routes included in the router.
Summary
Reflection
Returns the compile-time route info and runtime path params for a request.
Functions
Defines a route to handle a connect request to the given path.
Defines a route to handle a delete request to the given path.
Forwards a request at the given path to a plug.
Defines a route to handle a get request to the given path.
Defines a route to handle a head request to the given path.
Defines a route based on an arbitrary HTTP method.
Defines a route to handle a options request to the given path.
Defines a route to handle a patch request to the given path.
Defines pipes to apply within the current scope.
Defines a pipeline, which is a named collection of plugs.
Adds a plug into a pipeline.
Defines a route to handle a post request to the given path.
Defines a route to handle a put request to the given path.
Returns all routes information from the given router.
Defines a scope.
See scope/2 for more information.
See scope/2 for more information.
Expands a module with the current scope's module.
Defines a route to handle a trace request to the given path.
Reflection
Returns the compile-time route info and runtime path params for a request.
The path can be either a string or the path_info segments.
A map of metadata is returned with the following keys:
:log- the configured log level, such as:debug.:path_params- the map of runtime path params.:pipes- the pipes for the route's scope, such as[:browser].:plug- the plug to dispatch the route to, such asMyApp.Web.PostController.:plug_opts- the options to pass when calling the plug, such as:index.:route- the string route pattern, such as"/posts/:id".
Examples
iex> Combo.Router.route_info(MyApp.Web.Router, "GET", "/posts/123")
%{
log: :debug,
path_params: %{"id" => "123"},
pipe_through: [:browser],
plug: MyApp.Web.PostController,
plug_opts: :show,
route: "/posts/:id",
}
iex> Combo.Router.route_info(MyRouter, "GET", "/not-exists")
:error
Functions
Defines a route to handle a connect request to the given path.
connect "/events/:id", EventController, :actionSee match/5 for options.
Defines a route to handle a delete request to the given path.
delete "/events/:id", EventController, :actionSee match/5 for options.
Forwards a request at the given path to a plug.
This is commonly used to forward all subroutes to another Plug. For example:
forward "/admin", SomeLib.AdminDashboardThe above will allow SomeLib.AdminDashboard to handle /admin,
/admin/foo, /admin/bar/baz, and so on. Furthermore,
SomeLib.AdminDashboard does not to be aware of the prefix it
is mounted in. From its point of view, the routes above are simply
handled as /, /foo, and /bar/baz.
A common use case for forward is for sharing a router between
applications or breaking a big router into smaller ones.
However, in other for route generation to route accordingly, you
can only forward to a given Combo.Router once.
The router pipes will be invoked prior to forwarding the connection.
Examples
scope "/", MyApp do
pipe_through [:browser, :admin]
forward "/admin", SomeLib.AdminDashboard
forward "/api", ApiRouter
end
Defines a route to handle a get request to the given path.
get "/events/:id", EventController, :actionSee match/5 for options.
Defines a route to handle a head request to the given path.
head "/events/:id", EventController, :actionSee match/5 for options.
Compatibility with Plug.Head
Templates provided by combo_new include Plug.Head in their endpoint,
which converts HEAD requests into regular GET requests. Therefore, if you
intend to use head/4 in your router, you need to move Plug.Head to
your router in a way it does not conflict with the paths given to head/4.
Defines a route based on an arbitrary HTTP method.
Useful for defining routes not included in the built-in macros.
The catch-all verb, :*, may also be used to match all HTTP methods.
Options
:scoped_module- whether to apply the scoped module to the route. Defaults totrue.:as- the name as an atom or a string, to override the default naming for the route helpers. Ifnil, it will not generate route helpers for this route.:private- the private data as a map to merge into the connection when a route matches. Default to%{}.:assigns- the data as a map to merge into the connection when a route matches. Default to%{}.:log- the level to log the route dispatching under. Defaults to:debug. Can be set tofalseto disable the logging. Route dispatching logging contains information about how the route is handled (which plug is called, what plug_opts are given, what parameters are available and which pipes are used). It is separated from the plug level logging. To alter the plug log level, please see https://hexdocs.pm/combo/Combo.Logger.html#module-dynamic-log-level.
Examples
# match the GET method
match :get, "/events/:id", EventController, :get
# match all methods
match :*, "/any", CatchAllController, :any
Defines a route to handle a options request to the given path.
options "/events/:id", EventController, :actionSee match/5 for options.
Defines a route to handle a patch request to the given path.
patch "/events/:id", EventController, :actionSee match/5 for options.
Defines pipes to apply within the current scope.
The pipes are specified by their names.
Examples
pipe_through [:browser, :require_authenticated_user]Multiple invocations
pipe_through/1 can be invoked multiple times within the same scope. Each
invocation appends new pipes, which are applied to all routes after
the pipe_through/1 invocation. For example:
scope "/" do
pipe_through [:browser]
get "/", HomeController, :index
pipe_through [:require_authenticated_user]
get "/settings", UserController, :edit
end/ applies :browser only, while /settings applies both :browser and
:require_authenticated_user. To avoid confusion, we recommend to use a
single pipe_through at the top of each scope:
scope "/" do
pipe_through [:browser]
get "/", HomeController, :index
end
scope "/" do
pipe_through [:browser, :require_authenticated_user]
get "/settings", UserController, :edit
end
Defines a pipeline, which is a named collection of plugs.
Pipelines must be defined at the root of router.
Examples
pipeline :api do
plug :put_current_user
plug :dispatch
endA scope can use this pipeline as:
scope "/" do
pipe_through :api
endSee pipe_through/1 for more information.
Adds a plug into a pipeline.
See pipeline/2 for more information.
Defines a route to handle a post request to the given path.
post "/events/:id", EventController, :actionSee match/5 for options.
Defines a route to handle a put request to the given path.
put "/events/:id", EventController, :actionSee match/5 for options.
Returns all routes information from the given router.
Defines a scope.
Scopes are for grouping routes under a common path prefix or a common module prefix.
Examples
scope path: "/api/v1", module: API.V1 do
get "/pages/:id", PageController, :show
endThe generated route above will match on the path "/api/v1/pages/:id" and
will dispatch requests to plug API.V1.PageController with opts :show.
A named helper api_v1_page_path will also be generated.
Options
:path- the path scope as a string.:module- the module scope as a module name. When set tofalse, it resets all nested:moduleoptions.:as- the route naming scope as a string or an atom. When set tofalse, it resets all nested:asoptions.:private- the private data as a map to merge into the connection when a route matches.:assigns- the data as a map to merge into the connection when a route matches.:log- the level to log the route dispatching under. Defaults to:debug. Can be set tofalseto disable the logging. Route dispatching logging contains information about how the route is handled (which plug is called, what plug_opts are given, what parameters are available and which pipes are used). It is separate from the plug level logging. To alter the plug log level, please see https://hexdocs.pm/combo/Combo.Logger.html#module-dynamic-log-level.
Shortcuts
A scope can also be defined with shortcuts.
# specify path and module
scope "/api/v1", API.V1 do
get "/pages/:id", PageController, :show
end
# specify path, module and options
scope "/api/v1", API.V1, as: :api, do
get "/pages/:id", PageController, :show
end
# specify path only
scope "/api/v1" do
get "/pages/:id", API.V1.PageController, :show
end
# specify path and options
scope "/api/v1", as: :api, do
get "/pages/:id", API.V1.PageController, :show
end
# specify module only
scope API.V1 do
get "/pages/:id", PageController, :show
end
# specify module and options
scope API.V1, as: :api, do
get "/pages/:id", PageController, :show
end
See scope/2 for more information.
See scope/2 for more information.
Expands a module with the current scope's module.
It's useful when you need to reference scoped modules in other contexts, such as passing them as options.
Examples
scope "/admin", Admin do
# UserController is expanded to Admin.UserController
get "/users", ProxyPlug, handler: scoped_module(UserController)end
Defines a route to handle a trace request to the given path.
trace "/events/:id", EventController, :actionSee match/5 for options.