api-test: add a json-body multi-parameter test method

Signed-off-by: Wolfgang Bumiller <w.bumiller@errno.eu>
This commit is contained in:
Wolfgang Bumiller 2019-08-15 11:03:10 +02:00
parent 82f8df963e
commit 8b77b3d08c
3 changed files with 51 additions and 5 deletions

1
Cargo.lock generated
View File

@ -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)",

View File

@ -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"

View File

@ -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<Response<Body>, 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<String>,
) -> Result<String, Error> {
Ok(match ps {
Some(ps) => format!("{}, {}.\n{}", person, message, ps),
None => format!("{}, {}.", person, message),
})
}
//
// Hyper glue
//
async fn route_request(request: Request<Body>) -> Result<http::Response<Body>, 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<Body>) -> Result<http::Response<Body>, 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
}