-
Notifications
You must be signed in to change notification settings - Fork 5
Referential Transparency
Cowmachine goes to great lengths to help your
controller functions be as referentially
transparent as possible. By "referentially transparent" we mean that
given the same input Context
the function will return the same
output {Result, Context}
and that side effects will be
insignificant from the point of view of Cowmachine's execution.
Since controller functions are generally referentially transparent, many things are easier -- testing, debugging, and even static analysis and reasoning about your web application.
The passed Context
always contains the Cowboy request map and the
application-specific data you put in there.
Besides a Cowboy request map()
the Context can also be a record.
If it is a record then the first element of the record (i.e. the
second tuple element as the first is the type of the record) must be
the Cowboy request.
Example:
-record(mycontext, { Req :: cowboy_req:req(), foo, bar, etc }.
This record option is used by Zotonic, where the context contains information about the vhost being used and other Zotonic specific state. In Zotonic the request is actually optional, only when controllers are called then the request must be defined.
If you don't use your own record then you can use the following functions to access metadata in the cowboy request:
NewContext = cowmachine_req:set_metadata(Key, Value, Context)
SomeTerm = cowmachine_req:get_metadata(Key, Context)
The get_metadata
will return undefined
for undefined keys.
The streamed body feature exists to allow
constollers to consume or produce request/response bodies a hunk at a
time without ever having the whole thing in memory. While the
continuation-passing style used in the streaming API is friendly to
general functional analysis, due to the necessary side-effect of
reading or writing to sockets the stream bodies cannot be treated in
quite the same way as other uses of the Context
interface. Luckily,
it is easy to inspect a Context
to see if this is the case in any
individual controller or request instance.