Skip to main content

ApiConnExt

Trait ApiConnExt 

Source
pub trait ApiConnExt {
    // Required methods
    fn with_json(self, response: &impl Serialize) -> Self;
    fn deserialize<T>(&mut self) -> impl Future<Output = Result<T>> + Send
       where T: DeserializeOwned;
    fn deserialize_json<T>(&mut self) -> impl Future<Output = Result<T>> + Send
       where T: DeserializeOwned;
    fn serialize<T>(
        &mut self,
        body: &T,
    ) -> impl Future<Output = Result<()>> + Send
       where T: Serialize + Sync;
    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

Available on crate features sonic-rs or serde_json only.

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};
use trillium_testing::TestServer;

async fn handler(conn: trillium::Conn) -> trillium::Conn {
conn.with_json(&json!({ "json macro": "is reexported" }))
}

let app = TestServer::new(handler).await;
app.get("/")
    .await
    .assert_ok()
    .assert_body(r#"{"json macro":"is reexported"}"#)
    .assert_header("content-type", "application/json");
§overriding status code
use serde::Serialize;
use trillium_api::ApiConnExt;
use trillium_testing::TestServer;

#[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)
}

let app = TestServer::new(handler).await;
app.get("/")
    .await
    .assert_status(201)
    .assert_body(r#"{"string":"not the most creative example","number":100}"#)
    .assert_header("content-type", "application/json");
Source

fn deserialize<T>(&mut self) -> impl Future<Output = Result<T>> + Send

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 = match conn.deserialize().await {
        Ok(v) => v,
        Err(_) => return conn.with_status(400),
    };
    conn.with_json(&value)
}

let app = TestServer::new(handler).await;
app.post("/")
    .with_body(r#"key=value"#)
    .with_request_header("content-type", "application/x-www-form-urlencoded")
    .await
    .assert_ok()
    .assert_body(r#"{"key":"value"}"#)
    .assert_header("content-type", "application/json");
§Deserializing a concrete type
use trillium_api::ApiConnExt;
use trillium_testing::TestServer;

#[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(),
    }
}

let app = TestServer::new(handler).await;

app.post("/")
    .with_body(r#"key=name&value=trillium"#)
    .with_request_header("content-type", "application/x-www-form-urlencoded")
    .await
    .assert_status(201)
    .assert_body(r#"name is trillium"#);

app.post("/")
    .with_body(r#"name=trillium"#)
    .with_request_header("content-type", "application/x-www-form-urlencoded")
    .await
    .assert_status(422)
    .assert_body(r#"nope"#);
Source

fn deserialize_json<T>(&mut self) -> impl Future<Output = Result<T>> + Send

Available on crate features sonic-rs or serde_json only.

Deserializes json without any Accepts header content negotiation

Source

fn serialize<T>(&mut self, body: &T) -> impl Future<Output = Result<()>> + Send
where T: Serialize + Sync,

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.

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

Available on crate features sonic-rs or serde_json only.
Source§

async fn deserialize<T>(&mut self) -> Result<T>

Source§

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

Source§

async fn deserialize_json<T>(&mut self) -> Result<T>

Available on crate features sonic-rs or serde_json only.
Source§

async fn serialize<T>(&mut self, body: &T) -> Result<()>
where T: Serialize + Sync,

Implementors§