mirror of https://github.com/knative/func.git
Define handler in terms of CloudEvents rather than http/payload (#412)
This should simplify the unit tests. Only the invalid_event test uses the actix-web test helpers, just as an example to show it's the HTTP plumbing that will fail the request when it tries to construct an Event from invalid (or missing) headers.
This commit is contained in:
parent
795cd7251e
commit
c2c1b999e0
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "actix-codec"
|
||||
version = "0.3.0"
|
||||
|
@ -448,15 +450,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cloudevents-sdk"
|
||||
version = "0.3.1"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7c9f6054fbd2d641a2d275e44f922a3816a6cf51751fb0f72fcf26e27209dfd"
|
||||
checksum = "1f86076fd3d8c3c3449f29cc8f41d5831504870620077307c1dcbae9f7861fa0"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"async-trait",
|
||||
"base64 0.12.3",
|
||||
"bitflags",
|
||||
"bytes 1.0.1",
|
||||
"chrono",
|
||||
"delegate-attr",
|
||||
"futures",
|
||||
"hostname",
|
||||
"lazy_static",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"snafu",
|
||||
|
@ -465,20 +472,6 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudevents-sdk-actix-web"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cbeee2dc837554a8e57b20025ba175241bae2cfe27b078bedf27c9da668d35a"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"async-trait",
|
||||
"bytes 0.5.6",
|
||||
"cloudevents-sdk",
|
||||
"futures",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.8"
|
||||
|
@ -661,7 +654,6 @@ dependencies = [
|
|||
"actix-rt",
|
||||
"actix-web",
|
||||
"cloudevents-sdk",
|
||||
"cloudevents-sdk-actix-web",
|
||||
"env_logger",
|
||||
"log",
|
||||
"serde_json",
|
||||
|
|
|
@ -5,8 +5,7 @@ version = "0.1.0"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cloudevents-sdk = "0.3.0"
|
||||
cloudevents-sdk-actix-web = "0.3.0"
|
||||
cloudevents-sdk = { version = "0.4", features = ["actix"] }
|
||||
actix-web = "3"
|
||||
actix-rt = "1"
|
||||
serde_json = "1"
|
||||
|
|
|
@ -1,74 +1,58 @@
|
|||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use cloudevents::{event::Data, EventBuilder, EventBuilderV10};
|
||||
use cloudevents_sdk_actix_web::{HttpRequestExt, HttpResponseBuilderExt};
|
||||
use cloudevents::{event::Data, Event, EventBuilder, EventBuilderV10};
|
||||
use log::info;
|
||||
use serde_json::json;
|
||||
use serde_json::{from_slice, from_str, json};
|
||||
|
||||
// Implement your function's logic here
|
||||
pub async fn handle(req: HttpRequest, pl: web::Payload) -> Result<HttpResponse, actix_web::Error> {
|
||||
let event = req.to_event(pl).await?;
|
||||
info!("request: {}", event);
|
||||
pub async fn handle(event: Event) -> Result<Event, actix_web::Error> {
|
||||
info!("event: {}", event);
|
||||
|
||||
let input = if let Some(Data::Binary(data)) = event.data() {
|
||||
serde_json::from_slice(data).unwrap()
|
||||
} else {
|
||||
json!({ "name": "world" })
|
||||
let input = match event.data() {
|
||||
Some(Data::Binary(v)) => from_slice(v)?,
|
||||
Some(Data::String(v)) => from_str(v)?,
|
||||
Some(Data::Json(v)) => v.to_owned(),
|
||||
None => json!({ "name": "world" }),
|
||||
};
|
||||
|
||||
let response = EventBuilderV10::from(event)
|
||||
EventBuilderV10::from(event)
|
||||
.source("func://handler")
|
||||
.ty("func.example")
|
||||
.data("application/json", json!({ "hello": input["name"] }))
|
||||
.build()
|
||||
.map_err(actix_web::error::ErrorInternalServerError)?;
|
||||
|
||||
info!("response: {}", response);
|
||||
HttpResponse::Ok().event(response).await
|
||||
.map_err(actix_web::error::ErrorInternalServerError)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use actix_web::{body::Body, test};
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn valid_input() {
|
||||
let input = json!({"name": "bootsy"});
|
||||
let (req, payload) = test::TestRequest::post()
|
||||
.header("ce-specversion", "1.0")
|
||||
.header("ce-id", "1")
|
||||
.header("ce-type", "test")
|
||||
.header("ce-source", "http://localhost")
|
||||
.set_json(&input)
|
||||
.to_http_parts();
|
||||
let resp = handle(req, web::Payload(payload)).await.unwrap();
|
||||
assert!(resp.status().is_success());
|
||||
assert_eq!(
|
||||
&Body::from(json!({"hello":"bootsy"})),
|
||||
resp.body().as_ref().unwrap()
|
||||
);
|
||||
let mut input = Event::default();
|
||||
input.set_data("application/json", json!({"name": "bootsy"}));
|
||||
let resp = handle(input).await;
|
||||
assert!(resp.is_ok());
|
||||
match resp.unwrap().data() {
|
||||
Some(Data::Json(output)) => assert_eq!("bootsy", output["hello"]),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn no_input() {
|
||||
let (req, payload) = test::TestRequest::post()
|
||||
.header("ce-specversion", "1.0")
|
||||
.header("ce-id", "1")
|
||||
.header("ce-type", "test")
|
||||
.header("ce-source", "http://localhost")
|
||||
.to_http_parts();
|
||||
let resp = handle(req, web::Payload(payload)).await.unwrap();
|
||||
assert!(resp.status().is_success());
|
||||
assert_eq!(
|
||||
&Body::from(json!({"hello":"world"})),
|
||||
resp.body().as_ref().unwrap()
|
||||
);
|
||||
let resp = handle(Event::default()).await;
|
||||
assert!(resp.is_ok());
|
||||
match resp.unwrap().data() {
|
||||
Some(Data::Json(output)) => assert_eq!("world", output["hello"]),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn invalid_event() {
|
||||
let (req, payload) = test::TestRequest::post().to_http_parts();
|
||||
let resp = handle(req, web::Payload(payload)).await;
|
||||
assert!(resp.is_err());
|
||||
use actix_web::{test, web, App};
|
||||
let mut app = test::init_service(App::new().route("/", web::post().to(handle))).await;
|
||||
let req = test::TestRequest::post().uri("/").to_request();
|
||||
let resp = test::call_service(&mut app, req).await;
|
||||
assert!(resp.status().is_client_error());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue