mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 00:21:08 +01:00
refactor RouteHandler trait
This commit is contained in:
parent
6f833798c7
commit
16ceb741b8
@ -82,8 +82,15 @@ fn main() {
|
||||
.header("LOCATION", "/index.html")
|
||||
.body(Body::Empty)
|
||||
}))
|
||||
.handler("/test", |req| {
|
||||
match *req.method() {
|
||||
Method::GET => httpcodes::HTTPOk,
|
||||
Method::POST => httpcodes::HTTPMethodNotAllowed,
|
||||
_ => httpcodes::HTTPNotFound,
|
||||
}
|
||||
})
|
||||
// static files
|
||||
.route_handler("/static", StaticFiles::new("examples/static/", true)))
|
||||
.route("/static", StaticFiles::new("examples/static/", true)))
|
||||
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
||||
|
||||
println!("Started http server: 127.0.0.1:8080");
|
||||
|
@ -66,7 +66,8 @@ fn main() {
|
||||
.middleware(middlewares::Logger::default())
|
||||
// websocket route
|
||||
.resource("/ws/", |r| r.get(ws_index))
|
||||
.route_handler("/", StaticFiles::new("examples/static/", true)))
|
||||
// static files
|
||||
.route("/", StaticFiles::new("examples/static/", true)))
|
||||
// start http server on 127.0.0.1:8080
|
||||
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
||||
|
||||
|
@ -2,7 +2,7 @@ use std::rc::Rc;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use task::Task;
|
||||
use route::{RouteHandler, FnHandler, Reply};
|
||||
use route::{RouteHandler, WrapHandler, Reply, Handler};
|
||||
use resource::Resource;
|
||||
use recognizer::{RouteRecognizer, check_pattern};
|
||||
use httprequest::HttpRequest;
|
||||
@ -126,10 +126,7 @@ impl<S> ApplicationBuilder<S> where S: 'static {
|
||||
/// store userid and friend in the exposed Params object:
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate actix;
|
||||
/// extern crate actix_web;
|
||||
///
|
||||
/// use actix::*;
|
||||
/// use actix_web::*;
|
||||
///
|
||||
/// fn main() {
|
||||
@ -158,7 +155,7 @@ impl<S> ApplicationBuilder<S> where S: 'static {
|
||||
self
|
||||
}
|
||||
|
||||
/// Default resource is used if no matches route could be found.
|
||||
/// Default resource is used if no match route could be found.
|
||||
pub fn default_resource<F>(&mut self, f: F) -> &mut Self
|
||||
where F: FnOnce(&mut Resource<S>) + 'static
|
||||
{
|
||||
@ -178,7 +175,7 @@ impl<S> ApplicationBuilder<S> where S: 'static {
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::default("/")
|
||||
/// .handler("/test", |req| {
|
||||
/// .inline("/test", |req| {
|
||||
/// match *req.method() {
|
||||
/// Method::GET => httpcodes::HTTPOk,
|
||||
/// Method::POST => httpcodes::HTTPMethodNotAllowed,
|
||||
@ -189,28 +186,22 @@ impl<S> ApplicationBuilder<S> where S: 'static {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn handler<P, F, R>(&mut self, path: P, handler: F) -> &mut Self
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static,
|
||||
P: Into<String>,
|
||||
where P: Into<String>,
|
||||
F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static
|
||||
{
|
||||
self.parts.as_mut().expect("Use after finish")
|
||||
.handlers.insert(path.into(), Box::new(FnHandler::new(handler)));
|
||||
.handlers.insert(path.into(), Box::new(WrapHandler::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
/// Add path handler
|
||||
pub fn route_handler<H, P>(&mut self, path: P, h: H) -> &mut Self
|
||||
where H: RouteHandler<S> + 'static, P: Into<String>
|
||||
/// This method register handler for specified path prefix.
|
||||
/// Any path that starts with this prefix matches handler.
|
||||
pub fn route<P, H>(&mut self, path: P, handler: H) -> &mut Self
|
||||
where P: Into<String>, H: Handler<S>
|
||||
{
|
||||
{
|
||||
// add resource
|
||||
let parts = self.parts.as_mut().expect("Use after finish");
|
||||
let path = path.into();
|
||||
if parts.handlers.contains_key(&path) {
|
||||
panic!("Handler already registered: {:?}", path);
|
||||
}
|
||||
parts.handlers.insert(path, Box::new(h));
|
||||
}
|
||||
self.parts.as_mut().expect("Use after finish")
|
||||
.handlers.insert(path.into(), Box::new(WrapHandler::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
// dev specific
|
||||
pub use task::Task;
|
||||
pub use route::Handler;
|
||||
pub use pipeline::Pipeline;
|
||||
pub use recognizer::RouteRecognizer;
|
||||
pub use channel::HttpChannel;
|
||||
|
@ -82,7 +82,7 @@ pub use application::Application;
|
||||
pub use httprequest::{HttpRequest, UrlEncoded};
|
||||
pub use httpresponse::HttpResponse;
|
||||
pub use payload::{Payload, PayloadItem};
|
||||
pub use route::{Frame, RouteHandler, Reply};
|
||||
pub use route::{Frame, Reply};
|
||||
pub use resource::Resource;
|
||||
pub use recognizer::Params;
|
||||
pub use server::HttpServer;
|
||||
|
@ -6,7 +6,7 @@ use futures::Stream;
|
||||
|
||||
use task::Task;
|
||||
use error::Error;
|
||||
use route::{Reply, RouteHandler, Frame, FnHandler, StreamHandler};
|
||||
use route::{Reply, RouteHandler, Frame, WrapHandler, Handler, StreamHandler};
|
||||
use httprequest::HttpRequest;
|
||||
use httpcodes::{HTTPNotFound, HTTPMethodNotAllowed};
|
||||
|
||||
@ -17,13 +17,12 @@ use httpcodes::{HTTPNotFound, HTTPMethodNotAllowed};
|
||||
/// Resource in turn has at least one route.
|
||||
/// Route corresponds to handling HTTP method by calling route handler.
|
||||
///
|
||||
/// ```rust,ignore
|
||||
///
|
||||
/// struct MyRoute;
|
||||
/// ```rust
|
||||
/// extern crate actix_web;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let router = RoutingMap::default()
|
||||
/// .resource("/", |r| r.post::<MyRoute>())
|
||||
/// let app = actix_web::Application::default("/")
|
||||
/// .resource("/", |r| r.get(|_| actix_web::HttpResponse::Ok()))
|
||||
/// .finish();
|
||||
/// }
|
||||
pub struct Resource<S=()> {
|
||||
@ -63,7 +62,7 @@ impl<S> Resource<S> where S: 'static {
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static,
|
||||
{
|
||||
self.routes.insert(method, Box::new(FnHandler::new(handler)));
|
||||
self.routes.insert(method, Box::new(WrapHandler::new(handler)));
|
||||
}
|
||||
|
||||
/// Register async handler for specified method.
|
||||
@ -74,51 +73,42 @@ impl<S> Resource<S> where S: 'static {
|
||||
self.routes.insert(method, Box::new(StreamHandler::new(handler)));
|
||||
}
|
||||
|
||||
/// Register handler for specified method.
|
||||
pub fn route_handler<H>(&mut self, method: Method, handler: H)
|
||||
where H: RouteHandler<S>
|
||||
{
|
||||
self.routes.insert(method, Box::new(handler));
|
||||
}
|
||||
|
||||
/// Default handler is used if no matched route found.
|
||||
/// By default `HTTPMethodNotAllowed` is used.
|
||||
pub fn default_handler<H>(&mut self, handler: H)
|
||||
where H: RouteHandler<S>
|
||||
pub fn default_handler<H>(&mut self, handler: H) where H: Handler<S>
|
||||
{
|
||||
self.default = Box::new(handler);
|
||||
self.default = Box::new(WrapHandler::new(handler));
|
||||
}
|
||||
|
||||
/// Handler for `GET` method.
|
||||
pub fn get<F, R>(&mut self, handler: F)
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static, {
|
||||
self.routes.insert(Method::GET, Box::new(FnHandler::new(handler)));
|
||||
self.routes.insert(Method::GET, Box::new(WrapHandler::new(handler)));
|
||||
}
|
||||
|
||||
/// Handler for `POST` method.
|
||||
pub fn post<F, R>(&mut self, handler: F)
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static, {
|
||||
self.routes.insert(Method::POST, Box::new(FnHandler::new(handler)));
|
||||
self.routes.insert(Method::POST, Box::new(WrapHandler::new(handler)));
|
||||
}
|
||||
|
||||
/// Handler for `PUT` method.
|
||||
pub fn put<F, R>(&mut self, handler: F)
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static, {
|
||||
self.routes.insert(Method::PUT, Box::new(FnHandler::new(handler)));
|
||||
self.routes.insert(Method::PUT, Box::new(WrapHandler::new(handler)));
|
||||
}
|
||||
|
||||
/// Handler for `DELETE` method.
|
||||
pub fn delete<F, R>(&mut self, handler: F)
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static, {
|
||||
self.routes.insert(Method::DELETE, Box::new(FnHandler::new(handler)));
|
||||
self.routes.insert(Method::DELETE, Box::new(WrapHandler::new(handler)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<S: 'static> RouteHandler<S> for Resource<S> {
|
||||
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task) {
|
||||
|
197
src/route.rs
197
src/route.rs
@ -4,15 +4,14 @@ use std::marker::PhantomData;
|
||||
use std::result::Result as StdResult;
|
||||
|
||||
use actix::Actor;
|
||||
// use http::{header, Version};
|
||||
use futures::Stream;
|
||||
|
||||
use task::{Task, DrainFut, IoContext};
|
||||
use body::Binary;
|
||||
use error::{Error}; //, ExpectError, Result};
|
||||
use error::Error;
|
||||
use context::HttpContext;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use task::{Task, DrainFut, IoContext};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
@ -28,118 +27,32 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait defines object that could be regestered as resource route
|
||||
/// Trait defines object that could be regestered as route handler
|
||||
#[allow(unused_variables)]
|
||||
pub trait RouteHandler<S>: 'static {
|
||||
pub trait Handler<S>: 'static {
|
||||
type Result: Into<Reply>;
|
||||
|
||||
/// Handle request
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task);
|
||||
fn handle(&self, req: HttpRequest<S>) -> Self::Result;
|
||||
|
||||
/// Set route prefix
|
||||
fn set_prefix(&mut self, prefix: String) {}
|
||||
}
|
||||
|
||||
/*
|
||||
/// Actors with ability to handle http requests.
|
||||
#[allow(unused_variables)]
|
||||
pub trait RouteState {
|
||||
/// Shared state. State is shared with all routes within same application
|
||||
/// and could be accessed with `HttpRequest::state()` method.
|
||||
type State;
|
||||
|
||||
/// Handle `EXPECT` header. By default respones with `HTTP/1.1 100 Continue`
|
||||
fn expect(req: &mut HttpRequest<Self::State>, ctx: &mut Self::Context) -> Result<()>
|
||||
where Self: Actor<Context=HttpContext<Self>>
|
||||
{
|
||||
// handle expect header only for HTTP/1.1
|
||||
if req.version() == Version::HTTP_11 {
|
||||
if let Some(expect) = req.headers().get(header::EXPECT) {
|
||||
if let Ok(expect) = expect.to_str() {
|
||||
if expect.to_lowercase() == "100-continue" {
|
||||
ctx.write("HTTP/1.1 100 Continue\r\n\r\n");
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ExpectError::UnknownExpect.into())
|
||||
}
|
||||
} else {
|
||||
Err(ExpectError::Encoding.into())
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle incoming request with http actor.
|
||||
fn handle(req: HttpRequest<Self::State>) -> Result<Reply>
|
||||
where Self: Default, Self: Actor<Context=HttpContext<Self>>
|
||||
{
|
||||
Ok(HttpContext::new(req, Self::default()).into())
|
||||
}
|
||||
}*/
|
||||
|
||||
/// Fn() route handler
|
||||
pub(crate)
|
||||
struct FnHandler<S, R, F>
|
||||
/// Handler<S> for Fn()
|
||||
impl<F, R, S> Handler<S> for F
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply>,
|
||||
S: 'static,
|
||||
R: Into<Reply> + 'static
|
||||
{
|
||||
f: Box<F>,
|
||||
s: PhantomData<S>,
|
||||
}
|
||||
type Result = R;
|
||||
|
||||
impl<S, R, F> FnHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
pub fn new(f: F) -> Self {
|
||||
FnHandler{f: Box::new(f), s: PhantomData}
|
||||
fn handle(&self, req: HttpRequest<S>) -> R {
|
||||
(self)(req)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, R, F> RouteHandler<S> for FnHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Into<Reply> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task) {
|
||||
(self.f)(req).into().into(task)
|
||||
}
|
||||
}
|
||||
|
||||
/// Async route handler
|
||||
pub(crate)
|
||||
struct StreamHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Stream<Item=Frame, Error=Error> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
f: Box<F>,
|
||||
s: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, R, F> StreamHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Stream<Item=Frame, Error=Error> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
pub fn new(f: F) -> Self {
|
||||
StreamHandler{f: Box::new(f), s: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, R, F> RouteHandler<S> for StreamHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Stream<Item=Frame, Error=Error> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task) {
|
||||
task.stream((self.f)(req))
|
||||
}
|
||||
}
|
||||
/// Represents response process.
|
||||
pub struct Reply(ReplyItem);
|
||||
|
||||
enum ReplyItem {
|
||||
Message(HttpResponse),
|
||||
@ -147,11 +60,8 @@ enum ReplyItem {
|
||||
Stream(Box<Stream<Item=Frame, Error=Error>>),
|
||||
}
|
||||
|
||||
/// Represents response process.
|
||||
pub struct Reply(ReplyItem);
|
||||
impl Reply {
|
||||
|
||||
impl Reply
|
||||
{
|
||||
/// Create actor response
|
||||
pub fn actor<A, S>(ctx: HttpContext<A, S>) -> Reply
|
||||
where A: Actor<Context=HttpContext<A, S>>, S: 'static
|
||||
@ -209,3 +119,78 @@ impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> fo
|
||||
Reply(ReplyItem::Actor(Box::new(item)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait defines object that could be regestered as resource route
|
||||
pub(crate) trait RouteHandler<S>: 'static {
|
||||
/// Handle request
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task);
|
||||
|
||||
/// Set route prefix
|
||||
fn set_prefix(&mut self, _prefix: String) {}
|
||||
}
|
||||
|
||||
/// Route handler wrapper for Handler
|
||||
pub(crate)
|
||||
struct WrapHandler<S, H, R>
|
||||
where H: Handler<S, Result=R>,
|
||||
R: Into<Reply>,
|
||||
S: 'static,
|
||||
{
|
||||
h: H,
|
||||
s: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, H, R> WrapHandler<S, H, R>
|
||||
where H: Handler<S, Result=R>,
|
||||
R: Into<Reply>,
|
||||
S: 'static,
|
||||
{
|
||||
pub fn new(h: H) -> Self {
|
||||
WrapHandler{h: h, s: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, H, R> RouteHandler<S> for WrapHandler<S, H, R>
|
||||
where H: Handler<S, Result=R>,
|
||||
R: Into<Reply> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task) {
|
||||
self.h.handle(req).into().into(task)
|
||||
}
|
||||
|
||||
fn set_prefix(&mut self, prefix: String) {
|
||||
self.h.set_prefix(prefix)
|
||||
}
|
||||
}
|
||||
|
||||
/// Async route handler
|
||||
pub(crate)
|
||||
struct StreamHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Stream<Item=Frame, Error=Error> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
f: Box<F>,
|
||||
s: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, R, F> StreamHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Stream<Item=Frame, Error=Error> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
pub fn new(f: F) -> Self {
|
||||
StreamHandler{f: Box::new(f), s: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, R, F> RouteHandler<S> for StreamHandler<S, R, F>
|
||||
where F: Fn(HttpRequest<S>) -> R + 'static,
|
||||
R: Stream<Item=Frame, Error=Error> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task) {
|
||||
task.stream((self.f)(req))
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,8 @@ use std::fmt::Write;
|
||||
use std::fs::{File, DirEntry};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use task::Task;
|
||||
use route::RouteHandler;
|
||||
use mime_guess::get_mime_type;
|
||||
use route::Handler;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use httpcodes::{HTTPOk, HTTPNotFound, HTTPForbidden};
|
||||
@ -24,7 +23,7 @@ use httpcodes::{HTTPOk, HTTPNotFound, HTTPForbidden};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::default("/")
|
||||
/// .route_handler("/static", StaticFiles::new(".", true))
|
||||
/// .handler("/static", StaticFiles::new(".", true))
|
||||
/// .finish();
|
||||
/// }
|
||||
/// ```
|
||||
@ -128,7 +127,8 @@ impl StaticFiles {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static> RouteHandler<S> for StaticFiles {
|
||||
impl<S> Handler<S> for StaticFiles {
|
||||
type Result = Result<HttpResponse, io::Error>;
|
||||
|
||||
fn set_prefix(&mut self, prefix: String) {
|
||||
if prefix != "/" {
|
||||
@ -136,9 +136,9 @@ impl<S: 'static> RouteHandler<S> for StaticFiles {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle(&self, req: HttpRequest<S>, task: &mut Task) {
|
||||
fn handle(&self, req: HttpRequest<S>) -> Self::Result {
|
||||
if !self.accessible {
|
||||
task.reply(HTTPNotFound)
|
||||
Ok(HTTPNotFound.into())
|
||||
} else {
|
||||
let mut hidden = false;
|
||||
let filepath = req.path()[self.prefix.len()..]
|
||||
@ -152,7 +152,7 @@ impl<S: 'static> RouteHandler<S> for StaticFiles {
|
||||
|
||||
// hidden file
|
||||
if hidden {
|
||||
task.reply(HTTPNotFound)
|
||||
return Ok(HTTPNotFound.into())
|
||||
}
|
||||
|
||||
// full filepath
|
||||
@ -160,19 +160,19 @@ impl<S: 'static> RouteHandler<S> for StaticFiles {
|
||||
let filename = match self.directory.join(&filepath[idx..]).canonicalize() {
|
||||
Ok(fname) => fname,
|
||||
Err(err) => return match err.kind() {
|
||||
io::ErrorKind::NotFound => task.reply(HTTPNotFound),
|
||||
io::ErrorKind::PermissionDenied => task.reply(HTTPForbidden),
|
||||
_ => task.error(err),
|
||||
io::ErrorKind::NotFound => Ok(HTTPNotFound.into()),
|
||||
io::ErrorKind::PermissionDenied => Ok(HTTPForbidden.into()),
|
||||
_ => Err(err),
|
||||
}
|
||||
};
|
||||
|
||||
if filename.is_dir() {
|
||||
match self.index(&filepath[idx..], &filename) {
|
||||
Ok(resp) => task.reply(resp),
|
||||
Ok(resp) => Ok(resp),
|
||||
Err(err) => match err.kind() {
|
||||
io::ErrorKind::NotFound => task.reply(HTTPNotFound),
|
||||
io::ErrorKind::PermissionDenied => task.reply(HTTPForbidden),
|
||||
_ => task.error(err),
|
||||
io::ErrorKind::NotFound => Ok(HTTPNotFound.into()),
|
||||
io::ErrorKind::PermissionDenied => Ok(HTTPForbidden.into()),
|
||||
_ => Err(err),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -185,9 +185,9 @@ impl<S: 'static> RouteHandler<S> for StaticFiles {
|
||||
Ok(mut file) => {
|
||||
let mut data = Vec::new();
|
||||
let _ = file.read_to_end(&mut data);
|
||||
task.reply(resp.body(data).unwrap())
|
||||
Ok(resp.body(data).unwrap())
|
||||
},
|
||||
Err(err) => task.error(err),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user