Expand description
This module contains Iron’s middleware and handler system, the fundamental building blocks for handling HTTP requests and generating responses.
§Handlers
A Handler
will produce a Response
given a Request
. Most handlers are
functions or closures that accept a &mut Request
as an argument and return
an IronResult
containing a Response
. An IronResult
is returned instead of
directly returning a Response
in order to indicate a possibility of
failure (e.g. database timeout).
Here’s an example of a Handler
:
use iron::prelude::*;
use iron::Handler;
use iron::status;
fn hello_handler(req: &mut Request) -> IronResult<Response> {
Ok(Response::with((status::Ok, "Hello world!")))
};
§Middleware
In situations involving more complex logic, it may be desirable to transform
Request
s passed to a Handler
or altering Response
s sent to the
clients. For example, an authorization step could only allow requests sent
by authorized users to be passed to a Handler
and respond to all other
requests with a 403 status code. To faciliate such use cases, Iron’s
middleware system allows Handler
s to be extended by defining middleware,
which will perform transformations.
There are three types of middleware:
- A
BeforeMiddleware
alters aRequest
. It can be useful for handling control flow (e.g. routing and authorization). - An
AroundMiddleware
wraps aHandler
, changing both theResponse
passed to theHandler
and the returnedResponse
. - An
AfterMiddleware
performsResponse
post-processing. It can be used for editing headers or loggingResponse
s, but it should not be used for changing the body of aResponse
.
See the documentation for each middleware for more details.
§Defining the middleware pipeline
A Chain
is a Handler
that wraps another Handler
. It is used to attach
middleware to the wrapped Handler
using a link
method corresponding to
each type of middleware. A sample middleware pipeline is shown below:
use iron::prelude::*;
use iron::middleware::*;
struct RequestLoggingMiddleware;
impl BeforeMiddleware for RequestLoggingMiddleware {
fn before(&self, req: &mut Request) -> IronResult<()> {
println!("{:?}", req);
Ok(())
}
}
let mut chain = Chain::new(hello_handler);
chain.link_before(RequestLoggingMiddleware {});
// Since a Chain is a Handler, chain can be passed to Iron::new without any problems.
// Iron::new(chain).http("localhost:3000").unwrap();
§The Request Handling Flow
A diagram modeling the entire middleware system process is shown below:
[b] = BeforeMiddleware
[a] = AfterMiddleware
[[h]] = AroundMiddleware
[h] = Handler
With no errors, the flow looks like:
[b] -> [b] -> [b] -> [[[[h]]]] -> [a] -> [a] -> [a] -> [a]
A request first travels through all BeforeMiddleware
, then a Response
is
generated by the Handler
, which can be an arbitrary nesting of
AroundMiddleware
, then all AfterMiddleware
are called with both the
Request
and Response
. After all AfterMiddleware
have been fired, the
response is written back to the client.
Iron’s error handling system is pragmatic and focuses on tracking two pieces of information for error receivers (other middleware):
- The cause of the error
- The result (what to do about) the error.
The cause of the error is represented simply by the error itself, and the result of the error, representing the action to take in response to the error, is a complete Response, which will be sent at the end of the error flow.
When an error is thrown in Iron by any middleware or handler returning an
Err
variant with an IronError
, the flow of the Request
switches to the
error flow, which proceeds to just call the catch
method of middleware and
sidesteps the Handler
entirely, since there is already a Response
in the
error.
A Request
can exit the error flow by returning an Ok from any of the catch
methods. This resumes the flow at the middleware immediately following the
middleware which handled the error. It is impossible to “go back” to an
earlier middleware that was skipped.
Generally speaking, returning a 5XX error code means that the error flow should be entered by raising an explicit error. Dealing with 4XX errors is trickier, since the server may not want to recognize an error that is entirely the clients fault; handling of 4XX error codes is up to to each application and middleware author.
Middleware authors should be cognizant that their middleware may be skipped
during the error flow. Anything that must be done to each Request
or
Response
should be run during both the normal and error flow by
implementing the catch
method to also do the necessary action.
Structs§
- Chain
- The middleware chain used in Iron.
Traits§
- After
Middleware AfterMiddleware
are fired after aHandler
is called inside of a Chain.- Around
Middleware AroundMiddleware
are used to wrap and replace theHandler
in aChain
.- Before
Middleware BeforeMiddleware
are fired before aHandler
is called inside of a Chain.- Handler
Handler
s are responsible for handling requests by creating Responses from Requests.