mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-04-20 23:07:01 +00:00
update to gotham 0.5 and start using rustfmt
This commit is contained in:
parent
5317e50961
commit
d55b0897e9
39 changed files with 1798 additions and 2095 deletions
|
@ -1,16 +1,15 @@
|
|||
#[macro_use] extern crate gotham_derive;
|
||||
#[macro_use]
|
||||
extern crate gotham_derive;
|
||||
|
||||
use gotham::{
|
||||
router::builder::*,
|
||||
test::TestServer
|
||||
};
|
||||
use gotham::{router::builder::*, test::TestServer};
|
||||
use gotham_restful::*;
|
||||
use mime::{APPLICATION_JSON, TEXT_PLAIN};
|
||||
use serde::Deserialize;
|
||||
|
||||
mod util { include!("util/mod.rs"); }
|
||||
use util::{test_get_response, test_post_response, test_put_response, test_delete_response};
|
||||
|
||||
mod util {
|
||||
include!("util/mod.rs");
|
||||
}
|
||||
use util::{test_delete_response, test_get_response, test_post_response, test_put_response};
|
||||
|
||||
#[derive(Resource)]
|
||||
#[resource(read_all, read, search, create, change_all, change, remove_all, remove)]
|
||||
|
@ -19,88 +18,96 @@ struct FooResource;
|
|||
#[derive(Deserialize)]
|
||||
#[cfg_attr(feature = "openapi", derive(OpenapiType))]
|
||||
#[allow(dead_code)]
|
||||
struct FooBody
|
||||
{
|
||||
data : String
|
||||
struct FooBody {
|
||||
data: String
|
||||
}
|
||||
|
||||
#[derive(Deserialize, StateData, StaticResponseExtender)]
|
||||
#[cfg_attr(feature = "openapi", derive(OpenapiType))]
|
||||
#[allow(dead_code)]
|
||||
struct FooSearch
|
||||
{
|
||||
query : String
|
||||
struct FooSearch {
|
||||
query: String
|
||||
}
|
||||
|
||||
const READ_ALL_RESPONSE : &[u8] = b"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e";
|
||||
const READ_ALL_RESPONSE: &[u8] = b"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e";
|
||||
#[read_all(FooResource)]
|
||||
async fn read_all() -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn read_all() -> Raw<&'static [u8]> {
|
||||
Raw::new(READ_ALL_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const READ_RESPONSE : &[u8] = b"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9";
|
||||
const READ_RESPONSE: &[u8] = b"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9";
|
||||
#[read(FooResource)]
|
||||
async fn read(_id : u64) -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn read(_id: u64) -> Raw<&'static [u8]> {
|
||||
Raw::new(READ_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const SEARCH_RESPONSE : &[u8] = b"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E";
|
||||
const SEARCH_RESPONSE: &[u8] = b"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E";
|
||||
#[search(FooResource)]
|
||||
async fn search(_body : FooSearch) -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn search(_body: FooSearch) -> Raw<&'static [u8]> {
|
||||
Raw::new(SEARCH_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const CREATE_RESPONSE : &[u8] = b"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83";
|
||||
const CREATE_RESPONSE: &[u8] = b"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83";
|
||||
#[create(FooResource)]
|
||||
async fn create(_body : FooBody) -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn create(_body: FooBody) -> Raw<&'static [u8]> {
|
||||
Raw::new(CREATE_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const CHANGE_ALL_RESPONSE : &[u8] = b"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv";
|
||||
const CHANGE_ALL_RESPONSE: &[u8] = b"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv";
|
||||
#[change_all(FooResource)]
|
||||
async fn change_all(_body : FooBody) -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn change_all(_body: FooBody) -> Raw<&'static [u8]> {
|
||||
Raw::new(CHANGE_ALL_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const CHANGE_RESPONSE : &[u8] = b"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu";
|
||||
const CHANGE_RESPONSE: &[u8] = b"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu";
|
||||
#[change(FooResource)]
|
||||
async fn change(_id : u64, _body : FooBody) -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn change(_id: u64, _body: FooBody) -> Raw<&'static [u8]> {
|
||||
Raw::new(CHANGE_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const REMOVE_ALL_RESPONSE : &[u8] = b"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5";
|
||||
const REMOVE_ALL_RESPONSE: &[u8] = b"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5";
|
||||
#[remove_all(FooResource)]
|
||||
async fn remove_all() -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn remove_all() -> Raw<&'static [u8]> {
|
||||
Raw::new(REMOVE_ALL_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const REMOVE_RESPONSE : &[u8] = b"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq";
|
||||
const REMOVE_RESPONSE: &[u8] = b"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq";
|
||||
#[remove(FooResource)]
|
||||
async fn remove(_id : u64) -> Raw<&'static [u8]>
|
||||
{
|
||||
async fn remove(_id: u64) -> Raw<&'static [u8]> {
|
||||
Raw::new(REMOVE_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn async_methods()
|
||||
{
|
||||
fn async_methods() {
|
||||
let server = TestServer::new(build_simple_router(|router| {
|
||||
router.resource::<FooResource>("foo");
|
||||
})).unwrap();
|
||||
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
test_get_response(&server, "http://localhost/foo", READ_ALL_RESPONSE);
|
||||
test_get_response(&server, "http://localhost/foo/1", READ_RESPONSE);
|
||||
test_get_response(&server, "http://localhost/foo/search?query=hello+world", SEARCH_RESPONSE);
|
||||
test_post_response(&server, "http://localhost/foo", r#"{"data":"hello world"}"#, APPLICATION_JSON, CREATE_RESPONSE);
|
||||
test_put_response(&server, "http://localhost/foo", r#"{"data":"hello world"}"#, APPLICATION_JSON, CHANGE_ALL_RESPONSE);
|
||||
test_put_response(&server, "http://localhost/foo/1", r#"{"data":"hello world"}"#, APPLICATION_JSON, CHANGE_RESPONSE);
|
||||
test_post_response(
|
||||
&server,
|
||||
"http://localhost/foo",
|
||||
r#"{"data":"hello world"}"#,
|
||||
APPLICATION_JSON,
|
||||
CREATE_RESPONSE
|
||||
);
|
||||
test_put_response(
|
||||
&server,
|
||||
"http://localhost/foo",
|
||||
r#"{"data":"hello world"}"#,
|
||||
APPLICATION_JSON,
|
||||
CHANGE_ALL_RESPONSE
|
||||
);
|
||||
test_put_response(
|
||||
&server,
|
||||
"http://localhost/foo/1",
|
||||
r#"{"data":"hello world"}"#,
|
||||
APPLICATION_JSON,
|
||||
CHANGE_RESPONSE
|
||||
);
|
||||
test_delete_response(&server, "http://localhost/foo", REMOVE_ALL_RESPONSE);
|
||||
test_delete_response(&server, "http://localhost/foo/1", REMOVE_RESPONSE);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use gotham::{
|
|||
router::builder::*,
|
||||
test::{Server, TestRequest, TestServer}
|
||||
};
|
||||
use gotham_restful::{CorsConfig, DrawResources, Origin, Raw, Resource, change_all, read_all};
|
||||
use gotham_restful::{change_all, read_all, CorsConfig, DrawResources, Origin, Raw, Resource};
|
||||
use itertools::Itertools;
|
||||
use mime::TEXT_PLAIN;
|
||||
|
||||
|
@ -14,70 +14,108 @@ use mime::TEXT_PLAIN;
|
|||
struct FooResource;
|
||||
|
||||
#[read_all(FooResource)]
|
||||
fn read_all()
|
||||
{
|
||||
}
|
||||
fn read_all() {}
|
||||
|
||||
#[change_all(FooResource)]
|
||||
fn change_all(_body : Raw<Vec<u8>>)
|
||||
{
|
||||
}
|
||||
fn change_all(_body: Raw<Vec<u8>>) {}
|
||||
|
||||
fn test_server(cfg : CorsConfig) -> TestServer
|
||||
{
|
||||
fn test_server(cfg: CorsConfig) -> TestServer {
|
||||
let (chain, pipeline) = single_pipeline(new_pipeline().add(cfg).build());
|
||||
TestServer::new(build_router(chain, pipeline, |router| {
|
||||
router.resource::<FooResource>("/foo")
|
||||
})).unwrap()
|
||||
TestServer::new(build_router(chain, pipeline, |router| router.resource::<FooResource>("/foo"))).unwrap()
|
||||
}
|
||||
|
||||
fn test_response<TS, C>(req : TestRequest<TS, C>, origin : Option<&str>, vary : Option<&str>, credentials : bool)
|
||||
fn test_response<TS, C>(req: TestRequest<TS, C>, origin: Option<&str>, vary: Option<&str>, credentials: bool)
|
||||
where
|
||||
TS : Server + 'static,
|
||||
C : Connect + Clone + Send + Sync + 'static
|
||||
TS: Server + 'static,
|
||||
C: Connect + Clone + Send + Sync + 'static
|
||||
{
|
||||
let res = req.with_header(ORIGIN, "http://example.org".parse().unwrap()).perform().unwrap();
|
||||
let res = req
|
||||
.with_header(ORIGIN, "http://example.org".parse().unwrap())
|
||||
.perform()
|
||||
.unwrap();
|
||||
assert_eq!(res.status(), StatusCode::NO_CONTENT);
|
||||
let headers = res.headers();
|
||||
println!("{}", headers.keys().join(","));
|
||||
assert_eq!(headers.get(ACCESS_CONTROL_ALLOW_ORIGIN).and_then(|value| value.to_str().ok()).as_deref(), origin);
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.as_deref(),
|
||||
origin
|
||||
);
|
||||
assert_eq!(headers.get(VARY).and_then(|value| value.to_str().ok()).as_deref(), vary);
|
||||
assert_eq!(headers.get(ACCESS_CONTROL_ALLOW_CREDENTIALS).and_then(|value| value.to_str().ok()).map(|value| value == "true").unwrap_or(false), credentials);
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(ACCESS_CONTROL_ALLOW_CREDENTIALS)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.map(|value| value == "true")
|
||||
.unwrap_or(false),
|
||||
credentials
|
||||
);
|
||||
assert!(headers.get(ACCESS_CONTROL_MAX_AGE).is_none());
|
||||
}
|
||||
|
||||
fn test_preflight(server : &TestServer, method : &str, origin : Option<&str>, vary : &str, credentials : bool, max_age : u64)
|
||||
{
|
||||
let res = server.client().options("http://example.org/foo")
|
||||
fn test_preflight(server: &TestServer, method: &str, origin: Option<&str>, vary: &str, credentials: bool, max_age: u64) {
|
||||
let res = server
|
||||
.client()
|
||||
.options("http://example.org/foo")
|
||||
.with_header(ACCESS_CONTROL_REQUEST_METHOD, method.parse().unwrap())
|
||||
.with_header(ORIGIN, "http://example.org".parse().unwrap())
|
||||
.perform().unwrap();
|
||||
.perform()
|
||||
.unwrap();
|
||||
assert_eq!(res.status(), StatusCode::NO_CONTENT);
|
||||
let headers = res.headers();
|
||||
println!("{}", headers.keys().join(","));
|
||||
assert_eq!(headers.get(ACCESS_CONTROL_ALLOW_METHODS).and_then(|value| value.to_str().ok()).as_deref(), Some(method));
|
||||
assert_eq!(headers.get(ACCESS_CONTROL_ALLOW_ORIGIN).and_then(|value| value.to_str().ok()).as_deref(), origin);
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(ACCESS_CONTROL_ALLOW_METHODS)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.as_deref(),
|
||||
Some(method)
|
||||
);
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.as_deref(),
|
||||
origin
|
||||
);
|
||||
assert_eq!(headers.get(VARY).and_then(|value| value.to_str().ok()).as_deref(), Some(vary));
|
||||
assert_eq!(headers.get(ACCESS_CONTROL_ALLOW_CREDENTIALS).and_then(|value| value.to_str().ok()).map(|value| value == "true").unwrap_or(false), credentials);
|
||||
assert_eq!(headers.get(ACCESS_CONTROL_MAX_AGE).and_then(|value| value.to_str().ok()).and_then(|value| value.parse().ok()), Some(max_age));
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(ACCESS_CONTROL_ALLOW_CREDENTIALS)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.map(|value| value == "true")
|
||||
.unwrap_or(false),
|
||||
credentials
|
||||
);
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(ACCESS_CONTROL_MAX_AGE)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.and_then(|value| value.parse().ok()),
|
||||
Some(max_age)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn cors_origin_none()
|
||||
{
|
||||
fn cors_origin_none() {
|
||||
let cfg = Default::default();
|
||||
let server = test_server(cfg);
|
||||
|
||||
test_preflight(&server, "PUT", None, "Access-Control-Request-Method", false, 0);
|
||||
|
||||
|
||||
test_response(server.client().get("http://example.org/foo"), None, None, false);
|
||||
test_response(server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN), None, None, false);
|
||||
test_response(
|
||||
server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN),
|
||||
None,
|
||||
None,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cors_origin_star()
|
||||
{
|
||||
fn cors_origin_star() {
|
||||
let cfg = CorsConfig {
|
||||
origin: Origin::Star,
|
||||
..Default::default()
|
||||
|
@ -85,44 +123,80 @@ fn cors_origin_star()
|
|||
let server = test_server(cfg);
|
||||
|
||||
test_preflight(&server, "PUT", Some("*"), "Access-Control-Request-Method", false, 0);
|
||||
|
||||
|
||||
test_response(server.client().get("http://example.org/foo"), Some("*"), None, false);
|
||||
test_response(server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN), Some("*"), None, false);
|
||||
test_response(
|
||||
server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN),
|
||||
Some("*"),
|
||||
None,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cors_origin_single()
|
||||
{
|
||||
fn cors_origin_single() {
|
||||
let cfg = CorsConfig {
|
||||
origin: Origin::Single("https://foo.com".to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
let server = test_server(cfg);
|
||||
|
||||
test_preflight(&server, "PUT", Some("https://foo.com"), "Access-Control-Request-Method", false, 0);
|
||||
|
||||
test_response(server.client().get("http://example.org/foo"), Some("https://foo.com"), None, false);
|
||||
test_response(server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN), Some("https://foo.com"), None, false);
|
||||
test_preflight(
|
||||
&server,
|
||||
"PUT",
|
||||
Some("https://foo.com"),
|
||||
"Access-Control-Request-Method",
|
||||
false,
|
||||
0
|
||||
);
|
||||
|
||||
test_response(
|
||||
server.client().get("http://example.org/foo"),
|
||||
Some("https://foo.com"),
|
||||
None,
|
||||
false
|
||||
);
|
||||
test_response(
|
||||
server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN),
|
||||
Some("https://foo.com"),
|
||||
None,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cors_origin_copy()
|
||||
{
|
||||
fn cors_origin_copy() {
|
||||
let cfg = CorsConfig {
|
||||
origin: Origin::Copy,
|
||||
..Default::default()
|
||||
};
|
||||
let server = test_server(cfg);
|
||||
|
||||
test_preflight(&server, "PUT", Some("http://example.org"), "Access-Control-Request-Method,Origin", false, 0);
|
||||
|
||||
test_response(server.client().get("http://example.org/foo"), Some("http://example.org"), Some("Origin"), false);
|
||||
test_response(server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN), Some("http://example.org"), Some("Origin"), false);
|
||||
test_preflight(
|
||||
&server,
|
||||
"PUT",
|
||||
Some("http://example.org"),
|
||||
"Access-Control-Request-Method,Origin",
|
||||
false,
|
||||
0
|
||||
);
|
||||
|
||||
test_response(
|
||||
server.client().get("http://example.org/foo"),
|
||||
Some("http://example.org"),
|
||||
Some("Origin"),
|
||||
false
|
||||
);
|
||||
test_response(
|
||||
server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN),
|
||||
Some("http://example.org"),
|
||||
Some("Origin"),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cors_credentials()
|
||||
{
|
||||
fn cors_credentials() {
|
||||
let cfg = CorsConfig {
|
||||
origin: Origin::None,
|
||||
credentials: true,
|
||||
|
@ -131,14 +205,18 @@ fn cors_credentials()
|
|||
let server = test_server(cfg);
|
||||
|
||||
test_preflight(&server, "PUT", None, "Access-Control-Request-Method", true, 0);
|
||||
|
||||
|
||||
test_response(server.client().get("http://example.org/foo"), None, None, true);
|
||||
test_response(server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN), None, None, true);
|
||||
test_response(
|
||||
server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN),
|
||||
None,
|
||||
None,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cors_max_age()
|
||||
{
|
||||
fn cors_max_age() {
|
||||
let cfg = CorsConfig {
|
||||
origin: Origin::None,
|
||||
max_age: 31536000,
|
||||
|
@ -147,7 +225,12 @@ fn cors_max_age()
|
|||
let server = test_server(cfg);
|
||||
|
||||
test_preflight(&server, "PUT", None, "Access-Control-Request-Method", false, 31536000);
|
||||
|
||||
|
||||
test_response(server.client().get("http://example.org/foo"), None, None, false);
|
||||
test_response(server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN), None, None, false);
|
||||
test_response(
|
||||
server.client().put("http://example.org/foo", Body::empty(), TEXT_PLAIN),
|
||||
None,
|
||||
None,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
use gotham::{
|
||||
hyper::header::CONTENT_TYPE,
|
||||
router::builder::*,
|
||||
test::TestServer
|
||||
};
|
||||
use gotham::{hyper::header::CONTENT_TYPE, router::builder::*, test::TestServer};
|
||||
use gotham_restful::*;
|
||||
use mime::TEXT_PLAIN;
|
||||
|
||||
|
||||
const RESPONSE : &[u8] = b"This is the only valid response.";
|
||||
const RESPONSE: &[u8] = b"This is the only valid response.";
|
||||
|
||||
#[derive(Resource)]
|
||||
#[resource(create)]
|
||||
|
@ -21,23 +16,24 @@ struct Foo {
|
|||
}
|
||||
|
||||
#[create(FooResource)]
|
||||
fn create(body : Foo) -> Raw<Vec<u8>> {
|
||||
fn create(body: Foo) -> Raw<Vec<u8>> {
|
||||
Raw::new(body.content, body.content_type)
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn custom_request_body()
|
||||
{
|
||||
fn custom_request_body() {
|
||||
let server = TestServer::new(build_simple_router(|router| {
|
||||
router.resource::<FooResource>("foo");
|
||||
})).unwrap();
|
||||
|
||||
let res = server.client()
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
let res = server
|
||||
.client()
|
||||
.post("http://localhost/foo", RESPONSE, TEXT_PLAIN)
|
||||
.perform().unwrap();
|
||||
.perform()
|
||||
.unwrap();
|
||||
assert_eq!(res.headers().get(CONTENT_TYPE).unwrap().to_str().unwrap(), "text/plain");
|
||||
let res = res.read_body().unwrap();
|
||||
let body : &[u8] = res.as_ref();
|
||||
let body: &[u8] = res.as_ref();
|
||||
assert_eq!(body, RESPONSE);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![cfg(all(feature = "auth", feature = "chrono", feature = "openapi"))]
|
||||
|
||||
#[macro_use] extern crate gotham_derive;
|
||||
#[macro_use]
|
||||
extern crate gotham_derive;
|
||||
|
||||
use chrono::{NaiveDate, NaiveDateTime};
|
||||
use gotham::{
|
||||
|
@ -13,10 +14,11 @@ use mime::IMAGE_PNG;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod util { include!("util/mod.rs"); }
|
||||
mod util {
|
||||
include!("util/mod.rs");
|
||||
}
|
||||
use util::{test_get_response, test_openapi_response};
|
||||
|
||||
|
||||
const IMAGE_RESPONSE : &[u8] = b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUA/wA0XsCoAAAAAXRSTlN/gFy0ywAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=";
|
||||
|
||||
#[derive(Resource)]
|
||||
|
@ -28,71 +30,59 @@ struct ImageResource;
|
|||
struct Image(Vec<u8>);
|
||||
|
||||
#[read(ImageResource, operation_id = "getImage")]
|
||||
fn get_image(_id : u64) -> Raw<&'static [u8]>
|
||||
{
|
||||
fn get_image(_id: u64) -> Raw<&'static [u8]> {
|
||||
Raw::new(IMAGE_RESPONSE, "image/png;base64".parse().unwrap())
|
||||
}
|
||||
|
||||
#[change(ImageResource, operation_id = "setImage")]
|
||||
fn set_image(_id : u64, _image : Image)
|
||||
{
|
||||
}
|
||||
|
||||
fn set_image(_id: u64, _image: Image) {}
|
||||
|
||||
#[derive(Resource)]
|
||||
#[resource(read, search)]
|
||||
struct SecretResource;
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct AuthData
|
||||
{
|
||||
sub : String,
|
||||
iat : u64,
|
||||
exp : u64
|
||||
struct AuthData {
|
||||
sub: String,
|
||||
iat: u64,
|
||||
exp: u64
|
||||
}
|
||||
|
||||
type AuthStatus = gotham_restful::AuthStatus<AuthData>;
|
||||
|
||||
#[derive(OpenapiType, Serialize)]
|
||||
struct Secret
|
||||
{
|
||||
code : f32
|
||||
struct Secret {
|
||||
code: f32
|
||||
}
|
||||
|
||||
#[derive(OpenapiType, Serialize)]
|
||||
struct Secrets
|
||||
{
|
||||
secrets : Vec<Secret>
|
||||
struct Secrets {
|
||||
secrets: Vec<Secret>
|
||||
}
|
||||
|
||||
#[derive(Deserialize, OpenapiType, StateData, StaticResponseExtender)]
|
||||
struct SecretQuery
|
||||
{
|
||||
date : NaiveDate,
|
||||
hour : Option<u16>,
|
||||
minute : Option<u16>
|
||||
struct SecretQuery {
|
||||
date: NaiveDate,
|
||||
hour: Option<u16>,
|
||||
minute: Option<u16>
|
||||
}
|
||||
|
||||
#[read(SecretResource)]
|
||||
fn read_secret(auth : AuthStatus, _id : NaiveDateTime) -> AuthSuccess<Secret>
|
||||
{
|
||||
fn read_secret(auth: AuthStatus, _id: NaiveDateTime) -> AuthSuccess<Secret> {
|
||||
auth.ok()?;
|
||||
Ok(Secret { code: 4.2 })
|
||||
}
|
||||
|
||||
#[search(SecretResource)]
|
||||
fn search_secret(auth : AuthStatus, _query : SecretQuery) -> AuthSuccess<Secrets>
|
||||
{
|
||||
fn search_secret(auth: AuthStatus, _query: SecretQuery) -> AuthSuccess<Secrets> {
|
||||
auth.ok()?;
|
||||
Ok(Secrets {
|
||||
secrets: vec![Secret { code: 4.2 }, Secret { code: 3.14 }]
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn openapi_supports_scope()
|
||||
{
|
||||
fn openapi_supports_scope() {
|
||||
let info = OpenapiInfo {
|
||||
title: "This is just a test".to_owned(),
|
||||
version: "1.2.3".to_owned(),
|
||||
|
@ -110,7 +100,8 @@ fn openapi_supports_scope()
|
|||
router.get_openapi("openapi");
|
||||
router.resource::<SecretResource>("secret");
|
||||
});
|
||||
})).unwrap();
|
||||
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
test_openapi_response(&server, "http://localhost/openapi", "tests/openapi_specification.json");
|
||||
}
|
||||
|
|
|
@ -1,32 +1,27 @@
|
|||
#![cfg(feature = "openapi")]
|
||||
use gotham::{
|
||||
router::builder::*,
|
||||
test::TestServer
|
||||
};
|
||||
use gotham::{router::builder::*, test::TestServer};
|
||||
use gotham_restful::*;
|
||||
use mime::TEXT_PLAIN;
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod util { include!("util/mod.rs"); }
|
||||
mod util {
|
||||
include!("util/mod.rs");
|
||||
}
|
||||
use util::{test_get_response, test_openapi_response};
|
||||
|
||||
|
||||
const RESPONSE : &[u8] = b"This is the only valid response.";
|
||||
const RESPONSE: &[u8] = b"This is the only valid response.";
|
||||
|
||||
#[derive(Resource)]
|
||||
#[resource(read_all)]
|
||||
struct FooResource;
|
||||
|
||||
#[read_all(FooResource)]
|
||||
fn read_all() -> Raw<&'static [u8]>
|
||||
{
|
||||
fn read_all() -> Raw<&'static [u8]> {
|
||||
Raw::new(RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn openapi_supports_scope()
|
||||
{
|
||||
fn openapi_supports_scope() {
|
||||
let info = OpenapiInfo {
|
||||
title: "Test".to_owned(),
|
||||
version: "1.2.3".to_owned(),
|
||||
|
@ -44,8 +39,9 @@ fn openapi_supports_scope()
|
|||
});
|
||||
router.resource::<FooResource>("foo4");
|
||||
});
|
||||
})).unwrap();
|
||||
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
test_get_response(&server, "http://localhost/foo1", RESPONSE);
|
||||
test_get_response(&server, "http://localhost/bar/foo2", RESPONSE);
|
||||
test_get_response(&server, "http://localhost/bar/baz/foo3", RESPONSE);
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
#[macro_use] extern crate gotham_derive;
|
||||
#[macro_use]
|
||||
extern crate gotham_derive;
|
||||
|
||||
use gotham::{
|
||||
router::builder::*,
|
||||
test::TestServer
|
||||
};
|
||||
use gotham::{router::builder::*, test::TestServer};
|
||||
use gotham_restful::*;
|
||||
use mime::{APPLICATION_JSON, TEXT_PLAIN};
|
||||
use serde::Deserialize;
|
||||
|
||||
mod util { include!("util/mod.rs"); }
|
||||
use util::{test_get_response, test_post_response, test_put_response, test_delete_response};
|
||||
|
||||
mod util {
|
||||
include!("util/mod.rs");
|
||||
}
|
||||
use util::{test_delete_response, test_get_response, test_post_response, test_put_response};
|
||||
|
||||
#[derive(Resource)]
|
||||
#[resource(read_all, read, search, create, change_all, change, remove_all, remove)]
|
||||
|
@ -19,88 +18,96 @@ struct FooResource;
|
|||
#[derive(Deserialize)]
|
||||
#[cfg_attr(feature = "openapi", derive(OpenapiType))]
|
||||
#[allow(dead_code)]
|
||||
struct FooBody
|
||||
{
|
||||
data : String
|
||||
struct FooBody {
|
||||
data: String
|
||||
}
|
||||
|
||||
#[derive(Deserialize, StateData, StaticResponseExtender)]
|
||||
#[cfg_attr(feature = "openapi", derive(OpenapiType))]
|
||||
#[allow(dead_code)]
|
||||
struct FooSearch
|
||||
{
|
||||
query : String
|
||||
struct FooSearch {
|
||||
query: String
|
||||
}
|
||||
|
||||
const READ_ALL_RESPONSE : &[u8] = b"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e";
|
||||
const READ_ALL_RESPONSE: &[u8] = b"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e";
|
||||
#[read_all(FooResource)]
|
||||
fn read_all() -> Raw<&'static [u8]>
|
||||
{
|
||||
fn read_all() -> Raw<&'static [u8]> {
|
||||
Raw::new(READ_ALL_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const READ_RESPONSE : &[u8] = b"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9";
|
||||
const READ_RESPONSE: &[u8] = b"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9";
|
||||
#[read(FooResource)]
|
||||
fn read(_id : u64) -> Raw<&'static [u8]>
|
||||
{
|
||||
fn read(_id: u64) -> Raw<&'static [u8]> {
|
||||
Raw::new(READ_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const SEARCH_RESPONSE : &[u8] = b"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E";
|
||||
const SEARCH_RESPONSE: &[u8] = b"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E";
|
||||
#[search(FooResource)]
|
||||
fn search(_body : FooSearch) -> Raw<&'static [u8]>
|
||||
{
|
||||
fn search(_body: FooSearch) -> Raw<&'static [u8]> {
|
||||
Raw::new(SEARCH_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const CREATE_RESPONSE : &[u8] = b"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83";
|
||||
const CREATE_RESPONSE: &[u8] = b"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83";
|
||||
#[create(FooResource)]
|
||||
fn create(_body : FooBody) -> Raw<&'static [u8]>
|
||||
{
|
||||
fn create(_body: FooBody) -> Raw<&'static [u8]> {
|
||||
Raw::new(CREATE_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const CHANGE_ALL_RESPONSE : &[u8] = b"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv";
|
||||
const CHANGE_ALL_RESPONSE: &[u8] = b"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv";
|
||||
#[change_all(FooResource)]
|
||||
fn change_all(_body : FooBody) -> Raw<&'static [u8]>
|
||||
{
|
||||
fn change_all(_body: FooBody) -> Raw<&'static [u8]> {
|
||||
Raw::new(CHANGE_ALL_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const CHANGE_RESPONSE : &[u8] = b"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu";
|
||||
const CHANGE_RESPONSE: &[u8] = b"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu";
|
||||
#[change(FooResource)]
|
||||
fn change(_id : u64, _body : FooBody) -> Raw<&'static [u8]>
|
||||
{
|
||||
fn change(_id: u64, _body: FooBody) -> Raw<&'static [u8]> {
|
||||
Raw::new(CHANGE_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const REMOVE_ALL_RESPONSE : &[u8] = b"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5";
|
||||
const REMOVE_ALL_RESPONSE: &[u8] = b"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5";
|
||||
#[remove_all(FooResource)]
|
||||
fn remove_all() -> Raw<&'static [u8]>
|
||||
{
|
||||
fn remove_all() -> Raw<&'static [u8]> {
|
||||
Raw::new(REMOVE_ALL_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
const REMOVE_RESPONSE : &[u8] = b"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq";
|
||||
const REMOVE_RESPONSE: &[u8] = b"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq";
|
||||
#[remove(FooResource)]
|
||||
fn remove(_id : u64) -> Raw<&'static [u8]>
|
||||
{
|
||||
fn remove(_id: u64) -> Raw<&'static [u8]> {
|
||||
Raw::new(REMOVE_RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_methods()
|
||||
{
|
||||
fn sync_methods() {
|
||||
let server = TestServer::new(build_simple_router(|router| {
|
||||
router.resource::<FooResource>("foo");
|
||||
})).unwrap();
|
||||
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
test_get_response(&server, "http://localhost/foo", READ_ALL_RESPONSE);
|
||||
test_get_response(&server, "http://localhost/foo/1", READ_RESPONSE);
|
||||
test_get_response(&server, "http://localhost/foo/search?query=hello+world", SEARCH_RESPONSE);
|
||||
test_post_response(&server, "http://localhost/foo", r#"{"data":"hello world"}"#, APPLICATION_JSON, CREATE_RESPONSE);
|
||||
test_put_response(&server, "http://localhost/foo", r#"{"data":"hello world"}"#, APPLICATION_JSON, CHANGE_ALL_RESPONSE);
|
||||
test_put_response(&server, "http://localhost/foo/1", r#"{"data":"hello world"}"#, APPLICATION_JSON, CHANGE_RESPONSE);
|
||||
test_post_response(
|
||||
&server,
|
||||
"http://localhost/foo",
|
||||
r#"{"data":"hello world"}"#,
|
||||
APPLICATION_JSON,
|
||||
CREATE_RESPONSE
|
||||
);
|
||||
test_put_response(
|
||||
&server,
|
||||
"http://localhost/foo",
|
||||
r#"{"data":"hello world"}"#,
|
||||
APPLICATION_JSON,
|
||||
CHANGE_ALL_RESPONSE
|
||||
);
|
||||
test_put_response(
|
||||
&server,
|
||||
"http://localhost/foo/1",
|
||||
r#"{"data":"hello world"}"#,
|
||||
APPLICATION_JSON,
|
||||
CHANGE_RESPONSE
|
||||
);
|
||||
test_delete_response(&server, "http://localhost/foo", REMOVE_ALL_RESPONSE);
|
||||
test_delete_response(&server, "http://localhost/foo/1", REMOVE_RESPONSE);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,9 @@ use trybuild::TestCases;
|
|||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn trybuild_ui()
|
||||
{
|
||||
fn trybuild_ui() {
|
||||
let t = TestCases::new();
|
||||
|
||||
|
||||
// always enabled
|
||||
t.compile_fail("tests/ui/from_body_enum.rs");
|
||||
t.compile_fail("tests/ui/method_async_state.rs");
|
||||
|
@ -16,10 +15,9 @@ fn trybuild_ui()
|
|||
t.compile_fail("tests/ui/method_too_many_args.rs");
|
||||
t.compile_fail("tests/ui/method_unsafe.rs");
|
||||
t.compile_fail("tests/ui/resource_unknown_method.rs");
|
||||
|
||||
|
||||
// require the openapi feature
|
||||
if cfg!(feature = "openapi")
|
||||
{
|
||||
if cfg!(feature = "openapi") {
|
||||
t.compile_fail("tests/ui/openapi_type_enum_with_fields.rs");
|
||||
t.compile_fail("tests/ui/openapi_type_nullable_non_bool.rs");
|
||||
t.compile_fail("tests/ui/openapi_type_rename_non_string.rs");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue