View Source Antikythera.Router (antikythera v0.5.1)
Defines the antikythera routing DSL.
Routing macros
This module defines macros to be used in each gear's Router module.
The names of the macros are the same as the HTTP verbs: get, post, etc.
The macros take the following 4 arguments (although you can omit the last and just pass 3 of them):
- URL path pattern which consists of '/'-separated segments. The 1st character must be '/'. To match against incoming request path to a pattern you can use placeholders. See examples below for the usage.
- Controller module.
Antikythera expects that the module name given here does not contain
GearName.Controller.as a prefix; it's automatically prepended by antikythera. - Name of the controller action as an atom.
- Keyword list of options.
Currently available options are
:fromand:as. See below for further explanations.
Example
If you define the following router module,
defmodule MyGear.Router do
use Antikythera.Router
static_prefix "/static"
websocket "/ws"
get "/foo" , Hello, :exact_match
post "/foo/:a/:b" , Hello, :placeholders
put "/foo/bar/*w", Hello, :wildcard
endThen the following requests are routed as:
GET "/foo"=>MyGear.Controller.Hello.exact_match/1is invoked withpath_matches:%{}POST "/foo/bar/baz"=>MyGear.Controller.Hello.placeholders/1is invoked withpath_matches:%{a: "bar", b: "baz"}PUT "/foo/bar/abc/def/ghi"=>MyGear.Controller.Hello.wildcard/1is invoked withpath_matches:%{w: "abc/def/ghi"}
Note that
- Each controller action is expected to receive a
Antikythera.Connstruct and returns aAntikythera.Connstruct. Antikythera.Connstruct has a fieldrequestwhich is aAntikythera.Requeststruct.- Matched segments are URL-decoded and stored in
path_matchesfield inAntikythera.Request. If the result of URL-decoding is nonprintable binary, the request is rejected.
Websocket endpoint
To enable websocket interaction with clients, you must first define MyGear.Websocket module.
See Antikythera.Websocket for more details about websocket handler module.
Then invoke websocket/1 macro in your router.
websocket "/ws_path_pattern"The path pattern may have placeholders in the same way as normal routes. GET request with appropriate headers to this path will initialize a websocket connection using the HTTP 1.1 upgrade mechanism.
If your gear does not interact with clients via websocket, simply don't invoke websocket/1 macro in your router.
Static file serving
You can serve your static assets by placing them under /priv/static directory in your gear project.
The endpoint to be used can be specified by static_prefix/1 macro.
For example, if you add
static_prefix "/assets"to your router, you can download /priv/static/html/index.html file by sending GET request to the path /assets/html/index.html.
If you don't need to serve static assets, just don't call static_prefix/1 macro in your router.
Currently, static assets served in this way are NOT automatically gzip compressed,
even if acceept-encoding: gzip request header is set.
It is recommended to use CDN to deliver large static assets in production.
See also Antikythera.Asset for usage of CDN in delivery of static assets.
Web requests and gear-to-gear (g2g) requests
Antikythera treats both web requests and g2g requests in basically the same way.
This means that if you define a route in your gear one can send request to the route using both HTTP and g2g communication.
If you want to define a route that can be accessible only via g2g communication, specify from: :gear option.
get "/foo", Hello, :action1, from: :gear
post "/bar", Hello, :action2, from: :gearSimilarly passing from: :web makes the route accessible only from web request.
When dealing with multiple routes, only_from_web/1 and only_from_gear/1 macros can be used.
For example, the following routes definition is the same as above one.
only_from_gear do
get "/foo", Hello, :action1
post "/bar", Hello, :action2
endReverse routing
To generate URL path of a route (e.g. a link in HTML), you will want to refer to the route's path.
For this purpose you can specify :as option.
For example, you have the following router module
defmodule MyGear.Router do
use Antikythera.Router
get "/foo/:a/:b/*c", Hello, :placeholders, as: :myroute
endBy writing this the router automatically defines a function myroute_path/4,
which receives segments that fill placeholders and an optional map for query parameters.
MyGear.Router.myroute_path("segment_a", "segment_b", ["wildcard", "part"])
=> "/foo/segment_a/segment_b/wildcard/part
MyGear.Router.myroute_path("segment_a", "segment_b", ["wildcard", "part"], %{"query" => "param"})
=> "/foo/segment_a/segment_b/wildcard/part?query=paramReverse routing helper functions automatically URI-encode all given arguments.
If websocket endpoint is enabled, you can get its path with MyGear.Router.websocket_path/0.
Also if static file serving is enabled, path prefix for static files can be obtained by MyGear.Router.static_prefix/0.
Per-API timeout
You can specify timeout for each API by :timeout option.
The timeout is specified in milliseconds.
For example, the following API times out after 60 seconds.
get "/foo", Hello, :long_action, timeout: 60_000The maximum timeout is determined by :gear_action_max_timeout configuration in config/config.exs.
The default value is 10 seconds, which can be configured by GEAR_ACTION_TIMEOUT environment variable.