diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 18413f8..6ba7d54 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,7 +13,6 @@ test-default:
- cargo -V
script:
- cargo test --workspace --lib
- - cargo test --workspace --doc
cache:
paths:
- cargo/
@@ -23,6 +22,7 @@ test-all:
stage: test
image: msrd0/rust:alpine-tarpaulin
before_script:
+ - apk add --no-cache postgresql-dev
- cargo -V
script:
- cargo test --workspace --all-features --doc
diff --git a/README.md b/README.md
index 1a7e323..2e6c996 100644
--- a/README.md
+++ b/README.md
@@ -23,58 +23,71 @@
-This crate is an extension to the popular [gotham web framework][gotham] for Rust. The idea is to
-have several RESTful resources that can be added to the gotham router. This crate will take care
-of everything else, like parsing path/query parameters, request bodies, and writing response
-bodies, relying on [`serde`][serde] and [`serde_json`][serde_json] for (de)serializing. If you
-enable the `openapi` feature, you can also generate an OpenAPI Specification from your RESTful
-resources.
-
**Note:** The `stable` branch contains some bugfixes against the last release. The `master`
branch currently tracks gotham's master branch and the next release will use gotham 0.5.0 and be
compatible with the new future / async stuff.
-## Usage
+This crate is an extension to the popular [gotham web framework][gotham] for Rust. It allows you to
+create resources with assigned methods that aim to be a more convenient way of creating handlers
+for requests. Assuming you assign `/foobar` to your resource, you can implement the following
+methods:
-A basic server with only one resource, handling a simple `GET` request, could look like this:
+| Method Name | Required Arguments | HTTP Verb | HTTP Path |
+| ----------- | ------------------ | --------- | ----------- |
+| read_all | | GET | /foobar |
+| read | id | GET | /foobar/:id |
+| search | query | GET | /foobar/search |
+| create | body | POST | /foobar |
+| change_all | body | PUT | /foobar |
+| change | id, body | PUT | /foobar/:id |
+| remove_all | | DELETE | /foobar |
+| remove | id | DELETE | /foobar/:id |
+
+Each of those methods has a macro that creates the neccessary boilerplate for the Resource. A
+simple example could look like this:
```rust
-/// Our RESTful Resource.
+/// Our RESTful resource.
#[derive(Resource)]
-#[rest_resource(read_all)]
-struct UsersResource;
+#[resource(read)]
+struct FooResource;
-/// Our return type.
-#[derive(Deserialize, Serialize)]
-struct User {
- id: i64,
- username: String,
- email: String
+/// The return type of the foo read method.
+#[derive(Serialize)]
+struct Foo {
+ id: u64
}
-/// Our handler method.
-#[rest_read_all(UsersResource)]
-fn read_all(_state: &mut State) -> Success> {
- vec![User {
- id: 1,
- username: "h4ck3r".to_string(),
- email: "h4ck3r@example.org".to_string()
- }].into()
-}
-
-/// Our main method.
-fn main() {
- gotham::start("127.0.0.1:8080", build_simple_router(|route| {
- route.resource::("users");
- }));
+/// The foo read method handler.
+#[read(FooResource)]
+fn read(id: u64) -> Success {
+ Foo { id }.into()
}
```
-Uploads and Downloads can also be handled:
+## Arguments
+
+Some methods require arguments. Those should be
+ * **id** Should be a deserializable json-primitive like `i64` or `String`.
+ * **body** Should be any deserializable object, or any type implementing [`RequestBody`].
+ * **query** Should be any deserializable object whose variables are json-primitives. It will
+ however not be parsed from json, but from HTTP GET parameters like in `search?id=1`. The
+ type needs to implement [`QueryStringExtractor`].
+
+Additionally, non-async handlers may take a reference to gotham's [`State`]. If you need to
+have an async handler (that is, the function that the method macro is invoked on is declared
+as `async fn`), consider returning the boxed future instead. Since [`State`] does not implement
+`Sync` there is unfortunately no more convenient way.
+
+## Uploads and Downloads
+
+By default, every request body is parsed from json, and every respone is converted to json using
+[serde_json]. However, you may also use raw bodies. This is an example where the request body
+is simply returned as the response again, no json parsing involved:
```rust
#[derive(Resource)]
-#[rest_resource(create)]
+#[resource(create)]
struct ImageResource;
#[derive(FromBody, RequestBody)]
@@ -84,23 +97,105 @@ struct RawImage {
content_type: Mime
}
-#[rest_create(ImageResource)]
-fn create(_state : &mut State, body : RawImage) -> Raw> {
+#[create(ImageResource)]
+fn create(body : RawImage) -> Raw> {
Raw::new(body.content, body.content_type)
}
```
-Look at the [example] for more methods and usage with the `openapi` feature.
+## Features
-## Known Issues
+To make life easier for common use-cases, this create offers a few features that might be helpful
+when you implement your web server.
-These are currently known major issues. For a complete list please see
-[the issue tracker](https://gitlab.com/msrd0/gotham-restful/issues).
-If you encounter any issues that aren't yet reported, please report them
-[here](https://gitlab.com/msrd0/gotham-restful/issues/new).
+### Authentication Feature
- - Enabling the `openapi` feature might break code ([#4](https://gitlab.com/msrd0/gotham-restful/issues/4))
- - For `chrono`'s `DateTime` types, the format is `date-time` instead of `datetime` ([openapiv3#14](https://github.com/glademiller/openapiv3/pull/14))
+In order to enable authentication support, enable the `auth` feature gate. This allows you to
+register a middleware that can automatically check for the existence of an JWT authentication
+token. Besides being supported by the method macros, it supports to lookup the required JWT secret
+with the JWT data, hence you can use several JWT secrets and decide on the fly which secret to use.
+None of this is currently supported by gotham's own JWT middleware.
+
+A simple example that uses only a single secret could look like this:
+
+```rust
+#[derive(Resource)]
+#[resource(read)]
+struct SecretResource;
+
+#[derive(Serialize)]
+struct Secret {
+ id: u64,
+ intended_for: String
+}
+
+#[derive(Deserialize, Clone)]
+struct AuthData {
+ sub: String,
+ exp: u64
+}
+
+#[read(SecretResource)]
+fn read(auth: AuthStatus, id: u64) -> AuthSuccess {
+ let intended_for = auth.ok()?.sub;
+ Ok(Secret { id, intended_for })
+}
+
+fn main() {
+ let auth: AuthMiddleware = AuthMiddleware::new(
+ AuthSource::AuthorizationHeader,
+ AuthValidation::default(),
+ StaticAuthHandler::from_array(b"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc")
+ );
+ let (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());
+ gotham::start("127.0.0.1:8080", build_router(chain, pipelines, |route| {
+ route.resource::("secret");
+ }));
+}
+```
+
+### Database Feature
+
+The database feature allows an easy integration of [diesel] into your handler functions. Please
+note however that due to the way gotham's diesel middleware implementation, it is not possible
+to run async code while holding a database connection. If you need to combine async and database,
+you'll need to borrow the connection from the [`State`] yourself and return a boxed future.
+
+A simple non-async example could look like this:
+
+```rust
+#[derive(Resource)]
+#[resource(read_all)]
+struct FooResource;
+
+#[derive(Queryable, Serialize)]
+struct Foo {
+ id: i64,
+ value: String
+}
+
+#[read_all(FooResource)]
+fn read_all(conn: &PgConnection) -> QueryResult> {
+ foo::table.load(conn)
+}
+
+type Repo = gotham_middleware_diesel::Repo;
+
+fn main() {
+ let repo = Repo::new(&env::var("DATABASE_URL").unwrap());
+ let diesel = DieselMiddleware::new(repo);
+
+ let (chain, pipelines) = single_pipeline(new_pipeline().add(diesel).build());
+ gotham::start("127.0.0.1:8080", build_router(chain, pipelines, |route| {
+ route.resource::("foo");
+ }));
+}
+```
+
+## Examples
+
+There is a lack of good examples, but there is currently a collection of code in the [example]
+directory, that might help you. Any help writing more examples is highly appreciated.
## License
@@ -109,7 +204,10 @@ Licensed under your option of:
- [Eclipse Public License Version 2.0](https://gitlab.com/msrd0/gotham-restful/blob/master/LICENSE-EPL)
-[example]: https://gitlab.com/msrd0/gotham-restful/tree/master/example
-[gotham]: https://gotham.rs/
-[serde]: https://github.com/serde-rs/serde#serde-----
-[serde_json]: https://github.com/serde-rs/json#serde-json----
+ [diesel]: https://diesel.rs/
+ [example]: https://gitlab.com/msrd0/gotham-restful/tree/master/example
+ [gotham]: https://gotham.rs/
+ [serde_json]: https://github.com/serde-rs/json#serde-json----
+ [`QueryStringExtractor`]: ../gotham/extractor/trait.QueryStringExtractor.html
+ [`RequestBody`]: trait.RequestBody.html
+ [`State`]: ../gotham/state/struct.State.html
diff --git a/example/src/main.rs b/example/src/main.rs
index d062710..d300bd8 100644
--- a/example/src/main.rs
+++ b/example/src/main.rs
@@ -18,13 +18,13 @@ use log4rs::{
use serde::{Deserialize, Serialize};
#[derive(Resource)]
-#[rest_resource(ReadAll, Read, Search, Create, DeleteAll, Delete, Update, UpdateAll)]
+#[resource(read_all, read, search, create, change_all, change, remove, remove_all)]
struct Users
{
}
#[derive(Resource)]
-#[rest_resource(ReadAll)]
+#[resource(ReadAll)]
struct Auth
{
}
@@ -35,7 +35,7 @@ struct User
username : String
}
-#[rest_read_all(Users)]
+#[read_all(Users)]
fn read_all() -> Success>>
{
vec![Username().fake(), Username().fake()]
@@ -45,50 +45,50 @@ fn read_all() -> Success>>
.into()
}
-#[rest_read(Users)]
+#[read(Users)]
fn read(id : u64) -> Success
{
let username : String = Username().fake();
User { username: format!("{}{}", username, id) }.into()
}
-#[rest_search(Users)]
+#[search(Users)]
fn search(query : User) -> Success
{
query.into()
}
-#[rest_create(Users)]
+#[create(Users)]
fn create(body : User)
{
info!("Created User: {}", body.username);
}
-#[rest_update_all(Users)]
+#[change_all(Users)]
fn update_all(body : Vec)
{
info!("Changing all Users to {:?}", body.into_iter().map(|u| u.username).collect::>());
}
-#[rest_update(Users)]
+#[change(Users)]
fn update(id : u64, body : User)
{
info!("Change User {} to {}", id, body.username);
}
-#[rest_delete_all(Users)]
+#[delete_all(Users)]
fn delete_all()
{
info!("Delete all Users");
}
-#[rest_delete(Users)]
+#[delete(Users)]
fn delete(id : u64)
{
info!("Delete User {}", id);
}
-#[rest_read_all(Auth)]
+#[read_all(Auth)]
fn auth_read_all(auth : AuthStatus<()>) -> AuthSuccess
{
match auth {
diff --git a/gotham_restful/Cargo.toml b/gotham_restful/Cargo.toml
index 78359fe..2e65978 100644
--- a/gotham_restful/Cargo.toml
+++ b/gotham_restful/Cargo.toml
@@ -36,11 +36,12 @@ thiserror = "1.0.15"
uuid = { version = ">= 0.1, < 0.9", optional = true }
[dev-dependencies]
+diesel = { version = "1.4.4", features = ["postgres"] }
futures-executor = "0.3.4"
paste = "0.1.10"
[features]
-default = []
+default = ["errorlog"]
auth = ["gotham_restful_derive/auth", "base64", "cookie", "jsonwebtoken"]
errorlog = []
database = ["gotham_restful_derive/database", "gotham_middleware_diesel"]
diff --git a/gotham_restful/src/auth.rs b/gotham_restful/src/auth.rs
index c109f07..0888ac3 100644
--- a/gotham_restful/src/auth.rs
+++ b/gotham_restful/src/auth.rs
@@ -1,4 +1,4 @@
-use crate::HeaderName;
+use crate::{AuthError, Forbidden, HeaderName};
use cookie::CookieJar;
use futures_util::{future, future::{FutureExt, TryFutureExt}};
use gotham::{
@@ -58,6 +58,17 @@ where
{
}
+impl AuthStatus
+{
+ pub fn ok(self) -> Result
+ {
+ match self {
+ Self::Authenticated(data) => Ok(data),
+ _ => Err(Forbidden)
+ }
+ }
+}
+
/// The source of the authentication token in the request.
#[derive(Clone, Debug, StateData)]
pub enum AuthSource
@@ -134,7 +145,7 @@ simply add it to your pipeline and request it inside your handler:
# use serde::{Deserialize, Serialize};
#
#[derive(Resource)]
-#[rest_resource(read_all)]
+#[resource(read_all)]
struct AuthResource;
#[derive(Debug, Deserialize, Clone)]
@@ -143,7 +154,7 @@ struct AuthData {
exp: u64
}
-#[rest_read_all(AuthResource)]
+#[read_all(AuthResource)]
fn read_all(auth : &AuthStatus) -> Success {
format!("{:?}", auth).into()
}
diff --git a/gotham_restful/src/lib.rs b/gotham_restful/src/lib.rs
index c96e905..1e01f08 100644
--- a/gotham_restful/src/lib.rs
+++ b/gotham_restful/src/lib.rs
@@ -2,67 +2,85 @@
#![warn(missing_debug_implementations, rust_2018_idioms)]
#![deny(intra_doc_link_resolution_failure)]
/*!
-This crate is an extension to the popular [gotham web framework][gotham] for Rust. The idea is to
-have several RESTful resources that can be added to the gotham router. This crate will take care
-of everything else, like parsing path/query parameters, request bodies, and writing response
-bodies, relying on [`serde`][serde] and [`serde_json`][serde_json] for (de)serializing. If you
-enable the `openapi` feature, you can also generate an OpenAPI Specification from your RESTful
-resources.
-
**Note:** The `stable` branch contains some bugfixes against the last release. The `master`
branch currently tracks gotham's master branch and the next release will use gotham 0.5.0 and be
compatible with the new future / async stuff.
-# Usage
+This crate is an extension to the popular [gotham web framework][gotham] for Rust. It allows you to
+create resources with assigned methods that aim to be a more convenient way of creating handlers
+for requests. Assuming you assign `/foobar` to your resource, you can implement the following
+methods:
-A basic server with only one resource, handling a simple `GET` request, could look like this:
+| Method Name | Required Arguments | HTTP Verb | HTTP Path |
+| ----------- | ------------------ | --------- | ----------- |
+| read_all | | GET | /foobar |
+| read | id | GET | /foobar/:id |
+| search | query | GET | /foobar/search |
+| create | body | POST | /foobar |
+| change_all | body | PUT | /foobar |
+| change | id, body | PUT | /foobar/:id |
+| remove_all | | DELETE | /foobar |
+| remove | id | DELETE | /foobar/:id |
+
+Each of those methods has a macro that creates the neccessary boilerplate for the Resource. A
+simple example could look like this:
```rust,no_run
# #[macro_use] extern crate gotham_restful_derive;
-# use gotham::{router::builder::*, state::State};
-# use gotham_restful::{DrawResources, Resource, Success};
+# use gotham::router::builder::*;
+# use gotham_restful::*;
# use serde::{Deserialize, Serialize};
-/// Our RESTful Resource.
+/// Our RESTful resource.
#[derive(Resource)]
-#[rest_resource(read_all)]
-struct UsersResource;
+#[resource(read)]
+struct FooResource;
-/// Our return type.
-#[derive(Deserialize, Serialize)]
+/// The return type of the foo read method.
+#[derive(Serialize)]
# #[derive(OpenapiType)]
-struct User {
- id: i64,
- username: String,
- email: String
+struct Foo {
+ id: u64
}
-/// Our handler method.
-#[rest_read_all(UsersResource)]
-fn read_all(_state: &mut State) -> Success> {
- vec![User {
- id: 1,
- username: "h4ck3r".to_string(),
- email: "h4ck3r@example.org".to_string()
- }].into()
-}
-
-/// Our main method.
-fn main() {
- gotham::start("127.0.0.1:8080", build_simple_router(|route| {
- route.resource::("users");
- }));
+/// The foo read method handler.
+#[read(FooResource)]
+fn read(id: u64) -> Success {
+ Foo { id }.into()
}
+# fn main() {
+# gotham::start("127.0.0.1:8080", build_simple_router(|route| {
+# route.resource::("foo");
+# }));
+# }
```
-Uploads and Downloads can also be handled:
+# Arguments
+
+Some methods require arguments. Those should be
+ * **id** Should be a deserializable json-primitive like `i64` or `String`.
+ * **body** Should be any deserializable object, or any type implementing [`RequestBody`].
+ * **query** Should be any deserializable object whose variables are json-primitives. It will
+ however not be parsed from json, but from HTTP GET parameters like in `search?id=1`. The
+ type needs to implement [`QueryStringExtractor`].
+
+Additionally, non-async handlers may take a reference to gotham's [`State`]. If you need to
+have an async handler (that is, the function that the method macro is invoked on is declared
+as `async fn`), consider returning the boxed future instead. Since [`State`] does not implement
+`Sync` there is unfortunately no more convenient way.
+
+# Uploads and Downloads
+
+By default, every request body is parsed from json, and every respone is converted to json using
+[serde_json]. However, you may also use raw bodies. This is an example where the request body
+is simply returned as the response again, no json parsing involved:
```rust,no_run
# #[macro_use] extern crate gotham_restful_derive;
-# use gotham::{router::builder::*, state::State};
-# use gotham_restful::{DrawResources, Mime, Raw, Resource, Success};
+# use gotham::router::builder::*;
+# use gotham_restful::*;
# use serde::{Deserialize, Serialize};
#[derive(Resource)]
-#[rest_resource(create)]
+#[resource(create)]
struct ImageResource;
#[derive(FromBody, RequestBody)]
@@ -72,8 +90,8 @@ struct RawImage {
content_type: Mime
}
-#[rest_create(ImageResource)]
-fn create(_state : &mut State, body : RawImage) -> Raw> {
+#[create(ImageResource)]
+fn create(body : RawImage) -> Raw> {
Raw::new(body.content, body.content_type)
}
# fn main() {
@@ -83,17 +101,119 @@ fn create(_state : &mut State, body : RawImage) -> Raw> {
# }
```
-Look at the [example] for more methods and usage with the `openapi` feature.
+# Features
-# Known Issues
+To make life easier for common use-cases, this create offers a few features that might be helpful
+when you implement your web server.
-These are currently known major issues. For a complete list please see
-[the issue tracker](https://gitlab.com/msrd0/gotham-restful/issues).
-If you encounter any issues that aren't yet reported, please report them
-[here](https://gitlab.com/msrd0/gotham-restful/issues/new).
+## Authentication Feature
- - Enabling the `openapi` feature might break code ([#4](https://gitlab.com/msrd0/gotham-restful/issues/4))
- - For `chrono`'s `DateTime` types, the format is `date-time` instead of `datetime` ([openapiv3#14](https://github.com/glademiller/openapiv3/pull/14))
+In order to enable authentication support, enable the `auth` feature gate. This allows you to
+register a middleware that can automatically check for the existence of an JWT authentication
+token. Besides being supported by the method macros, it supports to lookup the required JWT secret
+with the JWT data, hence you can use several JWT secrets and decide on the fly which secret to use.
+None of this is currently supported by gotham's own JWT middleware.
+
+A simple example that uses only a single secret could look like this:
+
+```rust,no_run
+# #[macro_use] extern crate gotham_restful_derive;
+# use gotham::{router::builder::*, pipeline::{new_pipeline, single::single_pipeline}, state::State};
+# use gotham_restful::*;
+# use serde::{Deserialize, Serialize};
+#[derive(Resource)]
+#[resource(read)]
+struct SecretResource;
+
+#[derive(Serialize)]
+# #[derive(OpenapiType)]
+struct Secret {
+ id: u64,
+ intended_for: String
+}
+
+#[derive(Deserialize, Clone)]
+struct AuthData {
+ sub: String,
+ exp: u64
+}
+
+#[read(SecretResource)]
+fn read(auth: AuthStatus, id: u64) -> AuthSuccess {
+ let intended_for = auth.ok()?.sub;
+ Ok(Secret { id, intended_for })
+}
+
+fn main() {
+ let auth: AuthMiddleware = AuthMiddleware::new(
+ AuthSource::AuthorizationHeader,
+ AuthValidation::default(),
+ StaticAuthHandler::from_array(b"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc")
+ );
+ let (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());
+ gotham::start("127.0.0.1:8080", build_router(chain, pipelines, |route| {
+ route.resource::("secret");
+ }));
+}
+```
+
+## Database Feature
+
+The database feature allows an easy integration of [diesel] into your handler functions. Please
+note however that due to the way gotham's diesel middleware implementation, it is not possible
+to run async code while holding a database connection. If you need to combine async and database,
+you'll need to borrow the connection from the [`State`] yourself and return a boxed future.
+
+A simple non-async example could look like this:
+
+```rust,no_run
+# #[macro_use] extern crate diesel;
+# #[macro_use] extern crate gotham_restful_derive;
+# use diesel::{table, PgConnection, QueryResult, RunQueryDsl};
+# use gotham::{router::builder::*, pipeline::{new_pipeline, single::single_pipeline}, state::State};
+# use gotham_middleware_diesel::DieselMiddleware;
+# use gotham_restful::*;
+# use serde::{Deserialize, Serialize};
+# use std::env;
+# table! {
+# foo (id) {
+# id -> Int8,
+# value -> Text,
+# }
+# }
+#[derive(Resource)]
+#[resource(read_all)]
+struct FooResource;
+
+#[derive(Queryable, Serialize)]
+# #[derive(OpenapiType)]
+struct Foo {
+ id: i64,
+ value: String
+}
+
+#[read_all(FooResource)]
+fn read_all(conn: &PgConnection) -> QueryResult> {
+ foo::table.load(conn)
+}
+
+type Repo = gotham_middleware_diesel::Repo;
+
+fn main() {
+ let repo = Repo::new(&env::var("DATABASE_URL").unwrap());
+ let diesel = DieselMiddleware::new(repo);
+
+ let (chain, pipelines) = single_pipeline(new_pipeline().add(diesel).build());
+ gotham::start("127.0.0.1:8080", build_router(chain, pipelines, |route| {
+ route.resource::("foo");
+ }));
+}
+```
+
+# Examples
+
+There is a lack of good examples, but there is currently a collection of code in the [example]
+directory, that might help you. Any help writing more examples is highly appreciated.
# License
@@ -102,10 +222,13 @@ Licensed under your option of:
- [Eclipse Public License Version 2.0](https://gitlab.com/msrd0/gotham-restful/blob/master/LICENSE-EPL)
-[example]: https://gitlab.com/msrd0/gotham-restful/tree/master/example
-[gotham]: https://gotham.rs/
-[serde]: https://github.com/serde-rs/serde#serde-----
-[serde_json]: https://github.com/serde-rs/json#serde-json----
+ [diesel]: https://diesel.rs/
+ [example]: https://gitlab.com/msrd0/gotham-restful/tree/master/example
+ [gotham]: https://gotham.rs/
+ [serde_json]: https://github.com/serde-rs/json#serde-json----
+ [`QueryStringExtractor`]: ../gotham/extractor/trait.QueryStringExtractor.html
+ [`RequestBody`]: trait.RequestBody.html
+ [`State`]: ../gotham/state/struct.State.html
*/
// weird proc macro issue
@@ -175,10 +298,10 @@ pub use resource::{
ResourceRead,
ResourceSearch,
ResourceCreate,
- ResourceUpdateAll,
- ResourceUpdate,
- ResourceDeleteAll,
- ResourceDelete
+ ResourceChangeAll,
+ ResourceChange,
+ ResourceRemoveAll,
+ ResourceRemove
};
mod response;
diff --git a/gotham_restful/src/openapi/router.rs b/gotham_restful/src/openapi/router.rs
index 1fa3ccf..86d92cb 100644
--- a/gotham_restful/src/openapi/router.rs
+++ b/gotham_restful/src/openapi/router.rs
@@ -106,7 +106,7 @@ macro_rules! implOpenapiRouter {
(&mut *(self.0).router, self.1).create::()
}
- fn update_all(&mut self)
+ fn change_all(&mut self)
where
Handler::Res : 'static,
Handler::Body : 'static
@@ -119,10 +119,10 @@ macro_rules! implOpenapiRouter {
item.put = Some(OperationDescription::new::(schema).with_body::(body_schema).into_operation());
(self.0).openapi_builder.add_path(path, item);
- (&mut *(self.0).router, self.1).update_all::()
+ (&mut *(self.0).router, self.1).change_all::()
}
- fn update(&mut self)
+ fn change(&mut self)
where
Handler::Res : 'static,
Handler::Body : 'static
@@ -136,10 +136,10 @@ macro_rules! implOpenapiRouter {
item.put = Some(OperationDescription::new::(schema).add_path_param("id", id_schema).with_body::(body_schema).into_operation());
(self.0).openapi_builder.add_path(path, item);
- (&mut *(self.0).router, self.1).update::()
+ (&mut *(self.0).router, self.1).change::()
}
- fn delete_all(&mut self)
+ fn remove_all(&mut self)
{
let schema = (self.0).openapi_builder.add_schema::();
@@ -148,10 +148,10 @@ macro_rules! implOpenapiRouter {
item.delete = Some(OperationDescription::new::(schema).into_operation());
(self.0).openapi_builder.add_path(path, item);
- (&mut *(self.0).router, self.1).delete_all::()
+ (&mut *(self.0).router, self.1).remove_all::()
}
- fn delete(&mut self)
+ fn remove(&mut self)
{
let schema = (self.0).openapi_builder.add_schema::();
let id_schema = (self.0).openapi_builder.add_schema::();
@@ -161,7 +161,7 @@ macro_rules! implOpenapiRouter {
item.delete = Some(OperationDescription::new::(schema).add_path_param("id", id_schema).into_operation());
(self.0).openapi_builder.add_path(path, item);
- (&mut *(self.0).router, self.1).delete::()
+ (&mut *(self.0).router, self.1).remove::()
}
}
diff --git a/gotham_restful/src/resource.rs b/gotham_restful/src/resource.rs
index 360f2a1..6e2d5cd 100644
--- a/gotham_restful/src/resource.rs
+++ b/gotham_restful/src/resource.rs
@@ -68,32 +68,32 @@ pub trait ResourceCreate : ResourceMethod
}
/// Handle a PUT request on the Resource root.
-pub trait ResourceUpdateAll : ResourceMethod
+pub trait ResourceChangeAll : ResourceMethod
{
type Body : RequestBody;
- fn update_all(state : State, body : Self::Body) -> Pin + Send>>;
+ fn change_all(state : State, body : Self::Body) -> Pin + Send>>;
}
/// Handle a PUT request on the Resource with an id.
-pub trait ResourceUpdate : ResourceMethod
+pub trait ResourceChange : ResourceMethod
{
type Body : RequestBody;
type ID : ResourceID + 'static;
- fn update(state : State, id : Self::ID, body : Self::Body) -> Pin + Send>>;
+ fn change(state : State, id : Self::ID, body : Self::Body) -> Pin + Send>>;
}
/// Handle a DELETE request on the Resource root.
-pub trait ResourceDeleteAll : ResourceMethod
+pub trait ResourceRemoveAll : ResourceMethod
{
- fn delete_all(state : State) -> Pin + Send>>;
+ fn remove_all(state : State) -> Pin + Send>>;
}
/// Handle a DELETE request on the Resource with an id.
-pub trait ResourceDelete : ResourceMethod
+pub trait ResourceRemove : ResourceMethod
{
type ID : ResourceID + 'static;
- fn delete(state : State, id : Self::ID) -> Pin + Send>>;
+ fn remove(state : State, id : Self::ID) -> Pin + Send>>;
}
diff --git a/gotham_restful/src/result/auth_result.rs b/gotham_restful/src/result/auth_result.rs
index b2ebbe1..bed279f 100644
--- a/gotham_restful/src/result/auth_result.rs
+++ b/gotham_restful/src/result/auth_result.rs
@@ -29,12 +29,13 @@ look something like this (assuming the `auth` feature is enabled):
# use serde::Deserialize;
#
# #[derive(Resource)]
+# #[resource(read_all)]
# struct MyResource;
#
# #[derive(Clone, Deserialize)]
# struct MyAuthData { exp : u64 }
#
-#[rest_read_all(MyResource)]
+#[read_all(MyResource)]
fn read_all(auth : AuthStatus) -> AuthSuccess {
let auth_data = match auth {
AuthStatus::Authenticated(data) => data,
@@ -88,12 +89,13 @@ look something like this (assuming the `auth` feature is enabled):
# use std::io;
#
# #[derive(Resource)]
+# #[resource(read_all)]
# struct MyResource;
#
# #[derive(Clone, Deserialize)]
# struct MyAuthData { exp : u64 }
#
-#[rest_read_all(MyResource)]
+#[read_all(MyResource)]
fn read_all(auth : AuthStatus) -> AuthResult {
let auth_data = match auth {
AuthStatus::Authenticated(data) => data,
diff --git a/gotham_restful/src/result/no_content.rs b/gotham_restful/src/result/no_content.rs
index 0011a67..3377b66 100644
--- a/gotham_restful/src/result/no_content.rs
+++ b/gotham_restful/src/result/no_content.rs
@@ -22,9 +22,10 @@ the function attributes:
# use gotham_restful::*;
#
# #[derive(Resource)]
+# #[resource(read_all)]
# struct MyResource;
#
-#[rest_read_all(MyResource)]
+#[read_all(MyResource)]
fn read_all(_state: &mut State) {
// do something
}
diff --git a/gotham_restful/src/result/success.rs b/gotham_restful/src/result/success.rs
index 11b2f2b..f622f12 100644
--- a/gotham_restful/src/result/success.rs
+++ b/gotham_restful/src/result/success.rs
@@ -25,6 +25,7 @@ Usage example:
# use serde::{Deserialize, Serialize};
#
# #[derive(Resource)]
+# #[resource(read_all)]
# struct MyResource;
#
#[derive(Deserialize, Serialize)]
@@ -33,7 +34,7 @@ struct MyResponse {
message: &'static str
}
-#[rest_read_all(MyResource)]
+#[read_all(MyResource)]
fn read_all(_state: &mut State) -> Success {
let res = MyResponse { message: "I'm always happy" };
res.into()
diff --git a/gotham_restful/src/routing.rs b/gotham_restful/src/routing.rs
index 3e67e09..1714a32 100644
--- a/gotham_restful/src/routing.rs
+++ b/gotham_restful/src/routing.rs
@@ -78,19 +78,19 @@ pub trait DrawResourceRoutes
Handler::Res : 'static,
Handler::Body : 'static;
- fn update_all(&mut self)
+ fn change_all(&mut self)
where
Handler::Res : 'static,
Handler::Body : 'static;
- fn update(&mut self)
+ fn change(&mut self)
where
Handler::Res : 'static,
Handler::Body : 'static;
- fn delete_all(&mut self);
+ fn remove_all(&mut self);
- fn delete(&mut self);
+ fn remove(&mut self);
}
fn response_from(res : Response, state : &State) -> gotham::hyper::Response
@@ -217,15 +217,15 @@ where
handle_with_body::(state, |state, body| Handler::create(state, body))
}
-fn update_all_handler(state : State) -> Pin>
+fn change_all_handler(state : State) -> Pin>
where
Handler::Res : 'static,
Handler::Body : 'static
{
- handle_with_body::(state, |state, body| Handler::update_all(state, body))
+ handle_with_body::(state, |state, body| Handler::change_all(state, body))
}
-fn update_handler(state : State) -> Pin>
+fn change_handler(state : State) -> Pin>
where
Handler::Res : 'static,
Handler::Body : 'static
@@ -234,21 +234,21 @@ where
let path : &PathExtractor = PathExtractor::borrow_from(&state);
path.id.clone()
};
- handle_with_body::(state, |state, body| Handler::update(state, id, body))
+ handle_with_body::(state, |state, body| Handler::change(state, id, body))
}
-fn delete_all_handler(state : State) -> Pin>
+fn remove_all_handler(state : State) -> Pin>
{
- to_handler_future(state, |state| Handler::delete_all(state)).boxed()
+ to_handler_future(state, |state| Handler::remove_all(state)).boxed()
}
-fn delete_handler(state : State) -> Pin>
+fn remove_handler(state : State) -> Pin>
{
let id = {
let path : &PathExtractor = PathExtractor::borrow_from(&state);
path.id.clone()
};
- to_handler_future(state, |state| Handler::delete(state, id)).boxed()
+ to_handler_future(state, |state| Handler::remove(state, id)).boxed()
}
#[derive(Clone)]
@@ -386,7 +386,7 @@ macro_rules! implDrawResourceRoutes {
.to(|state| create_handler::(state));
}
- fn update_all(&mut self)
+ fn change_all(&mut self)
where
Handler::Res : Send + 'static,
Handler::Body : 'static
@@ -396,10 +396,10 @@ macro_rules! implDrawResourceRoutes {
self.0.put(&self.1)
.extend_route_matcher(accept_matcher)
.extend_route_matcher(content_matcher)
- .to(|state| update_all_handler::(state));
+ .to(|state| change_all_handler::(state));
}
- fn update(&mut self)
+ fn change(&mut self)
where
Handler::Res : Send + 'static,
Handler::Body : 'static
@@ -410,24 +410,24 @@ macro_rules! implDrawResourceRoutes {
.extend_route_matcher(accept_matcher)
.extend_route_matcher(content_matcher)
.with_path_extractor::>()
- .to(|state| update_handler::(state));
+ .to(|state| change_handler::(state));
}
- fn delete_all(&mut self)
+ fn remove_all(&mut self)
{
let matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into();
self.0.delete(&self.1)
.extend_route_matcher(matcher)
- .to(|state| delete_all_handler::(state));
+ .to(|state| remove_all_handler::(state));
}
- fn delete(&mut self)
+ fn remove(&mut self)
{
let matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into();
self.0.delete(&format!("{}/:id", self.1))
.extend_route_matcher(matcher)
.with_path_extractor::>()
- .to(|state| delete_handler::(state));
+ .to(|state| remove_handler::(state));
}
}
}
diff --git a/gotham_restful_derive/src/lib.rs b/gotham_restful_derive/src/lib.rs
index 66cd764..7645df9 100644
--- a/gotham_restful_derive/src/lib.rs
+++ b/gotham_restful_derive/src/lib.rs
@@ -72,7 +72,7 @@ pub fn derive_request_body(input : TokenStream) -> TokenStream
expand_derive(input, expand_request_body)
}
-#[proc_macro_derive(Resource, attributes(rest_resource))]
+#[proc_macro_derive(Resource, attributes(resource))]
pub fn derive_resource(input : TokenStream) -> TokenStream
{
expand_derive(input, expand_resource)
@@ -86,49 +86,49 @@ pub fn derive_resource_error(input : TokenStream) -> TokenStream
#[proc_macro_attribute]
-pub fn rest_read_all(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn read_all(attr : TokenStream, item : TokenStream) -> TokenStream
{
expand_macro(attr, item, |attr, item| expand_method(Method::ReadAll, attr, item))
}
#[proc_macro_attribute]
-pub fn rest_read(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn read(attr : TokenStream, item : TokenStream) -> TokenStream
{
expand_macro(attr, item, |attr, item| expand_method(Method::Read, attr, item))
}
#[proc_macro_attribute]
-pub fn rest_search(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn search(attr : TokenStream, item : TokenStream) -> TokenStream
{
expand_macro(attr, item, |attr, item| expand_method(Method::Search, attr, item))
}
#[proc_macro_attribute]
-pub fn rest_create(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn create(attr : TokenStream, item : TokenStream) -> TokenStream
{
expand_macro(attr, item, |attr, item| expand_method(Method::Create, attr, item))
}
#[proc_macro_attribute]
-pub fn rest_update_all(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn change_all(attr : TokenStream, item : TokenStream) -> TokenStream
{
- expand_macro(attr, item, |attr, item| expand_method(Method::UpdateAll, attr, item))
+ expand_macro(attr, item, |attr, item| expand_method(Method::ChangeAll, attr, item))
}
#[proc_macro_attribute]
-pub fn rest_update(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn change(attr : TokenStream, item : TokenStream) -> TokenStream
{
- expand_macro(attr, item, |attr, item| expand_method(Method::Update, attr, item))
+ expand_macro(attr, item, |attr, item| expand_method(Method::Change, attr, item))
}
#[proc_macro_attribute]
-pub fn rest_delete_all(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn delete_all(attr : TokenStream, item : TokenStream) -> TokenStream
{
- expand_macro(attr, item, |attr, item| expand_method(Method::DeleteAll, attr, item))
+ expand_macro(attr, item, |attr, item| expand_method(Method::RemoveAll, attr, item))
}
#[proc_macro_attribute]
-pub fn rest_delete(attr : TokenStream, item : TokenStream) -> TokenStream
+pub fn delete(attr : TokenStream, item : TokenStream) -> TokenStream
{
- expand_macro(attr, item, |attr, item| expand_method(Method::Delete, attr, item))
+ expand_macro(attr, item, |attr, item| expand_method(Method::Remove, attr, item))
}
diff --git a/gotham_restful_derive/src/method.rs b/gotham_restful_derive/src/method.rs
index d232df5..789c50d 100644
--- a/gotham_restful_derive/src/method.rs
+++ b/gotham_restful_derive/src/method.rs
@@ -26,10 +26,10 @@ pub enum Method
Read,
Search,
Create,
- UpdateAll,
- Update,
- DeleteAll,
- Delete
+ ChangeAll,
+ Change,
+ RemoveAll,
+ Remove
}
impl FromStr for Method
@@ -43,10 +43,10 @@ impl FromStr for Method
"Read" | "read" => Ok(Self::Read),
"Search" | "search" => Ok(Self::Search),
"Create" | "create" => Ok(Self::Create),
- "UpdateAll" | "update_all" => Ok(Self::UpdateAll),
- "Update" | "update" => Ok(Self::Update),
- "DeleteAll" | "delete_all" => Ok(Self::DeleteAll),
- "Delete" | "delete" => Ok(Self::Delete),
+ "ChangeAll" | "change_all" => Ok(Self::ChangeAll),
+ "Change" | "change" => Ok(Self::Change),
+ "RemoveAll" | "remove_all" => Ok(Self::RemoveAll),
+ "Remove" | "remove" => Ok(Self::Remove),
_ => Err(Error::new(Span::call_site(), format!("Unknown method: `{}'", str)))
}
}
@@ -59,14 +59,11 @@ impl Method
use Method::*;
match self {
- ReadAll => vec![],
- Read => vec!["ID"],
+ ReadAll | RemoveAll => vec![],
+ Read | Remove => vec!["ID"],
Search => vec!["Query"],
- Create => vec!["Body"],
- UpdateAll => vec!["Body"],
- Update => vec!["ID", "Body"],
- DeleteAll => vec![],
- Delete => vec!["ID"]
+ Create | ChangeAll => vec!["Body"],
+ Change => vec!["ID", "Body"]
}
}
@@ -79,10 +76,10 @@ impl Method
Read => "Read",
Search => "Search",
Create => "Create",
- UpdateAll => "UpdateAll",
- Update => "Update",
- DeleteAll => "DeleteAll",
- Delete => "Delete"
+ ChangeAll => "ChangeAll",
+ Change => "Change",
+ RemoveAll => "RemoveAll",
+ Remove => "Remove"
};
format_ident!("Resource{}", name)
}
@@ -96,10 +93,10 @@ impl Method
Read => "read",
Search => "search",
Create => "create",
- UpdateAll => "update_all",
- Update => "update",
- DeleteAll => "delete_all",
- Delete => "delete"
+ ChangeAll => "change_all",
+ Change => "change",
+ RemoveAll => "remove_all",
+ Remove => "remove"
};
format_ident!("{}", name)
}
diff --git a/gotham_restful_derive/src/resource.rs b/gotham_restful_derive/src/resource.rs
index 173a8d4..a51ecbb 100644
--- a/gotham_restful_derive/src/resource.rs
+++ b/gotham_restful_derive/src/resource.rs
@@ -32,7 +32,7 @@ pub fn expand_resource(input : DeriveInput) -> Result
let name = ident.to_string();
let methods = input.attrs.into_iter().filter(|attr|
- attr.path.segments.iter().last().map(|segment| segment.ident.to_string()) == Some("rest_resource".to_string()) // TODO wtf
+ attr.path.segments.iter().last().map(|segment| segment.ident.to_string()) == Some("resource".to_string()) // TODO wtf
).map(|attr| {
syn::parse2(attr.tokens).map(|m : MethodList| m.0.into_iter())
}).flat_map(|list| match list {