mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 16:02:59 +01:00
add filters support to scopes
This commit is contained in:
parent
a817ddb57b
commit
c755d71a8b
@ -9,6 +9,7 @@ use httprequest::HttpRequest;
|
|||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
use middleware::Middleware;
|
use middleware::Middleware;
|
||||||
use pipeline::{HandlerType, Pipeline, PipelineHandler};
|
use pipeline::{HandlerType, Pipeline, PipelineHandler};
|
||||||
|
use pred::Predicate;
|
||||||
use resource::ResourceHandler;
|
use resource::ResourceHandler;
|
||||||
use router::{Resource, Router};
|
use router::{Resource, Router};
|
||||||
use scope::Scope;
|
use scope::Scope;
|
||||||
@ -34,7 +35,7 @@ pub(crate) struct Inner<S> {
|
|||||||
|
|
||||||
enum PrefixHandlerType<S> {
|
enum PrefixHandlerType<S> {
|
||||||
Handler(String, Box<RouteHandler<S>>),
|
Handler(String, Box<RouteHandler<S>>),
|
||||||
Scope(Resource, Box<RouteHandler<S>>),
|
Scope(Resource, Box<RouteHandler<S>>, Vec<Box<Predicate<S>>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: 'static> PipelineHandler<S> for Inner<S> {
|
impl<S: 'static> PipelineHandler<S> for Inner<S> {
|
||||||
@ -51,7 +52,7 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
|
|||||||
}
|
}
|
||||||
HandlerType::Handler(idx) => match self.handlers[idx] {
|
HandlerType::Handler(idx) => match self.handlers[idx] {
|
||||||
PrefixHandlerType::Handler(_, ref mut hnd) => hnd.handle(req),
|
PrefixHandlerType::Handler(_, ref mut hnd) => hnd.handle(req),
|
||||||
PrefixHandlerType::Scope(_, ref mut hnd) => hnd.handle(req),
|
PrefixHandlerType::Scope(_, ref mut hnd, _) => hnd.handle(req),
|
||||||
},
|
},
|
||||||
HandlerType::Default => self.default.handle(req, None),
|
HandlerType::Default => self.default.handle(req, None),
|
||||||
}
|
}
|
||||||
@ -73,8 +74,8 @@ impl<S: 'static> HttpApplication<S> {
|
|||||||
let path: &'static str =
|
let path: &'static str =
|
||||||
unsafe { &*(&req.path()[inner.prefix..] as *const _) };
|
unsafe { &*(&req.path()[inner.prefix..] as *const _) };
|
||||||
let path_len = path.len();
|
let path_len = path.len();
|
||||||
for idx in 0..inner.handlers.len() {
|
'outer: for idx in 0..inner.handlers.len() {
|
||||||
match &inner.handlers[idx] {
|
match inner.handlers[idx] {
|
||||||
PrefixHandlerType::Handler(ref prefix, _) => {
|
PrefixHandlerType::Handler(ref prefix, _) => {
|
||||||
let m = {
|
let m = {
|
||||||
path.starts_with(prefix)
|
path.starts_with(prefix)
|
||||||
@ -96,10 +97,16 @@ impl<S: 'static> HttpApplication<S> {
|
|||||||
return HandlerType::Handler(idx);
|
return HandlerType::Handler(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrefixHandlerType::Scope(ref pattern, _) => {
|
PrefixHandlerType::Scope(ref pattern, _, ref filters) => {
|
||||||
if let Some(prefix_len) =
|
if let Some(prefix_len) =
|
||||||
pattern.match_prefix_with_params(path, req.match_info_mut())
|
pattern.match_prefix_with_params(path, req.match_info_mut())
|
||||||
{
|
{
|
||||||
|
for filter in filters {
|
||||||
|
if !filter.check(req) {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let prefix_len = inner.prefix + prefix_len - 1;
|
let prefix_len = inner.prefix + prefix_len - 1;
|
||||||
let path: &'static str =
|
let path: &'static str =
|
||||||
unsafe { &*(&req.path()[prefix_len..] as *const _) };
|
unsafe { &*(&req.path()[prefix_len..] as *const _) };
|
||||||
@ -361,7 +368,7 @@ where
|
|||||||
F: FnOnce(Scope<S>) -> Scope<S>,
|
F: FnOnce(Scope<S>) -> Scope<S>,
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let scope = Box::new(f(Scope::new()));
|
let mut scope = Box::new(f(Scope::new()));
|
||||||
|
|
||||||
let mut path = path.trim().trim_right_matches('/').to_owned();
|
let mut path = path.trim().trim_right_matches('/').to_owned();
|
||||||
if !path.is_empty() && !path.starts_with('/') {
|
if !path.is_empty() && !path.starts_with('/') {
|
||||||
@ -372,9 +379,11 @@ where
|
|||||||
}
|
}
|
||||||
let parts = self.parts.as_mut().expect("Use after finish");
|
let parts = self.parts.as_mut().expect("Use after finish");
|
||||||
|
|
||||||
|
let filters = scope.take_filters();
|
||||||
parts.handlers.push(PrefixHandlerType::Scope(
|
parts.handlers.push(PrefixHandlerType::Scope(
|
||||||
Resource::prefix("", &path),
|
Resource::prefix("", &path),
|
||||||
scope,
|
scope,
|
||||||
|
filters,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
169
src/scope.rs
169
src/scope.rs
@ -1,5 +1,6 @@
|
|||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use futures::{Async, Future, Poll};
|
use futures::{Async, Future, Poll};
|
||||||
@ -11,11 +12,13 @@ use httprequest::HttpRequest;
|
|||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
use middleware::{Finished as MiddlewareFinished, Middleware,
|
use middleware::{Finished as MiddlewareFinished, Middleware,
|
||||||
Response as MiddlewareResponse, Started as MiddlewareStarted};
|
Response as MiddlewareResponse, Started as MiddlewareStarted};
|
||||||
|
use pred::Predicate;
|
||||||
use resource::ResourceHandler;
|
use resource::ResourceHandler;
|
||||||
use router::Resource;
|
use router::Resource;
|
||||||
|
|
||||||
type Route<S> = UnsafeCell<Box<RouteHandler<S>>>;
|
type Route<S> = UnsafeCell<Box<RouteHandler<S>>>;
|
||||||
type ScopeResources<S> = Rc<Vec<(Resource, Rc<UnsafeCell<ResourceHandler<S>>>)>>;
|
type ScopeResources<S> = Rc<Vec<(Resource, Rc<UnsafeCell<ResourceHandler<S>>>)>>;
|
||||||
|
type NestedInfo<S> = (Resource, Route<S>, Vec<Box<Predicate<S>>>);
|
||||||
|
|
||||||
/// Resources scope
|
/// Resources scope
|
||||||
///
|
///
|
||||||
@ -25,8 +28,8 @@ type ScopeResources<S> = Rc<Vec<(Resource, Rc<UnsafeCell<ResourceHandler<S>>>)>>
|
|||||||
/// Scope prefix is always complete path segment, i.e `/app` would
|
/// Scope prefix is always complete path segment, i.e `/app` would
|
||||||
/// be converted to a `/app/` and it would not match `/app` path.
|
/// be converted to a `/app/` and it would not match `/app` path.
|
||||||
///
|
///
|
||||||
/// You can use variable path segments with `Path` extractor, also variable
|
/// You can get variable path segments from HttpRequest::match_info()`.
|
||||||
/// segments are available in `HttpRequest::match_info()`.
|
/// `Path` extractor also is able to extract scope level variable segments.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// # extern crate actix_web;
|
||||||
@ -48,7 +51,8 @@ type ScopeResources<S> = Rc<Vec<(Resource, Rc<UnsafeCell<ResourceHandler<S>>>)>>
|
|||||||
/// * /{project_id}/path3 - `HEAD` requests
|
/// * /{project_id}/path3 - `HEAD` requests
|
||||||
///
|
///
|
||||||
pub struct Scope<S: 'static> {
|
pub struct Scope<S: 'static> {
|
||||||
nested: Vec<(Resource, Route<S>)>,
|
filters: Vec<Box<Predicate<S>>>,
|
||||||
|
nested: Vec<NestedInfo<S>>,
|
||||||
middlewares: Rc<Vec<Box<Middleware<S>>>>,
|
middlewares: Rc<Vec<Box<Middleware<S>>>>,
|
||||||
default: Rc<UnsafeCell<ResourceHandler<S>>>,
|
default: Rc<UnsafeCell<ResourceHandler<S>>>,
|
||||||
resources: ScopeResources<S>,
|
resources: ScopeResources<S>,
|
||||||
@ -63,6 +67,7 @@ impl<S: 'static> Default for Scope<S> {
|
|||||||
impl<S: 'static> Scope<S> {
|
impl<S: 'static> Scope<S> {
|
||||||
pub fn new() -> Scope<S> {
|
pub fn new() -> Scope<S> {
|
||||||
Scope {
|
Scope {
|
||||||
|
filters: Vec::new(),
|
||||||
nested: Vec::new(),
|
nested: Vec::new(),
|
||||||
resources: Rc::new(Vec::new()),
|
resources: Rc::new(Vec::new()),
|
||||||
middlewares: Rc::new(Vec::new()),
|
middlewares: Rc::new(Vec::new()),
|
||||||
@ -70,6 +75,36 @@ impl<S: 'static> Scope<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn take_filters(&mut self) -> Vec<Box<Predicate<S>>> {
|
||||||
|
mem::replace(&mut self.filters, Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add match predicate to scoupe.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate actix_web;
|
||||||
|
/// use actix_web::{http, pred, App, HttpRequest, HttpResponse, Path};
|
||||||
|
///
|
||||||
|
/// fn index(data: Path<(String, String)>) -> &'static str {
|
||||||
|
/// "Welcome!"
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let app = App::new()
|
||||||
|
/// .scope("/app", |scope| {
|
||||||
|
/// scope.filter(pred::Header("content-type", "text/plain"))
|
||||||
|
/// .route("/test1", http::Method::GET, index)
|
||||||
|
/// .route("/test2", http::Method::POST,
|
||||||
|
/// |_: HttpRequest| HttpResponse::MethodNotAllowed())
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn filter<T: Predicate<S> + 'static>(mut self, p: T) -> Self {
|
||||||
|
self.filters.push(Box::new(p));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Create nested scope with new state.
|
/// Create nested scope with new state.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
@ -96,12 +131,13 @@ impl<S: 'static> Scope<S> {
|
|||||||
F: FnOnce(Scope<T>) -> Scope<T>,
|
F: FnOnce(Scope<T>) -> Scope<T>,
|
||||||
{
|
{
|
||||||
let scope = Scope {
|
let scope = Scope {
|
||||||
|
filters: Vec::new(),
|
||||||
nested: Vec::new(),
|
nested: Vec::new(),
|
||||||
resources: Rc::new(Vec::new()),
|
resources: Rc::new(Vec::new()),
|
||||||
middlewares: Rc::new(Vec::new()),
|
middlewares: Rc::new(Vec::new()),
|
||||||
default: Rc::new(UnsafeCell::new(ResourceHandler::default_not_found())),
|
default: Rc::new(UnsafeCell::new(ResourceHandler::default_not_found())),
|
||||||
};
|
};
|
||||||
let scope = f(scope);
|
let mut scope = f(scope);
|
||||||
|
|
||||||
let mut path = path.trim().trim_right_matches('/').to_owned();
|
let mut path = path.trim().trim_right_matches('/').to_owned();
|
||||||
if !path.is_empty() && !path.starts_with('/') {
|
if !path.is_empty() && !path.starts_with('/') {
|
||||||
@ -111,12 +147,14 @@ impl<S: 'static> Scope<S> {
|
|||||||
path.push('/');
|
path.push('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
let handler = UnsafeCell::new(Box::new(Wrapper {
|
let state = Rc::new(state);
|
||||||
scope,
|
let filters: Vec<Box<Predicate<S>>> = vec![Box::new(FiltersWrapper {
|
||||||
state: Rc::new(state),
|
state: Rc::clone(&state),
|
||||||
}));
|
filters: scope.take_filters(),
|
||||||
|
})];
|
||||||
|
let handler = UnsafeCell::new(Box::new(Wrapper { scope, state }));
|
||||||
self.nested
|
self.nested
|
||||||
.push((Resource::prefix("", &path), handler));
|
.push((Resource::prefix("", &path), handler, filters));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -147,12 +185,13 @@ impl<S: 'static> Scope<S> {
|
|||||||
F: FnOnce(Scope<S>) -> Scope<S>,
|
F: FnOnce(Scope<S>) -> Scope<S>,
|
||||||
{
|
{
|
||||||
let scope = Scope {
|
let scope = Scope {
|
||||||
|
filters: Vec::new(),
|
||||||
nested: Vec::new(),
|
nested: Vec::new(),
|
||||||
resources: Rc::new(Vec::new()),
|
resources: Rc::new(Vec::new()),
|
||||||
middlewares: Rc::new(Vec::new()),
|
middlewares: Rc::new(Vec::new()),
|
||||||
default: Rc::new(UnsafeCell::new(ResourceHandler::default_not_found())),
|
default: Rc::new(UnsafeCell::new(ResourceHandler::default_not_found())),
|
||||||
};
|
};
|
||||||
let scope = f(scope);
|
let mut scope = f(scope);
|
||||||
|
|
||||||
let mut path = path.trim().trim_right_matches('/').to_owned();
|
let mut path = path.trim().trim_right_matches('/').to_owned();
|
||||||
if !path.is_empty() && !path.starts_with('/') {
|
if !path.is_empty() && !path.starts_with('/') {
|
||||||
@ -162,9 +201,11 @@ impl<S: 'static> Scope<S> {
|
|||||||
path.push('/');
|
path.push('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let filters = scope.take_filters();
|
||||||
self.nested.push((
|
self.nested.push((
|
||||||
Resource::prefix("", &path),
|
Resource::prefix("", &path),
|
||||||
UnsafeCell::new(Box::new(scope)),
|
UnsafeCell::new(Box::new(scope)),
|
||||||
|
filters,
|
||||||
));
|
));
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -315,10 +356,15 @@ impl<S: 'static> RouteHandler<S> for Scope<S> {
|
|||||||
let len = req.prefix_len() as usize;
|
let len = req.prefix_len() as usize;
|
||||||
let path: &'static str = unsafe { &*(&req.path()[len..] as *const _) };
|
let path: &'static str = unsafe { &*(&req.path()[len..] as *const _) };
|
||||||
|
|
||||||
for &(ref prefix, ref handler) in &self.nested {
|
'outer: for &(ref prefix, ref handler, ref filters) in &self.nested {
|
||||||
if let Some(prefix_len) =
|
if let Some(prefix_len) =
|
||||||
prefix.match_prefix_with_params(path, req.match_info_mut())
|
prefix.match_prefix_with_params(path, req.match_info_mut())
|
||||||
{
|
{
|
||||||
|
for filter in filters {
|
||||||
|
if !filter.check(&mut req) {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
let prefix_len = len + prefix_len - 1;
|
let prefix_len = len + prefix_len - 1;
|
||||||
let path: &'static str =
|
let path: &'static str =
|
||||||
unsafe { &*(&req.path()[prefix_len..] as *const _) };
|
unsafe { &*(&req.path()[prefix_len..] as *const _) };
|
||||||
@ -363,6 +409,23 @@ impl<S: 'static, S2: 'static> RouteHandler<S2> for Wrapper<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FiltersWrapper<S: 'static> {
|
||||||
|
state: Rc<S>,
|
||||||
|
filters: Vec<Box<Predicate<S>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: 'static, S2: 'static> Predicate<S2> for FiltersWrapper<S> {
|
||||||
|
fn check(&self, req: &mut HttpRequest<S2>) -> bool {
|
||||||
|
let mut req = req.change_state(Rc::clone(&self.state));
|
||||||
|
for filter in &self.filters {
|
||||||
|
if !filter.check(&mut req) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Compose resource level middlewares with route handler.
|
/// Compose resource level middlewares with route handler.
|
||||||
struct Compose<S: 'static> {
|
struct Compose<S: 'static> {
|
||||||
info: ComposeInfo<S>,
|
info: ComposeInfo<S>,
|
||||||
@ -713,8 +776,9 @@ mod tests {
|
|||||||
|
|
||||||
use application::App;
|
use application::App;
|
||||||
use body::Body;
|
use body::Body;
|
||||||
use http::StatusCode;
|
use http::{Method, StatusCode};
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
|
use pred;
|
||||||
use test::TestRequest;
|
use test::TestRequest;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -730,6 +794,29 @@ mod tests {
|
|||||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_scope_filter() {
|
||||||
|
let mut app = App::new()
|
||||||
|
.scope("/app", |scope| {
|
||||||
|
scope
|
||||||
|
.filter(pred::Get())
|
||||||
|
.resource("/path1", |r| r.f(|_| HttpResponse::Ok()))
|
||||||
|
})
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app/path1")
|
||||||
|
.method(Method::POST)
|
||||||
|
.finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app/path1")
|
||||||
|
.method(Method::GET)
|
||||||
|
.finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_scope_variable_segment() {
|
fn test_scope_variable_segment() {
|
||||||
let mut app = App::new()
|
let mut app = App::new()
|
||||||
@ -748,7 +835,7 @@ mod tests {
|
|||||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||||
|
|
||||||
match resp.as_msg().body() {
|
match resp.as_msg().body() {
|
||||||
Body::Binary(ref b) => {
|
&Body::Binary(ref b) => {
|
||||||
let bytes: Bytes = b.clone().into();
|
let bytes: Bytes = b.clone().into();
|
||||||
assert_eq!(bytes, Bytes::from_static(b"project: project1"));
|
assert_eq!(bytes, Bytes::from_static(b"project: project1"));
|
||||||
}
|
}
|
||||||
@ -777,6 +864,33 @@ mod tests {
|
|||||||
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_scope_with_state_filter() {
|
||||||
|
struct State;
|
||||||
|
|
||||||
|
let mut app = App::new()
|
||||||
|
.scope("/app", |scope| {
|
||||||
|
scope.with_state("/t1", State, |scope| {
|
||||||
|
scope
|
||||||
|
.filter(pred::Get())
|
||||||
|
.resource("/path1", |r| r.f(|_| HttpResponse::Ok()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app/t1/path1")
|
||||||
|
.method(Method::POST)
|
||||||
|
.finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app/t1/path1")
|
||||||
|
.method(Method::GET)
|
||||||
|
.finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nested_scope() {
|
fn test_nested_scope() {
|
||||||
let mut app = App::new()
|
let mut app = App::new()
|
||||||
@ -792,6 +906,31 @@ mod tests {
|
|||||||
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nested_scope_filter() {
|
||||||
|
let mut app = App::new()
|
||||||
|
.scope("/app", |scope| {
|
||||||
|
scope.nested("/t1", |scope| {
|
||||||
|
scope
|
||||||
|
.filter(pred::Get())
|
||||||
|
.resource("/path1", |r| r.f(|_| HttpResponse::Ok()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app/t1/path1")
|
||||||
|
.method(Method::POST)
|
||||||
|
.finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app/t1/path1")
|
||||||
|
.method(Method::GET)
|
||||||
|
.finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nested_scope_with_variable_segment() {
|
fn test_nested_scope_with_variable_segment() {
|
||||||
let mut app = App::new()
|
let mut app = App::new()
|
||||||
@ -814,7 +953,7 @@ mod tests {
|
|||||||
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
||||||
|
|
||||||
match resp.as_msg().body() {
|
match resp.as_msg().body() {
|
||||||
Body::Binary(ref b) => {
|
&Body::Binary(ref b) => {
|
||||||
let bytes: Bytes = b.clone().into();
|
let bytes: Bytes = b.clone().into();
|
||||||
assert_eq!(bytes, Bytes::from_static(b"project: project_1"));
|
assert_eq!(bytes, Bytes::from_static(b"project: project_1"));
|
||||||
}
|
}
|
||||||
@ -847,7 +986,7 @@ mod tests {
|
|||||||
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
||||||
|
|
||||||
match resp.as_msg().body() {
|
match resp.as_msg().body() {
|
||||||
Body::Binary(ref b) => {
|
&Body::Binary(ref b) => {
|
||||||
let bytes: Bytes = b.clone().into();
|
let bytes: Bytes = b.clone().into();
|
||||||
assert_eq!(bytes, Bytes::from_static(b"project: test - 1"));
|
assert_eq!(bytes, Bytes::from_static(b"project: test - 1"));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user