I am currently working on implementing a SOAP API in Go. I used the Hooklift's GoWSDL (
) into Go, then changed it over to GAE Go. However, I'm having problem with the code still. I call the API through:
package GAESoap
import (
"appengine"
"appengine/urlfetch"
"bytes"
//"crypto/tls"
"encoding/xml"
"io/ioutil"
"net/http"
"time"
"net"
)
var timeout = time.Duration(30 * time.Second)
func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}
type SoapEnvelope struct {
}
type SoapHeader struct {
Header interface{}
}
type SoapBody struct {
Content string `xml:",innerxml"`
}
type SoapFault struct {
Faultcode string `xml:"faultcode,omitempty"`
Faultstring string `xml:"faultstring,omitempty"`
Faultactor string `xml:"faultactor,omitempty"`
Detail string `xml:"detail,omitempty"`
}
type SoapClient struct {
url string
tls bool
}
func (f *SoapFault) Error() string {
return f.Faultstring
}
func NewSoapClient(url string, tls bool) *SoapClient {
return &SoapClient{
url: url,
tls: tls,
}
}
func (s *SoapClient) Call(c appengine.Context, soapAction string, request, response interface{}) error {
envelope := SoapEnvelope{
//Header: SoapHeader{},
}
if request != nil {
reqXml, err := xml.Marshal(request)
if err != nil {
c.Errorf("Call - %v", err)
return err
}
envelope.Body.Content = string(reqXml)
}
buffer := &bytes.Buffer{}
encoder := xml.NewEncoder(buffer)
//encoder.Indent(" ", " ")
err := encoder.Encode(envelope)
if err == nil {
err = encoder.Flush()
}
if err != nil {
c.Errorf("Call - %v", err)
return err
}
req, err := http.NewRequest("POST", s.url, buffer)
req.Header.Add("Content-Type", "text/xml; charset=\"utf-8\"")
if soapAction != "" {
req.Header.Add("SOAPAction", soapAction)
}
req.Header.Set("User-Agent", "gowsdl/0.1")
tr := urlfetch.Transport{
/*TLSClientConfig: &tls.Config{
InsecureSkipVerify: s.tls,
},
Dial: dialTimeout,*/
Context: c,
}
client := &http.Client{Transport: &tr}
res, err := client.Do(req)
if err != nil {
c.Errorf("Call - %v", err)
return err
}
defer res.Body.Close()
c.Debugf("res - %v", res)
rawbody, err := ioutil.ReadAll(res.Body)
if len(rawbody) == 0 {
c.Warningf("empty response")
return nil
}
respEnvelope := &SoapEnvelope{}
err = xml.Unmarshal(rawbody, respEnvelope)
if err != nil {
c.Errorf("Call - %v", err)
c.Debugf("rawbody - %x", rawbody)
c.Debugf("respEnvelope - %x", respEnvelope)
return err
}
body := respEnvelope.Body.Content
fault := respEnvelope.Body.Fault
if body == "" {
c.Warningf("empty response body", "envelope", respEnvelope, "body", body)
return nil
}
c.Debugf("response", "envelope", respEnvelope, "body", body)
if fault != nil {
c.Errorf("Call - %v", fault)
return fault
}
err = xml.Unmarshal([]byte(body), response)
if err != nil {
c.Errorf("Call - %v", err)
return err
}
return nil
}
What would be the proper way to call the SOAP API? Is it the problem with the URL I use to initialize the API, or is it something else?