A bare bones http web framework that stays out of your way.
The Server
type is used to tie everything together. A Server
instance is
constructed with Server::new
and takes a Router
as an argument. Finally the
.run
method takes in a Config
as an argument and starts the webserver.
Routing is done through the Router
type. The Router
has a new
method to
construct an instance and an .add
method to add routes to the router.
The route!
macro is used to generate a route from a path and a service proxy.
A service proxy is a closure with the signature |cx: Context, req: Request| SERVICE_INSTANCE.service_endpoint(cx, req)
. The route!
macro is used as
follows:
route!(/"path"/param/"path"/"path"/param => service_proxy)
Where "path"
is a static segment that must be matched verbatim and param
is
a parameter that is captured and made available through the Param
type in the
from_parts
method in the Context
trait.
Endpoint
is entirely internal to enzyme and a user will never need to interact
with it directly. Nonetheless it is good to know how it works.
An endpoint is an async function from Request
to Response
. An endpoint is
created using Endpoint::new
taking a service proxy as an argument. The
returned endpoint is a function that takes in a Request
and evaluates the
service proxy as steps in the request evaluation.
Route functions must have the following signature:
async fn(ContextType, RequestType) -> WebResult<ResponseType>
RequestType
and ResponseType
can be any type that implements Deserialize + Default
and Serialize
respectively. The body of the request is deserialized
into what ever type is used as RequestType
and the type used as ResponseType
is serialized into json automatically. This means contract types are
automatically deserialized and serialized, you just define routes that consume
your RequestType
and return your ResponseType
and the framework does the
rest.
The Content-Length
header is required in any requests containing a body that
you wish to be automatically deserialized. A Content-Length
of 0 will prevent
deserialization of the body entirely.
ContextType
can be any type that implements the Context
trait. The
from_parts
method is used to construct the ContextType
from Parts
and
Params
. Parts
is the http::request::Parts
type from the http
crate and
contains everything in the request except the body. An example ContextType
could have members such as auth_token
and the implementation of from_parts
could parse out and evaluate the auth_token
for validity before returning the
ContextType
. Finally access to the context of the request is accomplished by
passing the ContextType
into the async route function.
Async functions used in the framework return a WebResult
type. The
WebResult
is a Result
type with the error parameter set to be a WebError
.
A WebError
is a message and an error code. The message can be anything that
implements Serialize
and the code is an StatusCode
type from the http
crate.