use std::future::{Future, ready};
use axum::Router;
use axum::http::header::CONTENT_TYPE;
use axum::response::{Html, IntoResponse};
use axum::routing::get;
use ruststream::asyncapi::{ViewerOptions, build_spec, render_viewer_html};
use ruststream::memory::prelude::*;
use ruststream::schemars::JsonSchema;
use ruststream::{Contact, License, SecurityScheme, ServerSpec, Tag};
use serde::Deserialize;
#[derive(Debug, Deserialize, JsonSchema)]
struct Order {
id: u64,
item: String,
}
struct Receive;
impl Handle<Order> for Receive {
fn handle(
&self,
order: &Order,
_outs: &(),
_ctx: &mut Context<'_>,
) -> impl Future<Output = Result<(), HandlerOutcome>> {
println!("order {} ({})", order.id, order.item);
ready(Ok(()))
}
}
fn service() -> RustStream {
let info = AppInfo::new("orders", "0.1.0")
.description("Everything the order domain publishes")
.contact(
Contact::new()
.name("Payments team")
.email("payments@example.com"),
)
.license(License::new("Apache-2.0"))
.tag(Tag::new("payments"));
RustStream::new(info)
.server(
"kafka",
ServerSpec::new("kafka.example.com:9093", "kafka")
.protocol_version("3.9")
.security(SecurityScheme::scram_sha512().description("SASL over TLS")),
)
.with_broker_labeled("in-process", MemoryBroker::new(), |b| {
b.include(subscriber("orders", Receive).build());
})
}
fn document() -> Result<(String, String), serde_json::Error> {
let spec = build_spec(&service()).to_json()?;
let viewer = render_viewer_html("/asyncapi.json", &ViewerOptions::default());
Ok((spec, viewer))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (spec, viewer) = document()?;
let router = Router::new()
.route(
"/",
get(move || {
let viewer = viewer.clone();
async move { Html(viewer) }
}),
)
.route(
"/asyncapi.json",
get(move || {
let spec = spec.clone();
async move { ([(CONTENT_TYPE, "application/json")], spec).into_response() }
}),
);
let listener = tokio::net::TcpListener::bind("127.0.0.1:8080").await?;
println!("AsyncAPI viewer on http://127.0.0.1:8080/");
axum::serve(listener, router).await?;
Ok(())
}