pub trait ApiConnExt {
    fn with_json(self, response: &impl Serialize) -> Self;
    fn deserialize<'life0, 'async_trait, T>(
        &'life0 mut self
    ) -> Pin<Box<dyn Future<Output = Result<T, Value>> + Send + 'async_trait>>
    where
        T: DeserializeOwned,
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
; }
Expand description

Extension trait that adds api methods to [trillium::Conn]

Required Methods

Sends a json response body. This sets a status code of 200, serializes the body with serde_json, sets the content-type to application/json, and halts the conn. If serialization fails, a 500 status code is sent as per [trillium::conn_try]

Examples
use trillium_api::{json, ApiConnExt};
async fn handler(conn: trillium::Conn) -> trillium::Conn {
    conn.with_json(&json!({ "json macro": "is reexported" }))
}

assert_ok!(
    get("/").on(&handler),
    r#"{"json macro":"is reexported"}"#,
    "content-type" => "application/json"
);
overriding status code
use trillium_api::ApiConnExt;
use serde::Serialize;

#[derive(Serialize)]
struct ApiResponse {
   string: &'static str,
   number: usize
}

async fn handler(conn: trillium::Conn) -> trillium::Conn {
    conn.with_json(&ApiResponse { string: "not the most creative example", number: 100 })
        .with_status(201) // note that this has to be chained _after_ the with_json call
}

assert_response!(
    get("/").on(&handler),
    Status::Created,
    r#"{"string":"not the most creative example","number":100}"#,
    "content-type" => "application/json"
);

Attempts to deserialize a type from the request body, based on the request content type.

By default, both application/json and application/x-www-form-urlencoded are supported, and future versions may add accepted request content types. Please open an issue if you need to accept another content type.

To exclusively accept application/json, disable default features on this crate.

Examples
Deserializing to Value
use trillium_api::{ApiConnExt, Value};

async fn handler(mut conn: trillium::Conn) -> trillium::Conn {
    let value: Value = trillium::conn_try!(conn.deserialize().await, conn);
    conn.with_json(&value)
}

assert_ok!(
    post("/")
        .with_request_body(r#"key=value"#)
        .with_request_header("content-type", "application/x-www-form-urlencoded")
        .on(&handler),
    r#"{"key":"value"}"#,
    "content-type" => "application/json"
);
Deserializing a concrete type
use trillium_api::ApiConnExt;

#[derive(serde::Deserialize)]
struct KvPair { key: String, value: String }

async fn handler(mut conn: trillium::Conn) -> trillium::Conn {
    match conn.deserialize().await {
        Ok(KvPair { key, value }) => {
            conn.with_status(201)
                .with_body(format!("{} is {}", key, value))
                .halt()
        }

        Err(_) => conn.with_status(422).with_body("nope").halt()
    }
}

assert_response!(
    post("/")
        .with_request_body(r#"key=name&value=trillium"#)
        .with_request_header("content-type", "application/x-www-form-urlencoded")
        .on(&handler),
    Status::Created,
    r#"name is trillium"#,
);

assert_response!(
    post("/")
        .with_request_body(r#"name=trillium"#)
        .with_request_header("content-type", "application/x-www-form-urlencoded")
        .on(&handler),
    Status::UnprocessableEntity,
    r#"nope"#,
);

Implementations on Foreign Types

Implementors