How to share config across handlers
View Sourceconfig is one value, set once at startup, that every request can
read. You need it when your handlers all want the same things: a
database pool, a cache, settings you read at boot. It saves you
from capturing them in a closure for every handler, using a global,
or passing them through the per-request meta map (which is meant
for data about one request).
Pass config at startup
Pass config when you start the service. It can be any term, most
often a map of handles, and the same value reaches every request:
{ok, Pid} = livery:start_service(#{
http => #{port => 8080},
config => #{db => DbPool, cache => CachePid},
router => Router
}).Read it in a handler
Use livery_req:config/1 for the whole value:
list_users(Req) ->
#{db := Db} = livery_req:config(Req),
livery_resp:json(200, json:encode(users:all(Db))).or livery_req:config/2,3 to pull one key out of a map config:
list_users(Req) ->
Db = livery_req:config(db, Req),
livery_resp:json(200, json:encode(users:all(Db))).Middleware sees the same request, so it can read config too:
call(Req, Next, _Opts) ->
Limiter = livery_req:config(limiter, Req),
enforce(Limiter, Req, Next).Use a record, if you prefer
Config can be any term, so a record works too, and gives you a little more structure than a map:
%% -record(app, {db, cache}).
show(Req) ->
App = livery_req:config(Req),
livery_resp:json(200, fetch(App#app.db)).Set config on a single listener
livery:start_listener/2 takes config the same way:
{ok, _} = livery:start_listener(livery_h1, #{
port => 8080, config => App, stack => Stack, handler => Handler
}).A config inside one protocol's map on start_service/1 overrides
the service-wide one for that listener. This helps when, for example,
your TLS listener should use a different pool.
Test with config in the spec
You can still test handlers without a socket: put config in the
request spec.
Cap = livery_test_adapter:run([], fun my_app:list_users/1,
#{method => <<"GET">>, config => #{db => FakeDb}}).Notes
configis service-wide and set at startup: the same value for every request, read-only. Use it for shared handles and settings.metaholds data a middleware writes for one request only, like the authenticated user or a trace id. See Write a custom middleware.
See also
- Concept: Request and response model
- Guide: Write a custom middleware
- Reference:
livery_req,livery_service