SOAP in Go

2,409 views
Skip to first unread message

ThePiachu

unread,
Jan 31, 2015, 1:29:00 AM1/31/15
to golan...@googlegroups.com
I am currently working on implementing a SOAP API in Go. I used the Hooklift's GoWSDL (https://github.com/hooklift/gowsdl) to compile the WSDL file (https://api.okpay.com/OkPayAPI?singleWsdl) into Go, then changed it over to GAE Go. However, I'm having problem with the code still. I call the API through:

req:=new(OKPay.GetDateTime)
api:=OKPay.NewI_OkPayAPI("https://api.okpay.com", true)
resp, err:=api.GetDateTime(c, req)
c.Debugf("resp, err - %v, %v", resp, err)

And the response I get is essentially the HTML code from https://api.okpay.com/OkPayAPI , rather than an envelope response. I suspect I might be using a wrong URL to initialize the API, but I'm not sure.

Here is the rest of the relevant code:

OKPay.go:

package OKPay

import (
"encoding/xml"
"time"
"appengine"

)


var _ time.Time
var _ xml.Name

type GetDateTime struct {
XMLName xml.Name `xml:"https://api.okpay.com Get_Date_Time"`
}

type GetDateTimeResponse struct {
XMLName xml.Name `xml:"https://api.okpay.com Get_Date_TimeResponse"`

GetDateTimeResult string `xml:"Get_Date_TimeResult,omitempty"`
}

type I_OkPayAPI struct {
client *gowsdl.SoapClient
}

func NewI_OkPayAPI(url string, tls bool) *I_OkPayAPI {
if url == "" {
url = ""
}
client := gowsdl.NewSoapClient(url, tls)

return &I_OkPayAPI{
client: client,
}
}

func (service *I_OkPayAPI) GetDateTime(c appengine.Context, request *GetDateTime) (*GetDateTimeResponse, error) {
response := &GetDateTimeResponse{}
err := service.client.Call(c, "https://api.okpay.com/I_OkPayAPI/Get_Date_Time", request, response)
if err != nil {
return nil, err
}

return response, nil
}



GAESoap.go:

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 {
XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
//Header SoapHeader `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header,omitempty"`
Body SoapBody `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`
}

type SoapHeader struct {
Header interface{}
}

type SoapBody struct {
Fault   *SoapFault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
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?

Tamás Gulácsi

unread,
Jan 31, 2015, 3:05:24 AM1/31/15
to golan...@googlegroups.com
Dump your request and the response, than use curl to test the request with different URLs. When you found a working URL, payload pair, then dive into code to have reproduce it for you.

oju...@gmail.com

unread,
Jan 31, 2015, 5:01:25 AM1/31/15
to golan...@googlegroups.com
ThePiachu, I have no answer for your question, sorry. Instead, I want to ask what is this for:

var _ time.Time
var _ xml.Name

What is this unnamed variable declarations? I don't know this feature. What is the purpose?

Piotr Piasecki

unread,
Jan 31, 2015, 5:03:20 AM1/31/15
to oju...@gmail.com, golang-nuts
Auto generated code from the converter. It makes sure that we are using the time and xml packages and won't have to remove the imports in case we remove all the references to the packages in the actual code.

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/MREBSavUEMA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages