commit 7b2720a8393fb82d03a132537acbf93e7fea96bf Author: Jan Halfar Date: Wed Jan 20 16:49:34 2016 +0100 added a server draft diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df7ea1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.* +!.git* diff --git a/README.md b/README.md new file mode 100644 index 0000000..e98a316 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# SOAP is dead - long live SOAP + +First of all do not write SOAP services if you can avoid it! It is over. + +If you can not avoid it this package might help. + +```go +package main + +import "github.com/foomo/soap" + +type FooRequest struct { + Foo string +} + +type FooResponse struct { + Bar string +} + +func RunServer() { + soapServer := soap.NewServer("127.0.0.1:8080") + + soapServer.HandleOperation( + "operationFoo", + func() interface{} { + return &FooRequest{} + }, + func(request interface{}) (response interface{}, err error) { + fooRequest := request.(FooRequest) + fooResponse := &FooResponse{ + Bar: "Hello " + fooRequest.Foo, + } + response = fooResponse + return + }, + ) + +} + +func main() { + RunServer() +} + +``` diff --git a/server.go b/server.go new file mode 100644 index 0000000..75ccb81 --- /dev/null +++ b/server.go @@ -0,0 +1,13 @@ +package soap + +type Server struct { +} + +func NewServer(addr string) *Server { + s := &Server{} + return s +} + +func (s *Server) HandleOperation(operationName string, requestFactory func() interface{}, operationHandler func(request interface{}) (response interface{}, err error)) { + +} diff --git a/soap.go b/soap.go new file mode 100644 index 0000000..4dab6f7 --- /dev/null +++ b/soap.go @@ -0,0 +1,85 @@ +package soap + +import "encoding/xml" + +type SOAPEnvelope struct { + XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` + + Body SOAPBody +} + +type SOAPHeader struct { + XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header"` + + Header interface{} +} + +type SOAPBody struct { + XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"` + + Fault *SOAPFault `xml:",omitempty"` + Content interface{} `xml:",omitempty"` +} + +type SOAPFault struct { + XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault"` + + Code string `xml:"faultcode,omitempty"` + String string `xml:"faultstring,omitempty"` + Actor string `xml:"faultactor,omitempty"` + Detail string `xml:"detail,omitempty"` +} + +func (b *SOAPBody) UnmarshalXML(d *xml.Decoder, start 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://schemas.xmlsoap.org/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 +} + +func (f *SOAPFault) Error() string { + return f.String +} diff --git a/test/test.go b/test/test.go new file mode 100644 index 0000000..27b076c --- /dev/null +++ b/test/test.go @@ -0,0 +1,35 @@ +package main + +import "github.com/foomo/soap" + +type FooRequest struct { + Foo string +} + +type FooResponse struct { + Bar string +} + +func RunServer() { + soapServer := soap.NewServer("127.0.0.1:8080") + + soapServer.HandleOperation( + "operationFoo", + func() interface{} { + return &FooRequest{} + }, + func(request interface{}) (response interface{}, err error) { + fooRequest := request.(FooRequest) + fooResponse := &FooResponse{ + Bar: "Hello " + fooRequest.Foo, + } + response = fooResponse + return + }, + ) + +} + +func main() { + RunServer() +}