use bytes::Bytes;
use quick_xml::events::Event;
use quick_xml::NsReader;
use soap_server::{escape_text, FnHandler, ServerBuilder, SoapFault};
fn text_of(body: &[u8], local: &str) -> Option<String> {
let mut reader = NsReader::from_reader(body);
reader.config_mut().trim_text(true);
loop {
match reader.read_event() {
Ok(Event::Start(e)) if e.local_name().as_ref() == local.as_bytes() => {
let end = e.to_end().into_owned();
let raw = reader.read_text(end.name()).ok()?;
return quick_xml::escape::unescape(&raw)
.ok()
.map(|c| c.into_owned());
}
Ok(Event::Eof) => return None,
Err(_) => return None,
_ => {}
}
}
}
#[tokio::main]
async fn main() {
let wsdl = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/hello.wsdl");
let svc = ServerBuilder::from_wsdl_file(wsdl)
.handler(
"SayHello",
FnHandler::new(|body: Bytes| async move {
let name = text_of(&body, "Name").unwrap_or_else(|| "world".to_string());
let xml = format!(
r#"<SayHelloResponse xmlns="urn:example:hello"><Greeting>Hello, {}!</Greeting></SayHelloResponse>"#,
escape_text(&name)
);
Ok::<Bytes, SoapFault>(Bytes::from(xml))
}),
)
.path("/hello")
.build()
.expect("WSDL build failed");
let app = svc.into_router();
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080")
.await
.expect("bind failed");
println!("simple_service on http://0.0.0.0:8080/hello (GET ?wsdl for the contract)");
axum::serve(listener, app).await.expect("server error");
}