![](/img/trans.png)
[英]How do I read multiple parameters from a JSON request body in ASP.NET Core?
[英]How do I extract path parameters and parse JSON body from the same request using Actix-Web
我正在使用 Actix-Web v1.0.7 在 Rust 中編寫 Web 應用程序。 我正在嘗試創建一個可以訪問路徑參數並解析請求的 JSON 正文的路由處理程序。 但是,到目前為止,我還沒有這樣做。
我嘗試聲明一個接受actix_web::HttpRequest
作為參數的處理函數。 這使我可以使用match_info
方法訪問路徑參數而不會出現任何問題。 然后我嘗試使用actix_web::web::Json::from_request
方法(來自actix_web::FromRequest
特征實現)解析 JSON 正文,該方法需要 2 個參數:
&actix_web::HttpRequest
&mut actix_web::dev::Payload
我的問題是獲取actix_web::dev::Payload
。 我嘗試使用actix_web::HttpRequest::take_payload
方法(來自actix_web::HttpMessage
trait 實現),但 trait 實現聲明了一個單位值作為有效負載內的Stream
,這意味着我被卡住了。 我認為這是由於框架的異步性質造成的,並且可能在調用處理程序時尚未收到請求正文。 然而,這只是一個假設。
#[derive(Deserialize)]
struct Thing {
// ...
}
type JsonThing = Json<Thing>;
fn handle(req: HttpRequest) -> impl IntoFuture {
let id = req.match_info().query("id").parse::<usize>().unwrap();
let mut payload = req.take_payload();
JsonThing::from_request(&req, &mut payload)
.and_then(|thing| {
// ...
HttpResponse::Ok().finish()
})
}
fn main() {
let address = String::from("127.0.0.1:8080");
let scope = web::scope("/scope")
.route("/{id:\\d+}/path", web::put().to_async(handle));
HttpServer::new(|| App::new().service(scope))
.bind(address)
.unwrap()
.run()
.unwrap();
}
我知道上面的代碼片段不能編譯並包含其他問題,但是它傳達了總體思路。 我希望有一種方法可以從路徑中獲取 ID 參數的值,並且還能夠解析同一請求的 JSON 正文,但到目前為止我還沒有找到。
Actix 為此使用提取器。 定義要在處理程序中提取的內容:
#[derive(Deserialize, Serialize)] // <-- Note the Serialize for the json echo response
struct Thing {
//...
}
type JsonThing = Json<Thing>;
fn handle(thing: JsonThing) -> impl Reponse {
let id = req.match_info().query("id").parse::<usize>().unwrap();
// echo the body back
HttpResponse::Ok().json(thing)
}
您可以使用web::Query
對id
執行相同操作。
您將需要使用web::Path
提取器從路徑中獲取id
。 可以在同一個處理程序函數中使用多個提取器。 下面的示例適用於actix-web
>= 3.0。
use actix_web::{error, web, App, HttpResponse, HttpServer, Responder};
use serde::Deserialize;
#[derive(Deserialize)]
struct Thing {
name: String, // required string member. This must exist in the request body's json.
some_value: Option<String>, // optional member, can be missing from the request body.
// ...
}
/// deserialize `Thing` from request's body and get `id` from path.
#[put("/{id:\\d+}/path")]
async fn handle(
web::Path(id): web::Path<usize>, // web::Path extractor for 'id'
web::Json(thing): web::Json<Thing> // web::Json extractor for json body.
) -> impl IntoFuture {
// `web::Path(id)` uses Rust's pattern matching to "unwrap" the `id` value, so `id` is type `usize` here.
// `web::Json(thing)` does the same "unwrapping", so `thing` is of type `Thing` here.
// TODO: use 'id' and 'thing'
HttpResponse::Ok().finish()
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let address = String::from("127.0.0.1:8080");
HttpServer::new(|| {
App::new()
.service(handle)
})
.bind(address)?
.run()
.await
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.