courier 0.3.1

Utility to make it easier to send and receive data when using the Rocket framework.
Documentation
# Rocket Derive

`courier` is a utility crate for the [Rocket] framework which allows you derive [`FromData`]
and [`Responder`] for your custom types. Here's an example using `courier` to handle sending
and recieving custom data to/from the client:

```rust
#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
#[macro_use]
extern crate courier;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[derive(Deserialize, FromData)]
pub struct CustomRequest {
    pub foo: String,
    pub bar: usize,
}

#[derive(Serialize, Responder)]
pub struct CustomResponse {
    pub baz: usize,
}

#[post("/endpoint", data = "<request>")]
pub fn handle_request(request: CustomRequest) -> CustomResponse {
    if request.foo == "foo" {
        CustomResponse { baz: 0 }
    } else {
        CustomResponse { baz: request.bar }
    }
}
```

In this example, the response will be encoded the same way that the request was, e.g. if the client
sent the request body as JSON, then the response will be sent as JSON.

## Usage

Add `courier`, as well as the relevant Serde crates to your `Cargo.toml`:

```toml
[dependencies]
courier = "0.3.1"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
```

Import the crates into your project:

```rust
#[macro_use]
extern crate courier;

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
```

Note that you must have the `#[macro_use]` attribute on the `extern crate` statement in order to
use this crate's features.

You can now use `#[derive(FromData)]` and `#[derive(Responder)]` for your custom types.

## Supported Formats

`courier` supports receiving request bodies and sending response bodies in multiple formats.
For each one you'd like to enable, you'll have to enable a feature in your `Cargo.toml` and add the
relevant Serde crate(s) to your project. The following table shows which formats are currently
supported, the feature name for that format, and what Serde crate(s) you'll need to include.

| Format        | Feature Name | Serde Crate(s)    |
| --------------|--------------|-------------------|
| [JSON]        | `json`       | [`serde_json`]    |
| [MessagePack] | `msgpack`    | [`rmp-serde`]     |

By default, only JSON support is enabled. So, for example, if you'd like to add MessagePack support,
you'd edit your `Cargo.toml` to enable the `msgpack` feature and add rmp-serde as a dependency:

```toml
[dependencies]
rmp-serde = "0.13.6"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

[dependencies.courier]
version = "0.3.1"
features = ["msgpack"]
```

And then add `rmp-serde` to your project root:

```rust
#[macro_use]
extern crate courier;

extern crate rmp_serde;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
```

Note that, to also support JSON, you still need to include `serde_json` as a dependency. If you do
not wish to support JSON, you can specify `default-features = false` in your `Cargo.toml`:

```toml
[dependencies.courier]
version = "0.3.1"
default-features = false
features = ["msgpack"]
```

## Using Multiple Formats

When multiple formats are enabled at once, the [`Content-Type`] header in the request is used to
determine which format the request data is in, and the [`Accept`] header is used to determine which
format to use for the response.

While this mostly removes the need for [`rocket_contrib::Json`] (and similar types), it is still
possible to use it to override the behavior defined with `courier`. For example, say you
specify a format for your Rocket route:

```rust
#[post("/endpoint", format = "application/json", data = "<request>")]
pub fn handle_request(request: CustomRequest) -> CustomResponse {
    if request.foo == "foo" {
        CustomResponse { baz: 0 }
    } else {
        CustomResponse { baz: request.bar }
    }
}
```

In that case, Rocket will check the content type before routing the request to `handle_request`,
then the [`FromData`] impl for `CustomRequest` will check it again. If this isn't desirable, you
can use [`rocket_contrib::Json`] to skip the second check:

```rust
use rocket_contrib::Json;

#[post("/endpoint", format = "application/json", data = "<request>")]
pub fn handle_request(request: Json<CustomRequest>) -> Json<CustomResponse> {
    if request.foo == "foo" {
        Json(CustomResponse { baz: 0 })
    } else {
        Json(CustomResponse { baz: request.bar })
    }
}
```

Note, though, that recommended to not explicitly specify the `format` parameter for your route if you're using `courier`. The code generated by `courier` allows you to write content type-agnostic route handlers, so manually specifying an expected format is unnecessary.

[Rocket]: https://rocket.rs/
[`FromData`]: https://api.rocket.rs/rocket/data/trait.FromData.html
[`Responder`]: https://api.rocket.rs/rocket/response/trait.Responder.html
[JSON]: http://www.json.org/
[MessagePack]: http://msgpack.org/index.html
[`serde_json`]: https://crates.io/crates/serde_json
[`rmp-serde`]: https://crates.io/crates/rmp-serde
[`Content-Type`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
[`Accept`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept
[`rocket_contrib::Json`]: https://api.rocket.rs/rocket_contrib/struct.Json.html