RequestPayloadExt

Trait RequestPayloadExt 

Source
pub trait RequestPayloadExt {
    // Required methods
    fn payload<D>(&self) -> Result<Option<D>, PayloadError>
       where D: DeserializeOwned;
    fn json<D>(&self) -> Result<Option<D>, JsonPayloadError>
       where D: DeserializeOwned;
    fn form_url_encoded<D>(
        &self,
    ) -> Result<Option<D>, FormUrlEncodedPayloadError>
       where D: DeserializeOwned;
}
Expand description

Extends http::Request<Body> with payload deserialization helpers.

Required Methods§

Source

fn payload<D>(&self) -> Result<Option<D>, PayloadError>

Return the result of a payload parsed into a type that implements serde::Deserialize

Currently only application/x-www-form-urlencoded and application/json flavors of content type are supported

A PayloadError will be returned for undeserializable payloads. If no body is provided, the content-type header is missing, or the content-type header is unsupported, then Ok(None) will be returned. Note that a blank body (e.g. an empty string) is treated like a present payload by some deserializers and may result in an error.

§Examples

A request’s body can be deserialized if its correctly encoded as per the request’s Content-Type header. The two supported content types are application/x-www-form-urlencoded and application/json.

The following handler will work an http request body of x=1&y=2 as well as {"x":1, "y":2} respectively.

use lambda_http::{
    service_fn, Body, Context, Error, IntoResponse, Request, RequestPayloadExt, Response,
};
use serde::Deserialize;

#[derive(Debug, Default, Deserialize)]
struct Args {
  #[serde(default)]
  x: usize,
  #[serde(default)]
  y: usize
}

#[tokio::main]
async fn main() -> Result<(), Error> {
  lambda_http::run(service_fn(add)).await?;
  Ok(())
}

async fn add(
  request: Request
) -> Result<Response<Body>, Error> {
  let args: Args = request.payload()
    .unwrap_or_else(|_parse_err| None)
    .unwrap_or_default();
  Ok(
     Response::new(
       format!(
         "{} + {} = {}",
         args.x,
         args.y,
         args.x + args.y
       ).into()
     )
  )
}
Source

fn json<D>(&self) -> Result<Option<D>, JsonPayloadError>

Attempts to deserialize the request payload as JSON. When there is no payload, Ok(None) is returned.

§Errors

If a present payload is not a valid JSON payload matching the annotated type, a JsonPayloadError is returned.

§Examples
§1. Parsing a JSONString.
let req = http::Request::builder()
    .body(Body::from("\"I am a JSON string\""))
    .expect("failed to build request");
match req.json::<String>() {
    Ok(Some(json)) => assert_eq!(json, "I am a JSON string"),
    Ok(None) => panic!("payload is missing."),
    Err(err) => panic!("error processing json: {err:?}"),
}
§2. Parsing a JSONObject.
#[derive(Deserialize, Eq, PartialEq, Debug)]
struct Person {
    name: String,
    age: u8,
}

let req = http::Request::builder()
    .body(Body::from(r#"{"name": "Adam", "age": 23}"#))
    .expect("failed to build request");

match req.json::<Person>() {
    Ok(Some(person)) => assert_eq!(
        person,
        Person {
            name: "Adam".to_string(),
            age: 23
        }
    ),
    Ok(None) => panic!("payload is missing"),
    Err(JsonPayloadError::Parsing(err)) => {
        if err.is_data() {
            panic!("payload does not match Person schema: {err:?}")
        }
        if err.is_syntax() {
            panic!("payload is invalid json: {err:?}")
        }
        panic!("failed to parse json: {err:?}")
    }
}
Source

fn form_url_encoded<D>(&self) -> Result<Option<D>, FormUrlEncodedPayloadError>

Attempts to deserialize the request payload as an application/x-www-form-urlencoded content type. When there is no payload, Ok(None) is returned.

§Errors

If a present payload is not a valid application/x-www-form-urlencoded payload matching the annotated type, a FormUrlEncodedPayloadError is returned.

§Examples
let req = http::Request::builder()
    .body(Body::from("name=Adam&age=23"))
    .expect("failed to build request");
match req.form_url_encoded::<Person>() {
    Ok(Some(person)) => assert_eq!(
        person,
        Person {
            name: "Adam".to_string(),
            age: 23
        }
    ),
    Ok(None) => panic!("payload is missing."),
    Err(err) => panic!("error processing payload: {err:?}"),
}

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 RequestPayloadExt for Request<Body>

Implementors§