1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 07:53:00 +01:00

json request example

This commit is contained in:
Nikolay Kim 2017-12-20 15:12:43 -08:00
parent 79f047f5be
commit cbb81bc747
4 changed files with 137 additions and 1 deletions

16
examples/json/Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "json-example"
version = "0.1.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
[dependencies]
bytes = "0.4"
futures = "0.1"
env_logger = "*"
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
actix = "^0.3.1"
actix-web = { git = "https://github.com/actix/actix-web.git" }

17
examples/json/client.py Normal file
View File

@ -0,0 +1,17 @@
# This script could be used for actix-web multipart example test
# just start server and run client.py
import json
import asyncio
import aiohttp
async def req():
resp = await aiohttp.ClientSession().request(
"post", 'http://localhost:8080/',
data=json.dumps({"name": "Test user", "number": 100}),
headers={"content-type": "application/json"})
print(str(resp))
assert 200 == resp.status
asyncio.get_event_loop().run_until_complete(req())

64
examples/json/src/main.rs Normal file
View File

@ -0,0 +1,64 @@
extern crate actix;
extern crate actix_web;
extern crate bytes;
extern crate futures;
extern crate env_logger;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use actix_web::*;
use bytes::BytesMut;
use futures::Stream;
use futures::future::{Future, ok, err, result};
#[derive(Debug, Deserialize)]
struct MyObj {
name: String,
number: i32,
}
fn index(mut req: HttpRequest) -> Result<Box<Future<Item=HttpResponse, Error=Error>>> {
// check content-type, early error exit
if req.content_type() != "application/json" {
return Err(error::ErrorBadRequest("wrong content-type").into())
}
Ok(Box::new(
// load request body
req.payload_mut()
.readany()
.fold(BytesMut::new(), |mut body, chunk| {
body.extend(chunk);
result::<_, error::PayloadError>(Ok(body))
})
.map_err(|e| Error::from(e))
.and_then(|body| {
// body is loaded, now we can deserialize json
match serde_json::from_slice::<MyObj>(&body) {
Ok(obj) => {
println!("MODEL: {:?}", obj); // <- do something with payload
ok(httpcodes::HTTPOk.response()) // <- send response
},
Err(e) => {
err(error::ErrorBadRequest(e).into())
}
}
})))
}
fn main() {
::std::env::set_var("RUST_LOG", "actix_web=info");
let _ = env_logger::init();
let sys = actix::System::new("json-example");
HttpServer::new(|| {
Application::new()
// enable logger
.middleware(middlewares::Logger::default())
.resource("/", |r| r.method(Method::POST).f(index))})
.bind("127.0.0.1:8080").unwrap()
.start();
println!("Started http server: 127.0.0.1:8080");
let _ = sys.run();
}

View File

@ -55,7 +55,46 @@ fn index(req: HttpRequest) -> HttpResponse {
}
# fn main() {}
```
## JSON Request
Unfortunately, because of async nature of actix web framework, deserializing json
requests is not very ergonomic process. First you need to load whole body into
temporal storage and only then you can deserialize it.
Here is simple example. We will deserialize *MyObj* struct.
```rust,ignore
#[derive(Debug, Deserialize)]
struct MyObj {
name: String,
number: i32,
}
```
We need to load request body first.
```rust,ignore
fn index(mut req: HttpRequest) -> Future<Item=HttpResponse, Error=Error> {
req.payload_mut().readany()
.fold(BytesMut::new(), |mut body, chunk| { // <- load request body
body.extend(chunk);
result::<_, error::PayloadError>(Ok(body))
})
.and_then(|body| { // <- body is loaded, now we can deserialize json
let obj = serde_json::from_slice::<MyObj>(&body).unwrap();
println!("MODEL: {:?}", obj); // <- do something with payload
ok(httpcodes::HTTPOk.response()) // <- send response
})
}
```
Full example is available in
[examples directory](https://github.com/actix/actix-web/tree/master/examples/json/).
## JSON Response
The `Json` type allows you to respond with well-formed JSON data: simply return a value of