Files
onvif/gosoap/envelope.go
Cedric Verstraeten 8902e4e789 upgrade onvif library
2023-12-18 20:16:21 +01:00

122 lines
2.6 KiB
Go

package gosoap
import (
"encoding/xml"
"fmt"
)
type SOAPEnvelope struct {
XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Envelope"`
Header SOAPHeader
Body SOAPBody
}
type SOAPHeader struct {
XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Header"`
Headers []interface{}
}
type SOAPBody struct {
XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Body"`
Fault *SOAPFault `xml:",omitempty"`
Content interface{} `xml:",omitempty"`
}
type SOAPFault struct {
XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Fault"`
Code SOAPFaultCode `xml:",omitempty"`
Reason SOAPFaultReason `xml:",omitempty"`
Detail SOAPFaultDetail `xml:",omitempty"`
}
// UnmarshalXML the response body
// https://github.com/faceterteam/onvif4go/blob/master/soap/types.go#L46
// https://play.golang.org/p/FRzdAFrXZ1
func (b *SOAPBody) UnmarshalXML(d *xml.Decoder, _ xml.StartElement) error {
if b.Content == nil {
return xml.UnmarshalError("Content must be a pointer to a struct")
}
var (
token xml.Token
err error
consumed bool
)
Loop:
for {
if token, err = d.Token(); err != nil {
return err
}
if token == nil {
break
}
switch se := token.(type) {
case xml.StartElement:
if consumed {
return xml.UnmarshalError("Found multiple elements inside SOAP body; not wrapped-document/literal WS-I compliant")
} else if se.Name.Space == "http://www.w3.org/2003/05/soap-envelope" && se.Name.Local == "Fault" {
b.Fault = &SOAPFault{}
b.Content = nil
err = d.DecodeElement(b.Fault, &se)
if err != nil {
return err
}
consumed = true
} else {
if err = d.DecodeElement(b.Content, &se); err != nil {
return err
}
consumed = true
}
case xml.EndElement:
break Loop
}
}
return nil
}
type SOAPFaultCode struct {
Value string `xml:"Value"`
Subcode SOAPFaultSubCode `xml:"Subcode,omitempty"`
}
type SOAPFaultSubCode struct {
Value string `xml:"Value"`
Subcode *SOAPFaultSubCode `xml:"Subcode,omitempty"`
}
type SOAPFaultReason struct {
Text string `xml:"Text"`
}
type SOAPFaultDetail struct {
Text string `xml:"Text"`
}
func (fault *SOAPFault) String() string {
msg := fmt.Sprintf("fault reason: %s, fault detail: %s, fault code: %v %v ",
fault.Reason.Text, fault.Detail.Text, fault.Code.Value, fault.Code.Subcode.Value)
if fault.Code.Subcode.Subcode != nil {
msg += fault.Code.Subcode.Subcode.Value
}
return msg
}
func NewSOAPEnvelope(content interface{}) *SOAPEnvelope {
return &SOAPEnvelope{
Body: SOAPBody{
Content: content,
},
}
}