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:

1use iron::mime::Mime;
3pub fn example_handler(req: &mut Request) -> IronResult<Response> {
4 let mime = "application/json".parse::<Mime>().unwrap();
6 // …
8 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 a Request and a Response 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:

1use iron::{AfterMiddleware, IronResult, Request, Response};
2use iron::prelude::*;
3use iron::mime::Mime;
5pub struct MimeJson;
7impl AfterMiddleware for MimeJson {
8 fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
9 res.set_mut("application/json".parse::<Mime>().unwrap());
10 Ok(res)
11 }

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:

1extern crate iron;
2extern crate router;
3extern crate mount;
5// Import the middleware:
6use middleware;
8fn main() {
9 let api_v1_router = {
10 let mut router = Router::new();
11 router.get("/example", example_handler, "example");
13 // `api_v1` specific middleware:
14 let mut chain = Chain::new(router);
15 chain.link_after(middleware::MimeJson);
16 chain
17 };
19 let mut mount = Mount::new();
20 mount.mount("/api/v1", api_v1_router);
22 Iron::new(mount).http("").unwrap();

With that done we can go back and update our original example_handler, getting rid of all the MIME type code:

1pub fn example_handler(req: &mut Request) -> IronResult<Response> {
2 // …
4 Ok(Response::with((status::Ok, some_json)))