如何在中间件和处理程序中读取 Iron Request?
How do I read an Iron Request in both middleware and the handler?
我正在用 Rust 开发一个小的 API,我不确定如何在两个地方访问 Iron 的 Request
。
Authentication
中间件为令牌读取一次 Request
,如果路径被允许(目前没有检查),实际路由会尝试再次读取它。这给了我一个 EOF 错误,因为请求已被读取。
我似乎无法轻易克隆请求,我相信它必须是可变的才能读取正文。
extern crate iron;
extern crate router;
extern crate rustc_serialize;
use iron::prelude::*;
use iron::{BeforeMiddleware, status};
use router::Router;
use rustc_serialize::json;
use rustc_serialize::json::Json;
use std::io::Read;
#[derive(RustcEncodable, RustcDecodable)]
struct Greeting {
msg: String
}
struct Authentication;
fn main() {
let mut request_body = String::new();
impl BeforeMiddleware for Authentication {
fn before(&self, request: &mut Request) -> IronResult<()> {
let mut payload = String::new();
request.body.read_to_string(&mut payload).unwrap();
let json = Json::from_str(&payload).unwrap();
println!("json: {}", json);
let token = json.as_object()
.and_then(|obj| obj.get("token"))
.and_then(|token| token.as_string())
.unwrap_or_else(|| {
panic!("Unable to get token");
});
println!("token: {}", token);
Ok(())
}
}
fn attr(input: String, attribute: &str) -> String {
let json = Json::from_str(&input).unwrap();
let output = json.as_object()
.and_then(|obj| obj.get(attribute))
.and_then(|a| a.as_string())
.unwrap_or_else(|| {
panic!("Unable to get attribute {}", attribute);
});
String::from(output)
}
fn hello_world(_: &mut Request) -> IronResult<Response> {
let greeting = Greeting { msg: "Hello, world!".to_string() };
let payload = json::encode(&greeting).unwrap();
Ok(Response::with((status::Ok, payload)))
}
// Receive a message by POST and play it back if auth-key is correct.
fn set_greeting(request: &mut Request) -> IronResult<Response> {
let mut payload = String::new();
request.body.read_to_string(&mut payload).unwrap();
let json = Json::from_str(&payload).unwrap();
println!("json: {}", json);
let msg = attr(payload, "msg");
println!("msg: {}", msg);
let greeting = Greeting { msg: String::from(msg) };
let payload = json::encode(&greeting).unwrap();
Ok(Response::with((status::Ok, payload)))
}
let mut router = Router::new();
router.get("/", hello_world);
router.post("/set", set_greeting);
let mut chain = Chain::new(router);
chain.link_before(Authentication);
Iron::new(chain).http("localhost:3000").unwrap();
}
在不确定的情况下,我不认为您可以做任何事情来重新阅读正文(出于性能原因,您可能不想这样做)。相反,您可以让您的中间件解析数据,然后将其存储在 Request.extensions
中。然后你的路线会把它读回来:
struct AuthenticatedBody;
impl iron::typemap::Key for AuthenticatedBody {
type Value = Json;
}
struct Authentication;
impl BeforeMiddleware for Authentication {
fn before(&self, request: &mut Request) -> IronResult<()> {
let mut payload = String::new();
request.body.read_to_string(&mut payload).unwrap();
let json = Json::from_str(&payload).unwrap();
{
let token = json.as_object()
.and_then(|obj| obj.get("token"))
.and_then(|token| token.as_string())
.unwrap_or_else(|| panic!("Unable to get token"));
} // Scoped to end the borrow of `json`
request.extensions.insert::<AuthenticatedBody>(json);
Ok(())
}
}
// ...
fn set_greeting(request: &mut Request) -> IronResult<Response> {
let json = request.extensions.get::<AuthenticatedBody>().unwrap();
// ...
}
我正在用 Rust 开发一个小的 API,我不确定如何在两个地方访问 Iron 的 Request
。
Authentication
中间件为令牌读取一次 Request
,如果路径被允许(目前没有检查),实际路由会尝试再次读取它。这给了我一个 EOF 错误,因为请求已被读取。
我似乎无法轻易克隆请求,我相信它必须是可变的才能读取正文。
extern crate iron;
extern crate router;
extern crate rustc_serialize;
use iron::prelude::*;
use iron::{BeforeMiddleware, status};
use router::Router;
use rustc_serialize::json;
use rustc_serialize::json::Json;
use std::io::Read;
#[derive(RustcEncodable, RustcDecodable)]
struct Greeting {
msg: String
}
struct Authentication;
fn main() {
let mut request_body = String::new();
impl BeforeMiddleware for Authentication {
fn before(&self, request: &mut Request) -> IronResult<()> {
let mut payload = String::new();
request.body.read_to_string(&mut payload).unwrap();
let json = Json::from_str(&payload).unwrap();
println!("json: {}", json);
let token = json.as_object()
.and_then(|obj| obj.get("token"))
.and_then(|token| token.as_string())
.unwrap_or_else(|| {
panic!("Unable to get token");
});
println!("token: {}", token);
Ok(())
}
}
fn attr(input: String, attribute: &str) -> String {
let json = Json::from_str(&input).unwrap();
let output = json.as_object()
.and_then(|obj| obj.get(attribute))
.and_then(|a| a.as_string())
.unwrap_or_else(|| {
panic!("Unable to get attribute {}", attribute);
});
String::from(output)
}
fn hello_world(_: &mut Request) -> IronResult<Response> {
let greeting = Greeting { msg: "Hello, world!".to_string() };
let payload = json::encode(&greeting).unwrap();
Ok(Response::with((status::Ok, payload)))
}
// Receive a message by POST and play it back if auth-key is correct.
fn set_greeting(request: &mut Request) -> IronResult<Response> {
let mut payload = String::new();
request.body.read_to_string(&mut payload).unwrap();
let json = Json::from_str(&payload).unwrap();
println!("json: {}", json);
let msg = attr(payload, "msg");
println!("msg: {}", msg);
let greeting = Greeting { msg: String::from(msg) };
let payload = json::encode(&greeting).unwrap();
Ok(Response::with((status::Ok, payload)))
}
let mut router = Router::new();
router.get("/", hello_world);
router.post("/set", set_greeting);
let mut chain = Chain::new(router);
chain.link_before(Authentication);
Iron::new(chain).http("localhost:3000").unwrap();
}
在不确定的情况下,我不认为您可以做任何事情来重新阅读正文(出于性能原因,您可能不想这样做)。相反,您可以让您的中间件解析数据,然后将其存储在 Request.extensions
中。然后你的路线会把它读回来:
struct AuthenticatedBody;
impl iron::typemap::Key for AuthenticatedBody {
type Value = Json;
}
struct Authentication;
impl BeforeMiddleware for Authentication {
fn before(&self, request: &mut Request) -> IronResult<()> {
let mut payload = String::new();
request.body.read_to_string(&mut payload).unwrap();
let json = Json::from_str(&payload).unwrap();
{
let token = json.as_object()
.and_then(|obj| obj.get("token"))
.and_then(|token| token.as_string())
.unwrap_or_else(|| panic!("Unable to get token"));
} // Scoped to end the borrow of `json`
request.extensions.insert::<AuthenticatedBody>(json);
Ok(())
}
}
// ...
fn set_greeting(request: &mut Request) -> IronResult<Response> {
let json = request.extensions.get::<AuthenticatedBody>().unwrap();
// ...
}