Implement actix-web FromRequest and Responder
Fixes #130 I'm not entirely sure why this works, but the compiler seems to like it! :D The example is intentionally as simple as it gets, but a "real" app should probably return Result<Event, Error> from its handlers. Signed-off-by: Jim Crossley <jim@crossleys.org>
This commit is contained in:
parent
bf21c52869
commit
d45811604d
|
@ -1,31 +1,25 @@
|
||||||
use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer};
|
use actix_web::{get, post, App, HttpServer};
|
||||||
use cloudevents::actix::{HttpRequestExt, HttpResponseBuilderExt};
|
use cloudevents::{Event, EventBuilder, EventBuilderV10};
|
||||||
use cloudevents::{EventBuilder, EventBuilderV10};
|
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
#[post("/")]
|
#[post("/")]
|
||||||
async fn post_event(req: HttpRequest, payload: web::Payload) -> Result<String, actix_web::Error> {
|
async fn post_event(event: Event) -> Event {
|
||||||
let event = req.to_event(payload).await?;
|
|
||||||
println!("Received Event: {:?}", event);
|
println!("Received Event: {:?}", event);
|
||||||
Ok(format!("{:?}", event))
|
event
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn get_event() -> Result<HttpResponse, actix_web::Error> {
|
async fn get_event() -> Event {
|
||||||
let payload = json!({"hello": "world"});
|
let payload = json!({"hello": "world"});
|
||||||
|
|
||||||
Ok(HttpResponse::Ok()
|
EventBuilderV10::new()
|
||||||
.event(
|
.id("0001")
|
||||||
EventBuilderV10::new()
|
.ty("example.test")
|
||||||
.id("0001")
|
.source("http://localhost/")
|
||||||
.ty("example.test")
|
.data("application/json", payload)
|
||||||
.source("http://localhost/")
|
.extension("someint", "10")
|
||||||
.data("application/json", payload)
|
.build()
|
||||||
.extension("someint", "10")
|
.unwrap()
|
||||||
.build()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.await?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
|
|
|
@ -9,7 +9,8 @@ use actix_web::http::HeaderName;
|
||||||
use actix_web::web::{Bytes, BytesMut};
|
use actix_web::web::{Bytes, BytesMut};
|
||||||
use actix_web::{web, HttpMessage, HttpRequest};
|
use actix_web::{web, HttpMessage, HttpRequest};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use futures::StreamExt;
|
use futures::future::LocalBoxFuture;
|
||||||
|
use futures::{FutureExt, StreamExt};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
/// Wrapper for [`HttpRequest`] that implements [`MessageDeserializer`] trait.
|
/// Wrapper for [`HttpRequest`] that implements [`MessageDeserializer`] trait.
|
||||||
|
@ -112,6 +113,19 @@ pub async fn request_to_event(
|
||||||
.map_err(actix_web::error::ErrorBadRequest)
|
.map_err(actix_web::error::ErrorBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// So that an actix-web handler may take an Event parameter
|
||||||
|
impl actix_web::FromRequest for Event {
|
||||||
|
type Config = ();
|
||||||
|
type Error = actix_web::Error;
|
||||||
|
type Future = LocalBoxFuture<'static, std::result::Result<Self, Self::Error>>;
|
||||||
|
|
||||||
|
fn from_request(r: &HttpRequest, p: &mut actix_web::dev::Payload) -> Self::Future {
|
||||||
|
let payload = web::Payload(p.take());
|
||||||
|
let request = r.to_owned();
|
||||||
|
async move { request_to_event(&request, payload).await }.boxed_local()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Extention Trait for [`HttpRequest`] which acts as a wrapper for the function [`request_to_event()`].
|
/// Extention Trait for [`HttpRequest`] which acts as a wrapper for the function [`request_to_event()`].
|
||||||
///
|
///
|
||||||
/// This trait is sealed and cannot be implemented for types outside of this crate.
|
/// This trait is sealed and cannot be implemented for types outside of this crate.
|
||||||
|
|
|
@ -5,9 +5,11 @@ use crate::message::{
|
||||||
};
|
};
|
||||||
use crate::Event;
|
use crate::Event;
|
||||||
use actix_web::dev::HttpResponseBuilder;
|
use actix_web::dev::HttpResponseBuilder;
|
||||||
use actix_web::http::{HeaderName, HeaderValue};
|
use actix_web::http::{HeaderName, HeaderValue, StatusCode};
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use futures::future::LocalBoxFuture;
|
||||||
|
use futures::FutureExt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// Wrapper for [`HttpResponseBuilder`] that implements [`StructuredSerializer`] and [`BinarySerializer`].
|
/// Wrapper for [`HttpResponseBuilder`] that implements [`StructuredSerializer`] and [`BinarySerializer`].
|
||||||
|
@ -76,6 +78,16 @@ pub async fn event_to_response(
|
||||||
.map_err(actix_web::error::ErrorBadRequest)
|
.map_err(actix_web::error::ErrorBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// So that an actix-web handler may return an Event
|
||||||
|
impl actix_web::Responder for Event {
|
||||||
|
type Error = actix_web::Error;
|
||||||
|
type Future = LocalBoxFuture<'static, std::result::Result<HttpResponse, Self::Error>>;
|
||||||
|
|
||||||
|
fn respond_to(self, _: &actix_web::HttpRequest) -> Self::Future {
|
||||||
|
async { HttpResponse::build(StatusCode::OK).event(self).await }.boxed_local()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Extension Trait for [`HttpResponseBuilder`] which acts as a wrapper for the function [`event_to_response()`].
|
/// Extension Trait for [`HttpResponseBuilder`] which acts as a wrapper for the function [`event_to_response()`].
|
||||||
///
|
///
|
||||||
/// This trait is sealed and cannot be implemented for types outside of this crate.
|
/// This trait is sealed and cannot be implemented for types outside of this crate.
|
||||||
|
|
Loading…
Reference in New Issue