Skip to main content

soap_server/
lib.rs

1//! # soap-server
2//!
3//! A WSDL-driven SOAP 1.1/1.2 server library for Rust, built on top of
4//! [axum](https://docs.rs/axum). Provide a WSDL file, register async handler
5//! closures for each operation, and get a fully spec-compliant SOAP endpoint.
6//!
7//! ## Features
8//!
9//! - **SOAP 1.1 and 1.2** — auto-detects version from `Content-Type` and envelope
10//!   namespace; responds in the same version as the request.
11//! - **WSDL-driven dispatch** — operations are discovered from the WSDL at build time.
12//!   Registering a handler for an unknown operation is a build-time error.
13//! - **WS-Security (UsernameToken)** — supports PasswordDigest and PasswordText
14//!   authentication with nonce replay detection and timestamp freshness checks.
15//! - **XSD structural validation** — required elements are validated against the
16//!   WSDL/XSD schema before the handler is called.
17//!
18//! ## Quick start
19//!
20//! ```rust,no_run
21//! use soap_server::{FnHandler, ServerBuilder, SoapFault};
22//! use bytes::Bytes;
23//!
24//! #[tokio::main]
25//! async fn main() {
26//!     let svc = ServerBuilder::from_wsdl_file("path/to/service.wsdl")
27//!         .handler(
28//!             "MyOperation",
29//!             FnHandler::new(|_body: Bytes| async move {
30//!                 // Parse body, call business logic, return response XML bytes.
31//!                 Ok::<Bytes, SoapFault>(Bytes::from(
32//!                     r#"<MyOperationResponse xmlns="urn:example"/>"#,
33//!                 ))
34//!             }),
35//!         )
36//!         .build()
37//!         .expect("WSDL build failed");
38//!
39//!     let router = svc.into_router();
40//!     let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
41//!     axum::serve(listener, router).await.unwrap();
42//! }
43//! ```
44//!
45//! ## WS-Security
46//!
47//! Call `.auth(|username| { /* return password or None */ })` on the builder.
48//! Operations that require authentication return a `Sender` fault if the
49//! `<wsse:Security>` header is missing or invalid. Use `.auth_bypass([...])` to
50//! exempt specific operations (e.g. clock-sync operations).
51//!
52//! ## Multi-WSDL / multi-service
53//!
54//! Call `SoapService::into_router()` on each service and merge the resulting
55//! `axum::Router` instances — each service mounts at its own path derived from
56//! the WSDL `<service><port address>` element.
57
58pub mod dispatch;
59pub(crate) mod envelope;
60pub(crate) mod qname;
61pub(crate) mod server;
62pub(crate) mod wsdl;
63pub(crate) mod wssec;
64pub(crate) mod xsd;
65
66pub mod fault;
67pub mod handler;
68pub mod xml_escape;
69
70pub use crate::dispatch::{build_dispatch_table, DispatchTable};
71pub use crate::fault::{FaultCode, SoapFault};
72pub use crate::handler::{FnHandler, SoapHandler};
73pub use crate::server::{BuildError, FileWsdlLoader, ServerBuilder, SoapService};
74pub use crate::wsdl::parser::WsdlError;
75pub use crate::wsdl::resolver::WsdlLoader;
76pub use crate::wssec::nonce_cache::RotatingNonceCache;
77pub use crate::wssec::username_token::compute_digest;
78pub use crate::wssec::username_token::validate_username_token;
79pub use crate::xml_escape::{escape_attr, escape_text};