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>> + Send + 'async_trait>>
       where T: DeserializeOwned + 'async_trait,
             Self: 'async_trait,
             'life0: 'async_trait;
    fn deserialize_json<'life0, 'async_trait, T>(
        &'life0 mut self
    ) -> Pin<Box<dyn Future<Output = Result<T>> + Send + 'async_trait>>
       where T: DeserializeOwned + 'async_trait,
             Self: 'async_trait,
             'life0: 'async_trait;
    fn serialize<'life0, 'life1, 'async_trait, T>(
        &'life0 mut self,
        body: &'life1 T
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
       where T: Serialize + Sync + 'async_trait,
             Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn content_type(&self) -> Result<Mime>;
}
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)
}

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>> + 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.

This sets a status code of Status::Ok if and only if no status code has been explicitly set.

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

source

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

Deserializes json without any Accepts header content negotiation

source

fn serialize<'life0, 'life1, 'async_trait, T>( &'life0 mut self, body: &'life1 T ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where T: Serialize + Sync + 'async_trait, Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Serializes the provided body using Accepts header content negotiation

source

fn content_type(&self) -> Result<Mime>

Returns a parsed content type for this conn.

Note that this function considers a missing content type an error of variant Error::MissingContentType.

Object Safety§

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>> + Send + 'async_trait>>
where T: DeserializeOwned + 'async_trait, Self: 'async_trait, 'life0: 'async_trait,

source§

fn content_type(&self) -> Result<Mime>

source§

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

source§

fn serialize<'life0, 'life1, 'async_trait, T>( &'life0 mut self, body: &'life1 T ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where T: Serialize + Sync + 'async_trait, Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Implementors§