diff --git a/Cargo.lock b/Cargo.lock index f90ce13e..23f819b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "endian_trait 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.13.0-a.0 (git+https://github.com/hyperium/hyper)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/api-test/Cargo.toml b/api-test/Cargo.toml index 67a5e4fa..c1360d4b 100644 --- a/api-test/Cargo.toml +++ b/api-test/Cargo.toml @@ -11,6 +11,7 @@ authors = [ bytes = "0.4" endian_trait = { version = "0.6", features = [ "arrays" ] } failure = "0.1" +futures-preview = "0.3.0-alpha" http = "0.1" hyper = { version = "0.13.0-a.0", git = "https://github.com/hyperium/hyper" } lazy_static = "1.3" diff --git a/api-test/src/bin/api-test.rs b/api-test/src/bin/api-test.rs index 8d3a6119..2caf27d8 100644 --- a/api-test/src/bin/api-test.rs +++ b/api-test/src/bin/api-test.rs @@ -45,7 +45,7 @@ router! { GET: hello, /www/{path}*: { GET: get_www }, /api/1: { - // fill with more stuff + /greet: { GET: greet_person_with }, } }; } @@ -103,19 +103,39 @@ async fn get_www(path: String) -> Result, Error> { Ok(response.body(Body::from(data))?) } +#[api({ + description: "Create a greeting message with various parameters...", + parameters: { + person: "The person to greet", + message: "The message to give", + ps: "An optional PS message", + }, +})] +async fn greet_person_with( + person: String, + message: String, + ps: Option, +) -> Result { + Ok(match ps { + Some(ps) => format!("{}, {}.\n{}", person, message, ps), + None => format!("{}, {}.", person, message), + }) +} + // // Hyper glue // async fn route_request(request: Request) -> Result, Error> { - let path = request.uri().path(); + let (parts, body) = request.into_parts(); + let path = parts.uri.path(); - let (target, params) = ROUTER + let (target, mut params) = ROUTER .lookup(path) .ok_or_else(|| format_err!("missing path: {}", path))?; use hyper::Method; - let method = match *request.method() { + let method = match parts.method { Method::GET => target.get.as_ref(), Method::PUT => target.put.as_ref(), Method::POST => target.post.as_ref(), @@ -123,9 +143,33 @@ async fn route_request(request: Request) -> Result, E _ => bail!("unexpected method type"), }; + if let Some(ty) = parts.headers.get(http::header::CONTENT_TYPE) { + if ty.to_str()? == "application/json" { + use futures::stream::TryStreamExt; + let json = serde_json::from_str(std::str::from_utf8( + body + .try_concat() + .await? + .as_ref() + )?)?; + match json { + Value::Object(map) => for (k, v) in map { + let existed = params + .get_or_insert_with(serde_json::Map::new) + .insert(k, v) + .is_some(); + if existed { + bail!("tried to override path-based parameter!"); + } + } + _ => bail!("expected a json object"), + } + } + } + method .ok_or_else(|| format_err!("no GET method for: {}", path))? - .call(params.unwrap_or(Value::Null)) + .call(params.map(Value::Object).unwrap_or(Value::Null)) .await }