mirror of
https://github.com/actix/examples
synced 2025-06-28 18:00:37 +02:00
Restructure folders (#411)
This commit is contained in:
committed by
GitHub
parent
9db98162b2
commit
c3407627d0
17
json/json/Cargo.toml
Normal file
17
json/json/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "json-example"
|
||||
version = "0.1.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "3"
|
||||
actix-service = "1.0.0"
|
||||
futures = "0.3"
|
||||
env_logger = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
json = "0.12"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1"
|
48
json/json/README.md
Normal file
48
json/json/README.md
Normal file
@ -0,0 +1,48 @@
|
||||
# json
|
||||
|
||||
Json's `Getting Started` guide using json (serde-json or json-rust) for Actix web
|
||||
|
||||
## Usage
|
||||
|
||||
### server
|
||||
|
||||
```bash
|
||||
cd examples/json
|
||||
cargo run
|
||||
# Started http server: 127.0.0.1:8080
|
||||
```
|
||||
|
||||
### web client
|
||||
|
||||
With [Postman](https://www.getpostman.com/) or [Rested](moz-extension://60daeb1c-5b1b-4afd-9842-0579ed34dfcb/dist/index.html)
|
||||
|
||||
- POST / (embed serde-json):
|
||||
|
||||
- method : ``POST``
|
||||
- url : ``http://127.0.0.1:8080/``
|
||||
- header : ``Content-Type`` = ``application/json``
|
||||
- body (raw) : ``{"name": "Test user", "number": 100}``
|
||||
|
||||
- POST /manual (manual serde-json):
|
||||
|
||||
- method : ``POST``
|
||||
- url : ``http://127.0.0.1:8080/manual``
|
||||
- header : ``Content-Type`` = ``application/json``
|
||||
- body (raw) : ``{"name": "Test user", "number": 100}``
|
||||
|
||||
- POST /mjsonrust (manual json-rust):
|
||||
|
||||
- method : ``POST``
|
||||
- url : ``http://127.0.0.1:8080/mjsonrust``
|
||||
- header : ``Content-Type`` = ``application/json``
|
||||
- body (raw) : ``{"name": "Test user", "number": 100}`` (you can also test ``{notjson}``)
|
||||
|
||||
### python client
|
||||
|
||||
- ``pip install aiohttp``
|
||||
- ``python client.py``
|
||||
|
||||
if ubuntu :
|
||||
|
||||
- ``pip3 install aiohttp``
|
||||
- ``python3 client.py``
|
20
json/json/client.py
Normal file
20
json/json/client.py
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# 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))
|
||||
print(await resp.text())
|
||||
assert 200 == resp.status
|
||||
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(req())
|
119
json/json/src/main.rs
Normal file
119
json/json/src/main.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use actix_web::{
|
||||
error, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use json::JsonValue;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct MyObj {
|
||||
name: String,
|
||||
number: i32,
|
||||
}
|
||||
|
||||
/// This handler uses json extractor
|
||||
async fn index(item: web::Json<MyObj>) -> HttpResponse {
|
||||
println!("model: {:?}", &item);
|
||||
HttpResponse::Ok().json(item.0) // <- send response
|
||||
}
|
||||
|
||||
/// This handler uses json extractor with limit
|
||||
async fn extract_item(item: web::Json<MyObj>, req: HttpRequest) -> HttpResponse {
|
||||
println!("request: {:?}", req);
|
||||
println!("model: {:?}", item);
|
||||
|
||||
HttpResponse::Ok().json(item.0) // <- send json response
|
||||
}
|
||||
|
||||
const MAX_SIZE: usize = 262_144; // max payload size is 256k
|
||||
|
||||
/// This handler manually load request payload and parse json object
|
||||
async fn index_manual(mut payload: web::Payload) -> Result<HttpResponse, Error> {
|
||||
// payload is a stream of Bytes objects
|
||||
let mut body = web::BytesMut::new();
|
||||
while let Some(chunk) = payload.next().await {
|
||||
let chunk = chunk?;
|
||||
// limit max size of in-memory payload
|
||||
if (body.len() + chunk.len()) > MAX_SIZE {
|
||||
return Err(error::ErrorBadRequest("overflow"));
|
||||
}
|
||||
body.extend_from_slice(&chunk);
|
||||
}
|
||||
|
||||
// body is loaded, now we can deserialize serde-json
|
||||
let obj = serde_json::from_slice::<MyObj>(&body)?;
|
||||
Ok(HttpResponse::Ok().json(obj)) // <- send response
|
||||
}
|
||||
|
||||
/// This handler manually load request payload and parse json-rust
|
||||
async fn index_mjsonrust(body: web::Bytes) -> Result<HttpResponse, Error> {
|
||||
// body is loaded, now we can deserialize json-rust
|
||||
let result = json::parse(std::str::from_utf8(&body).unwrap()); // return Result
|
||||
let injson: JsonValue = match result {
|
||||
Ok(v) => v,
|
||||
Err(e) => json::object! {"err" => e.to_string() },
|
||||
};
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(injson.dump()))
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
std::env::set_var("RUST_LOG", "actix_web=info");
|
||||
env_logger::init();
|
||||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
// enable logger
|
||||
.wrap(middleware::Logger::default())
|
||||
.data(web::JsonConfig::default().limit(4096)) // <- limit size of the payload (global configuration)
|
||||
.service(web::resource("/extractor").route(web::post().to(index)))
|
||||
.service(
|
||||
web::resource("/extractor2")
|
||||
.data(web::JsonConfig::default().limit(1024)) // <- limit size of the payload (resource level)
|
||||
.route(web::post().to(extract_item)),
|
||||
)
|
||||
.service(web::resource("/manual").route(web::post().to(index_manual)))
|
||||
.service(web::resource("/mjsonrust").route(web::post().to(index_mjsonrust)))
|
||||
.service(web::resource("/").route(web::post().to(index)))
|
||||
})
|
||||
.bind("127.0.0.1:8080")?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use actix_web::dev::Service;
|
||||
use actix_web::{http, test, web, App};
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_index() -> Result<(), Error> {
|
||||
let mut app = test::init_service(
|
||||
App::new().service(web::resource("/").route(web::post().to(index))),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = test::TestRequest::post()
|
||||
.uri("/")
|
||||
.set_json(&MyObj {
|
||||
name: "my-name".to_owned(),
|
||||
number: 43,
|
||||
})
|
||||
.to_request();
|
||||
let resp = app.call(req).await.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||
|
||||
let response_body = match resp.response().body().as_ref() {
|
||||
Some(actix_web::body::Body::Bytes(bytes)) => bytes,
|
||||
_ => panic!("Response error"),
|
||||
};
|
||||
|
||||
assert_eq!(response_body, r##"{"name":"my-name","number":43}"##);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user