ApiConnExt

Trait ApiConnExt 

Source
pub trait ApiConnExt {
    // Required methods
    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 + 'async_trait,
             Self: 'async_trait,
             'life0: 'async_trait;
}
Expand description

Extension trait that adds api methods to trillium::Conn

Required Methods§

Source

fn with_json(self, response: &impl Serialize) -> Self

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"
);
Source

fn deserialize<'life0, 'async_trait, T>( &'life0 mut self, ) -> Pin<Box<dyn Future<Output = Result<T, Value>> + Send + 'async_trait>>
where T: DeserializeOwned + 'async_trait, Self: 'async_trait, 'life0: 'async_trait,

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"#,
);

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl ApiConnExt for Conn

Source§

fn with_json(self, response: &impl Serialize) -> Self

Source§

fn deserialize<'life0, 'async_trait, T>( &'life0 mut self, ) -> Pin<Box<dyn Future<Output = Result<T, Value>> + Send + 'async_trait>>
where T: DeserializeOwned + 'async_trait, Self: 'async_trait, 'life0: 'async_trait,

Implementors§