Setting Iron’s response MIME type with middleware
If your JSON API is powered by Iron, you may well have a lot of duplicate code that sets the MIME type of each Response
. Something like this:
use iron::mime::Mime;
pub fn example_handler(req: &mut Request) -> IronResult<Response> {
let mime = "application/json".parse::<Mime>().unwrap();
// …
Ok(Response::with((mime, status::Ok, some_json)))
}
As we can see above, the code for setting a MIME type is generic and doesn’t need anything except a Response
to modify. It is therefore a prime AfterMiddleware
candidate, which once implemented will remove the need for the code repetition in each and every one of our routes’ handlers. Here’s a very brief AfterMiddleware
description from the docs:
AfterMiddleware
receive both aRequest
and aResponse
and are responsible for doing any response post-processing.
Writing the middleware
As the docs said, AfterMiddleware
receives both the Request
and the Response
. We don’t need to do anything to the Request
so we’ll just mark it as unused with _
. We do however want to modify the Response
which can be done very straightforwardly with .set_mut()
. Pieced together, we end up with this:
src/middleware.rs:
use iron::{AfterMiddleware, IronResult, Request, Response};
use iron::prelude::*;
use iron::mime::Mime;
pub struct MimeJson;
impl AfterMiddleware for MimeJson {
fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
res.set_mut("application/json".parse::<Mime>().unwrap());
Ok(res)
}
}
Using the middleware
Not that we have our middleware in place, we need to use it. The following snippet, for example, uses it to set the MIME type of every handler in the api_v1_router
router:
src/main.rs:
extern crate iron;
extern crate router;
extern crate mount;
// Import the middleware:
use middleware;
fn main() {
let api_v1_router = {
let mut router = Router::new();
router.get("/example", example_handler, "example");
// `api_v1` specific middleware:
let mut chain = Chain::new(router);
chain.link_after(middleware::MimeJson);
chain
};
let mut mount = Mount::new();
mount.mount("/api/v1", api_v1_router);
Iron::new(mount).http("127.0.0.1:8888").unwrap();
}
With that done we can go back and update our original example_handler
, getting rid of all the MIME type code:
pub fn example_handler(req: &mut Request) -> IronResult<Response> {
// …
Ok(Response::with((status::Ok, some_json)))
}