Macros and functions for routing apps and services in LFE+Yaws
REST is a party, and you know it.
The name started with more than just a party reference: the intent was for this library to be used to develop RESTful services more easily by having one's routes more clear: LFe rEpresentational State Transfer.
But the web is more than REST, so everybody gets to play. The name's staying, though.
This project assumes that you have rebar
and [lfetool]() installed somwhere in your $PATH
.
This project depends upon the following, which are automatically installed
to the deps
directory of this project when you run make compile
:
Just add it to your rebar.config
deps:
{deps, [
...
{lfest, ".*", {git, "git@github.com:lfex/lfest.git", "master"}}
]}.
If you have created your project with lfetool
, you can download
lfeest
with the following:
$ make get-deps
Or, you can have it download automatically when you compile:
$ make compile
Create your application/service routes with the (defroutes ...)
form.
Here is an example:
(include-lib "deps/lfest/include/macros.lfe")
(defroutes
;; top-level
('GET "/"
(lfest-html-resp:ok "Welcome to the Volvo Store!"))
;; single order operations
('POST "/order"
(create-order (lfest:get-data arg-data)))
('GET "/order/:id"
(get-order id))
('PUT "/order/:id"
(update-order id (lfest:get-data arg-data)))
('DELETE "/order/:id"
(delete-order id))
;; order collection operations
('GET "/orders"
(get-orders))
;; payment operations
('GET "/payment/order/:id"
(get-payment-status id))
('PUT "/payment/order/:id"
(make-payment id (lfest:get-data arg-data)))
;; error conditions
('ALLOWONLY
('GET 'POST 'PUT 'DELETE)
(lfest-json-resp:method-not-allowed))
('NOTFOUND
(lfest-json-resp:not-found "Bad path: invalid operation.")))
Note that this creates a routes/3
function which can then be called
in the out/1
function that is required of a YAWS appmod module.
For an example of this in action, see this mini REST-api.
A few important things to note here:)
arg-data
passed from
YAWS; this contains all the data you could conceivably need to process a
request. (You may need to import the yaws_api.hrl
in your module to
parse the data of your choice, though.)(defroutes ...)
macro; the variable will then be
accessible from the function you provide in that route.(defroutes ...)
macro generates the routes/3
function; it's
three arguments are the HTTP verb (method name), the path info (a list of
path segments, with the ":varname"
segments converted to varname
/
variable segments), and then the arg-data
variable from YAWS.lfest needs to provide YAWS with an out/1
function. The location of this
function is configured in your etc/yaws.conf
file in the
<appmods ...>
directives (it can be repeated for supporting multiple
endpoints).
YAWS will call this function with one argument: the YAWS arg
record
data. Since this function is the entry point for applications running under
YAWS, it is responsible for determining how to process all requests.
The out/1
function in lfest-based apps calls the routes/3
function
generated by the (defroutes ...)
mamcro.
The route definition macro does some pretty heavy remixing of the routes
defined in (defroutes ...)
. The route definition given in the "Usage"
section above actually expands to the following LFE before being compiled to
a .beam
:
#((define-function routes
(match-lambda
(('GET () arg-data)
(call 'lfest-html-resp 'ok "Welcome to the Volvo Store!"))
(('POST ("order") arg-data)
(create-order (call 'lfest 'get-data arg-data)))
(('GET ("order" id) arg-data) (get-order id))
(('PUT ("order" id) arg-data)
(update-order id (call 'lfest 'get-data arg-data)))
(('DELETE ("order" id) arg-data) (delete-order id))
(('GET ("orders") arg-data) (get-orders))
(('GET ("payment" "order" id) arg-data) (get-payment-status id))
(('PUT ("payment" "order" id) arg-data)
(make-payment id (call 'lfest 'get-data arg-data)))
((method p a)
(when
(not
(if (call 'erlang '=:= 'GET method)
'true
(if (call 'erlang '=:= 'POST method)
'true
(if (call 'erlang '=:= 'PUT method)
'true
(call 'erlang '=:= 'DELETE method))))))
(call 'lfest-json-resp 'method-not-allowed))
((method path arg-data)
(call 'lfest-json-resp 'not-found "Bad path: invalid operation."))))
6)
When it is compiled, the routes/3
function is available for use from
wherever you have defined your routes.
Apache Version 2 License
Copyright © 2014-2019, Duncan McGreggor oubiwann@gmail.com
[](Named page links below ...)