1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-02-23 04:52:28 +00:00

add search method

This commit is contained in:
Dominic 2019-10-13 17:43:42 +02:00
parent 8429c425aa
commit 0153b2e22f
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
8 changed files with 84 additions and 13 deletions

View file

@ -16,7 +16,9 @@ gitlab = { repository = "msrd0/gotham-restful", branch = "master" }
[dependencies] [dependencies]
fake = "2.2" fake = "2.2"
gotham = "0.4" gotham = "0.4"
gotham_derive = "0.4"
gotham_restful = { path = "../gotham_restful", features = ["openapi"] } gotham_restful = { path = "../gotham_restful", features = ["openapi"] }
hyper = "0.12"
log = "0.4" log = "0.4"
log4rs = { version = "0.8", features = ["console_appender"], default-features = false } log4rs = { version = "0.8", features = ["console_appender"], default-features = false }
serde = "1" serde = "1"

View file

@ -1,3 +1,4 @@
#[macro_use] extern crate gotham_derive;
#[macro_use] extern crate log; #[macro_use] extern crate log;
use fake::{faker::internet::en::Username, Fake}; use fake::{faker::internet::en::Username, Fake};
@ -17,20 +18,12 @@ use log4rs::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Resource)] #[derive(Resource)]
#[rest_resource(ReadAll, Read, Create, DeleteAll, Delete, Update, UpdateAll)] #[rest_resource(ReadAll, Read, Search, Create, DeleteAll, Delete, Update, UpdateAll)]
struct Users struct Users
{ {
} }
// rest_resource!{Users, route => { #[derive(Deserialize, OpenapiType, Serialize, StateData, StaticResponseExtender)]
// route.read_all::<Self, _>();
// route.read::<Self, _, _>();
// route.create::<Self, _, _>();
// route.update_all::<Self, _, _>();
// route.update::<Self, _, _, _>();
// }}
#[derive(Deserialize, OpenapiType, Serialize)]
struct User struct User
{ {
username : String username : String
@ -53,6 +46,12 @@ fn read(_state : &mut State, id : u64) -> Success<User>
User { username: format!("{}{}", username, id) }.into() User { username: format!("{}{}", username, id) }.into()
} }
#[rest_search(Users)]
fn search(_state : &mut State, query : User) -> Success<User>
{
query.into()
}
#[rest_create(Users)] #[rest_create(Users)]
fn create(_state : &mut State, body : User) fn create(_state : &mut State, body : User)
{ {

View file

@ -30,6 +30,7 @@ pub use resource::{
Resource, Resource,
ResourceReadAll, ResourceReadAll,
ResourceRead, ResourceRead,
ResourceSearch,
ResourceCreate, ResourceCreate,
ResourceUpdateAll, ResourceUpdateAll,
ResourceUpdate, ResourceUpdate,

View file

@ -8,12 +8,14 @@ use crate::{
}; };
use futures::future::ok; use futures::future::ok;
use gotham::{ use gotham::{
extractor::QueryStringExtractor,
handler::{Handler, HandlerFuture, NewHandler}, handler::{Handler, HandlerFuture, NewHandler},
helpers::http::response::create_response, helpers::http::response::create_response,
pipeline::chain::PipelineHandleChain, pipeline::chain::PipelineHandleChain,
router::builder::*, router::builder::*,
state::State state::State
}; };
use hyper::Body;
use indexmap::IndexMap; use indexmap::IndexMap;
use log::error; use log::error;
use mime::{APPLICATION_JSON, TEXT_PLAIN}; use mime::{APPLICATION_JSON, TEXT_PLAIN};
@ -292,6 +294,22 @@ macro_rules! implOpenapiRouter {
(&mut *(self.0).0, self.1.to_string()).read::<Handler, ID, Res>() (&mut *(self.0).0, self.1.to_string()).read::<Handler, ID, Res>()
} }
fn search<Handler, Query, Res>(&mut self)
where
Query : ResourceType + QueryStringExtractor<Body> + Send + Sync + 'static,
Res : ResourceResult,
Handler : ResourceSearch<Query, Res>
{
let schema = (self.0).1.add_schema::<Res>();
let path = format!("/{}/search", &self.1);
let mut item = (self.0).1.remove_path(&self.1);
item.get = Some(new_operation(Res::default_status(), schema, vec![], None)); // TODO
(self.0).1.add_path(path, item);
(&mut *(self.0).0, self.1.to_string()).search::<Handler, Query, Res>()
}
fn create<Handler, Body, Res>(&mut self) fn create<Handler, Body, Res>(&mut self)
where where
Body : ResourceType, Body : ResourceType,

View file

@ -1,5 +1,8 @@
use crate::{DrawResourceRoutes, ResourceResult, ResourceType}; use crate::{DrawResourceRoutes, ResourceResult, ResourceType};
use gotham::state::State; use gotham::{
router::response::extender::StaticResponseExtender,
state::{State, StateData}
};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use std::panic::RefUnwindSafe; use std::panic::RefUnwindSafe;
@ -29,6 +32,14 @@ where
fn read(state : &mut State, id : ID) -> R; fn read(state : &mut State, id : ID) -> R;
} }
/// Handle a GET request on the Resource with additional search parameters.
pub trait ResourceSearch<Query : ResourceType, R : ResourceResult>
where
Query : ResourceType + StateData + StaticResponseExtender
{
fn search(state : &mut State, query : Query) -> R;
}
/// Handle a POST request on the Resource root. /// Handle a POST request on the Resource root.
pub trait ResourceCreate<Body : ResourceType, R : ResourceResult> pub trait ResourceCreate<Body : ResourceType, R : ResourceResult>
{ {
@ -36,7 +47,7 @@ pub trait ResourceCreate<Body : ResourceType, R : ResourceResult>
} }
/// Handle a PUT request on the Resource root. /// Handle a PUT request on the Resource root.
pub trait ResourceUpdateAll<Body : DeserializeOwned, R : ResourceResult> pub trait ResourceUpdateAll<Body : ResourceType, R : ResourceResult>
{ {
fn update_all(state : &mut State, body : Body) -> R; fn update_all(state : &mut State, body : Body) -> R;
} }

