Skip to main content

onvif_server/
wsdl_loader.rs

1use soap_server::{WsdlError, WsdlLoader};
2
3/// Serves bundled ONVIF WSDL and XSD files from bytes embedded at compile time.
4///
5/// Official ONVIF WSDLs use relative schemaLocation paths like
6/// `"../../../ver10/schema/onvif.xsd"` — the filename component is extracted
7/// via `rsplit('/')` so callers can use either the bare name or a relative path.
8pub struct EmbeddedWsdlLoader;
9
10impl WsdlLoader for EmbeddedWsdlLoader {
11    fn load(&self, location: &str) -> Result<Vec<u8>, WsdlError> {
12        // Strip any leading path — WSDLs use relative paths like "../common/onvif.xsd"
13        let filename = location.rsplit('/').next().unwrap_or(location);
14        match filename {
15            "devicemgmt.wsdl" => Ok(include_bytes!("../wsdl/devicemgmt.wsdl").to_vec()),
16            "media.wsdl" => Ok(include_bytes!("../wsdl/media.wsdl").to_vec()),
17            "ptz.wsdl" => Ok(include_bytes!("../wsdl/ptz.wsdl").to_vec()),
18            "imaging.wsdl" => Ok(include_bytes!("../wsdl/imaging.wsdl").to_vec()),
19            // ONVIF events WSDL is named "event.wsdl" at source but stored as "events.wsdl"
20            "events.wsdl" | "event.wsdl" => Ok(include_bytes!("../wsdl/events.wsdl").to_vec()),
21            "onvif.xsd" => Ok(include_bytes!("../wsdl/onvif.xsd").to_vec()),
22            "common.xsd" => Ok(include_bytes!("../wsdl/common.xsd").to_vec()),
23            // W3C and OASIS external schemas imported by onvif.xsd.
24            // Bundled as minimal stubs so ServerBuilder resolves the WSDL without network access.
25            // URL → rsplit('/') → match key:
26            //   https://www.w3.org/2005/05/xmlmime           → "xmlmime"
27            //   https://www.w3.org/2003/05/soap-envelope     → "soap-envelope"
28            //   http://docs.oasis-open.org/wsn/b-2.xsd       → "b-2.xsd"
29            //   https://www.w3.org/2004/08/xop/include       → "include"
30            "xmlmime" | "xmlmime.xsd" => Ok(include_bytes!("../wsdl/xmlmime.xsd").to_vec()),
31            "soap-envelope" | "soap-envelope.xsd" => {
32                Ok(include_bytes!("../wsdl/soap-envelope.xsd").to_vec())
33            }
34            "b-2.xsd" => Ok(include_bytes!("../wsdl/wsn-b2.xsd").to_vec()),
35            // OASIS WS-BaseNotification and WS-ResourceFramework WSDLs imported by events.wsdl
36            "bw-2.wsdl" => Ok(include_bytes!("../wsdl/wsn-bw2.wsdl").to_vec()),
37            "rw-2.wsdl" => Ok(include_bytes!("../wsdl/wsrf-rw2.wsdl").to_vec()),
38            // W3C WS-Addressing and OASIS WS-Notification topic XSDs imported by events.wsdl
39            "ws-addr.xsd" => Ok(include_bytes!("../wsdl/ws-addr.xsd").to_vec()),
40            "t-1.xsd" => Ok(include_bytes!("../wsdl/wsn-t1.xsd").to_vec()),
41            "include" | "xop-include.xsd" => Ok(include_bytes!("../wsdl/xop-include.xsd").to_vec()),
42            other => Err(WsdlError::MalformedXml(format!(
43                "Unknown WSDL/XSD: {other}"
44            ))),
45        }
46    }
47}