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:
parent
8429c425aa
commit
0153b2e22f
8 changed files with 84 additions and 13 deletions
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub use resource::{
|
||||||
Resource,
|
Resource,
|
||||||
ResourceReadAll,
|
ResourceReadAll,
|
||||||
ResourceRead,
|
ResourceRead,
|
||||||
|
ResourceSearch,
|
||||||
ResourceCreate,
|
ResourceCreate,
|
||||||
ResourceUpdateAll,
|
ResourceUpdateAll,
|
||||||
ResourceUpdate,
|
ResourceUpdate,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -284,7 +302,18 @@ macro_rules! implDrawResourceRoutes {
|
||||||
.with_path_extractor::<PathExtractor<ID>>()
|
.with_path_extractor::<PathExtractor<ID>>()
|
||||||
.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,
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Add table
Reference in a new issue