1
0
mirror of https://github.com/actix/actix-website synced 2024-12-19 02:13:13 +01:00
actix-website/examples/requests/src/manual.rs

48 lines
1.5 KiB
Rust
Raw Normal View History

2019-06-17 20:34:23 +02:00
// <json-manual>
use actix_web::{error, web, App, Error, HttpResponse};
2019-06-17 20:34:23 +02:00
use bytes::BytesMut;
use futures::{Future, Stream};
use serde::{Deserialize, Serialize};
use serde_json;
#[derive(Serialize, Deserialize)]
struct MyObj {
name: String,
number: i32,
}
const MAX_SIZE: usize = 262_144; // max payload size is 256k
pub fn index_manual(
2019-06-17 20:34:23 +02:00
payload: web::Payload,
) -> impl Future<Item = HttpResponse, Error = Error> {
// payload is a stream of Bytes objects
payload
// `Future::from_err` acts like `?` in that it coerces the error type from
// the future into the final error type
.from_err()
// `fold` will asynchronously read each chunk of the request body and
// call supplied closure, then it resolves to result of closure
.fold(BytesMut::new(), move |mut body, chunk| {
// limit max size of in-memory payload
if (body.len() + chunk.len()) > MAX_SIZE {
Err(error::ErrorBadRequest("overflow"))
} else {
body.extend_from_slice(&chunk);
Ok(body)
}
})
// `Future::and_then` can be used to merge an asynchronous workflow with a
// synchronous workflow
.and_then(|body| {
// body is loaded, now we can deserialize serde-json
let obj = serde_json::from_slice::<MyObj>(&body)?;
Ok(HttpResponse::Ok().json(obj)) // <- send response
})
}
// </json-manual>
pub fn main() {
App::new().route("/", web::post().to_async(index_manual));
}