View file

@ -12,12 +12,14 @@ use futures::{
stream::Stream stream::Stream
}; };
use gotham::{ use gotham::{
extractor::QueryStringExtractor,
handler::{HandlerFuture, IntoHandlerError}, handler::{HandlerFuture, IntoHandlerError},
helpers::http::response::create_response, helpers::http::response::create_response,
pipeline::chain::PipelineHandleChain, pipeline::chain::PipelineHandleChain,
router::builder::*, router::builder::*,
state::{FromState, State} state::{FromState, State}
}; };
use hyper::Body;
use mime::APPLICATION_JSON; use mime::APPLICATION_JSON;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use std::panic::RefUnwindSafe; use std::panic::RefUnwindSafe;
@ -65,6 +67,12 @@ pub trait DrawResourceRoutes
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceRead<ID, Res>; Handler : ResourceRead<ID, Res>;
fn search<Handler, Query, Res>(&mut self)
where
Query : ResourceType + QueryStringExtractor<Body> + Send + Sync + 'static,
Res : ResourceResult,
Handler : ResourceSearch<Query, Res>;
fn create<Handler, Body, Res>(&mut self) fn create<Handler, Body, Res>(&mut self)
where where
Body : ResourceType, Body : ResourceType,
@ -175,6 +183,16 @@ where
to_handler_future(state, |state| Handler::read(state, id)) to_handler_future(state, |state| Handler::read(state, id))
} }
fn search_handler<Handler, Query, Res>(mut state : State) -> Box<HandlerFuture>
where
Query : ResourceType + QueryStringExtractor<Body> + Send + Sync + 'static,
Res : ResourceResult,
Handler : ResourceSearch<Query, Res>
{
let query = Query::take_from(&mut state);
to_handler_future(state, |state| Handler::search(state, query))
}
fn create_handler<Handler, Body, Res>(state : State) -> Box<HandlerFuture> fn create_handler<Handler, Body, Res>(state : State) -> Box<HandlerFuture>
where where
Body : ResourceType, Body : ResourceType,
@ -285,6 +303,17 @@ macro_rules! implDrawResourceRoutes {
.to(|state| read_handler::<Handler, ID, Res>(state)); .to(|state| read_handler::<Handler, ID, Res>(state));
} }
fn search<Handler, Query, Res>(&mut self)
where
Query : ResourceType + QueryStringExtractor<Body> + Send + Sync + 'static,
Res : ResourceResult,
Handler : ResourceSearch<Query, Res>
{
self.0.get(&format!("{}/search", self.1))
.with_query_string_extractor::<Query>()
.to(|state| search_handler::<Handler, Query, Res>(state));
}
fn create<Handler, Body, Res>(&mut self) fn create<Handler, Body, Res>(&mut self)
where where
Body : ResourceType, Body : ResourceType,

View file

@ -36,6 +36,13 @@ pub fn rest_read(attr : TokenStream, item : TokenStream) -> TokenStream
output output
} }
#[proc_macro_attribute]
pub fn rest_search(attr : TokenStream, item : TokenStream) -> TokenStream
{
let output = expand_method(Method::Search, attr, item);
output
}
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn rest_create(attr : TokenStream, item : TokenStream) -> TokenStream pub fn rest_create(attr : TokenStream, item : TokenStream) -> TokenStream
{ {

View file

@ -13,6 +13,7 @@ pub enum Method
{ {
ReadAll, ReadAll,
Read, Read,
Search,
Create, Create,
UpdateAll, UpdateAll,
Update, Update,
@ -28,6 +29,7 @@ impl FromStr for Method
match str { match str {
"ReadAll" | "read_all" => Ok(Self::ReadAll), "ReadAll" | "read_all" => Ok(Self::ReadAll),
"Read" | "read" => Ok(Self::Read), "Read" | "read" => Ok(Self::Read),
"Search" | "search" => Ok(Self::Search),
"Create" | "create" => Ok(Self::Create), "Create" | "create" => Ok(Self::Create),
"UpdateAll" | "update_all" => Ok(Self::UpdateAll), "UpdateAll" | "update_all" => Ok(Self::UpdateAll),
"Update" | "update" => Ok(Self::Update), "Update" | "update" => Ok(Self::Update),
@ -47,6 +49,7 @@ impl Method
let name = match self { let name = match self {
ReadAll => "ReadAll", ReadAll => "ReadAll",
Read => "Read", Read => "Read",
Search => "Search",
Create => "Create", Create => "Create",
UpdateAll => "UpdateAll", UpdateAll => "UpdateAll",
Update => "Update", Update => "Update",
@ -63,6 +66,7 @@ impl Method
let name = match self { let name = match self {
ReadAll => "read_all", ReadAll => "read_all",
Read => "read", Read => "read",
Search => "search",
Create => "create", Create => "create",
UpdateAll => "update_all", UpdateAll => "update_all",
Update => "update", Update => "update",