Mi sono guardato intorno e tutto quello che ho trovato è il supporto per xml.Supporto WSDL/SOAP su Go?
Esistono pacchetti per supportare SOAP/WSDL su Go?
Mi sono guardato intorno e tutto quello che ho trovato è il supporto per xml.Supporto WSDL/SOAP su Go?
Esistono pacchetti per supportare SOAP/WSDL su Go?
No.
SOAP succhia, ma ho dovuto implementare un server di un protocollo già definito che utilizza SOAP, quindi ascoltato con net/http
e decodificato/buste codificati con encoding/xml
. In pochi minuti ho già servito la mia prima busta con Go.
Certo, ma esiste un'infinità di sistemi aziendali che supportano solo SOAP. Per quei casi, abbiamo ancora bisogno di qualcosa di utile. – fiorix
Non c'è supporto per WSDL in Go. Il supporto in altre lingue è statico o dinamico: entrambe le strutture sono pre-generate dal WSDL, oppure vengono eseguite al volo con tabelle hash.
È tuttavia possibile codificare e decodificare le richieste SOAP manualmente. Ho trovato che il pacchetto standard encoding/xml
non è sufficiente per SOAP. Ci sono così tante stranezze in diversi server, e le limitazioni in encoding/xml
rendono difficile generare una richiesta con cui questi server sono soddisfatti.
Ad esempio, alcuni server richiedono xsi:type="xsd:string"
su ogni tag stringa. Per farlo correttamente la vostra struct ha bisogno di guardare come questo per encoding/xml
:
type MethodCall struct {
One XSI
Two XSI
}
type XSI struct {
Type string `xml:"xsi:type,attr"`
Vaue string `xml:",chardata"`
}
E si costruisce in questo modo:
MethodCall{
XSI{"xsd:string", "One"},
XSI{"xsd:string", "Two"},
}
che ti dà:
<MethodCall>
<One xsi:type="xsd:string">One</One>
<Two xsi:type="xsd:string">Two</Two>
</MethodCall>
Ora questo potrebbe essere ok Sicuramente ottiene il lavoro svolto. Ma se avessi bisogno di più di un semplice string
? encoding/xml
attualmente non supporta interface{}
.
Come potete vedere, questo si complica. Se avevi una API SOAP da integrare, probabilmente non sarebbe male. E se ne avessi diversi, ognuno con le proprie stranezze?
Non sarebbe bello se potessi fare questo?
type MethodCall struct {
One string
Two string
}
Poi dico encoding/xml
: "Questo server vuole tipi XSI".
Per risolvere questo problema ho creato github.com/webconnex/xmlutil. E 'un lavoro in corso. Non ha tutte le funzionalità dell'encoder/decoder di encoding/xml
, ma ha ciò che è necessario per SOAP.
Ecco un esempio di lavoro:
package main
import (
"bytes"
"encoding/xml"
"fmt"
"github.com/webconnex/xmlutil"
"log"
//"net/http"
)
type Envelope struct {
Body `xml:"soap:"`
}
type Body struct {
Msg interface{}
}
type MethodCall struct {
One string
Two string
}
type MethodCallResponse struct {
Three string
}
func main() {
x := xmlutil.NewXmlUtil()
x.RegisterNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi")
x.RegisterNamespace("http://www.w3.org/2001/XMLSchema", "xsd")
x.RegisterNamespace("http://www.w3.org/2003/05/soap-envelope", "soap")
x.RegisterTypeMore(Envelope{}, xml.Name{"http://www.w3.org/2003/05/soap-envelope", ""},
[]xml.Attr{
xml.Attr{xml.Name{"xmlns", "xsi"}, "http://www.w3.org/2001/XMLSchema-instance"},
xml.Attr{xml.Name{"xmlns", "xsd"}, "http://www.w3.org/2001/XMLSchema"},
xml.Attr{xml.Name{"xmlns", "soap"}, "http://www.w3.org/2003/05/soap-envelope"},
})
x.RegisterTypeMore("", xml.Name{}, []xml.Attr{
xml.Attr{xml.Name{"http://www.w3.org/2001/XMLSchema-instance", "type"}, "xsd:string"},
})
buf := new(bytes.Buffer)
buf.WriteString(`<?xml version="1.0" encoding="utf-8"?>`)
buf.WriteByte('\n')
enc := x.NewEncoder(buf)
env := &Envelope{Body{MethodCall{
One: "one",
Two: "two",
}}}
if err := enc.Encode(env); err != nil {
log.Fatal(err)
}
// Print request
bs := buf.Bytes()
bs = bytes.Replace(bs, []byte{'>', '<'}, []byte{'>', '\n', '<'}, -1)
fmt.Printf("%s\n\n", bs)
/*
// Send response, SOAP 1.2, fill in url, namespace, and action
var r *http.Response
if r, err = http.Post(url, "application/soap+xml; charset=utf-8; action="+namespace+"/"+action, buf); err != nil {
return
}
dec := x.NewDecoder(r.Body)
*/
// Decode response
dec := x.NewDecoder(bytes.NewBufferString(`<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
<soap:Body>
<MethodCallResponse>
<Three>three</Three>
</MethodCallResponse>
</soap:Body>
</soap:Envelope>`))
find := []xml.Name{
xml.Name{"", "MethodCallResponse"},
xml.Name{"http://www.w3.org/2003/05/soap-envelope", "Fault"},
}
var start *xml.StartElement
var err error
if start, err = dec.Find(find); err != nil {
log.Fatal(err)
}
if start.Name.Local == "Fault" {
log.Fatal("Fault!") // Here you can decode a Soap Fault
}
var resp MethodCallResponse
if err := dec.DecodeElement(&resp, start); err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n\n", resp)
}
Con l'esempio di cui sopra io uso il metodo Find
per ottenere l'oggetto risposta, o un guasto. Questo non è strettamente necessario. È anche possibile fare in questo modo:
x.RegisterType(MethodCallResponse{})
...
// Decode response
dec := x.NewDecoder(bytes.NewBufferString(`<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
<soap:Body>
<MethodCallResponse>
<Three>three</Three>
</MethodCallResponse>
</soap:Body>
</soap:Envelope>`))
var start *xml.StartElement
var resp Envelope
if err := dec.DecodeElement(&resp, start); err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n\n", resp)
troverete il metodo Find
utile quando i dati si presenta così:
<soap:Envelope>
<soap:Body>
<MethodResponse>
<MethodResult>
<diffgr:diffgram>
<NewDataSet>
<Table1 diffgr:id="Table1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
<Three>three</Three>
</Table1>
</NewDataSet>
</diffgr:diffgram>
</MethodResult>
</MethodResponse>
</soap:Body>
</soap:Envelope>
Questo è un DiffGram, parte di Microsoft .NET.È possibile utilizzare il metodo Find
per arrivare a Table1
. Il metodo Decode
e DecodeElement
funziona anche su sezioni. Quindi è possibile passare in un []MethodCallResponse
se si verifica che NewDataSet
contenga più di un risultato.
Sono d'accordo con Zippower che SOAP fa schifo. Ma sfortunatamente molte aziende usano SOAP e qualche volta sei costretto a usare queste API. Con il pacchetto xmlutil spero di renderlo un po 'meno doloroso con cui lavorare.
Go tip ora supporta [Marsalers] (http://tip.golang.org/pkg/encoding/xml/#Marshaler) e [Unmarshalers] (http://tip.golang.org/pkg/encoding/xml/# Unmarshaler) in codifica/xml come codifica/json già fatto, e questa caratteristica dovrebbe essere in Go 1.2. Questo potrebbe aiutare a gestire SOAP. – Matt
Funziona alla grande @luke, la tua piccola utility xml lib ... js ha bisogno di una documentazione introduttiva, anche se con pochi minuti di scansione attraverso lo script sopra sono stato in grado di capire come andare da cose – Knights
Ho scritto un parser WSDL che può generare un codice Go per chiamare SOAP. Ci sono molte limitazioni nella codifica/xml per quanto riguarda i tag e ho inserito un link nel README. Dai un'occhiata a: https://github.com/fiorix/wsdl2go – fiorix
Mentre non c'è ancora nulla di Go per sé, non v'è gowsdl. Finora, sembra funzionare abbastanza bene per me per interfacciarmi con diversi servizi SOAP.
Non utilizzo il proxy SOAP fornito, che credo non supporti l'autenticazione, ma lo standard gowsdl genera le strutture e il codice necessari dal WSDL alle richieste di marshall e risposte unmarshal: una grande vittoria.
C'è anche wsdl-go.
Ma non l'ho usato, quindi non posso davvero dire.
This sembra non esistere più. –
Grazie per il piccolo pacchetto XML/SOAP, ha funzionato bene. I ragazzi possono trovare la lib qui - https://github.com/webconnex/xmlutil – Knights
Spesso devo usare SOAP su sistemi legacy, e lo sto facendo con strutture hard in Go fino allo scorso fine settimana. Hacked up parser + Go code generator per WSDL che può produrre codice Go utilizzabile per chiamare SOAP. Alcune delle API che uso sono piuttosto estese, generando file con oltre 2k LOC. Scoprilo: https://github.com/fiorix/wsdl2go – fiorix