gpt4 book ai didi

soap - Go 上的 WSDL/SOAP 支持?

转载 作者:IT老高 更新时间:2023-10-28 13:03:28 30 4
gpt4 key购买 nike

是否有任何软件包可以在 Go 上支持 SOAP/WSDL

最佳答案

Go 中不支持 WSDL。其他语言的支持要么是静态的,要么是动态的:要么是从 WSDL 预先生成的结构,要么是使用哈希表动态完成的。

但是,您可以手动编码和解码 SOAP 请求。我发现标准的 encoding/xml 包对于 SOAP 来说是不够的。不同的服务器有很多怪癖,encoding/xml 的限制使得很难生成这些服务器满意的请求。

例如,有些服务器需要在每个字符串标签上都有 xsi:type="xsd:string"。为了正确地做到这一点,你的结构需要看起来像这样 encoding/xml:

type MethodCall struct {
One XSI
Two XSI
}

type XSI struct {
Type string `xml:"xsi:type,attr"`
Vaue string `xml:",chardata"`
}

然后你像这样构造它:

MethodCall{
XSI{"xsd:string", "One"},
XSI{"xsd:string", "Two"},
}

这给了你:

<MethodCall>
<One xsi:type="xsd:string">One</One>
<Two xsi:type="xsd:string">Two</Two>
</MethodCall>

现在这可能没问题。它当然可以完成工作。但是,如果您需要的不仅仅是 string 怎么办? encoding/xml 目前不支持 interface{}

如您所见,这变得很复杂。如果您有一个要集成的 SOAP API,这可能不会太糟糕。如果你有几个,每个都有自己的怪癖怎么办?

如果你能做到这一点不是很好吗?

type MethodCall struct {
One string
Two string
}

然后对 encoding/xml 说:“此服务器需要 xsi 类型”。

为了解决这个问题,我创建了 github.com/webconnex/xmlutil .这是一项正在进行的工作。它没有 encoding/xml 的编码器/解码器的所有功能,但它具有 SOAP 所需的功能。

这是一个工作示例:

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)
}

在上面的示例中,我使用 Find 方法来获取响应对象或故障。这不是绝对必要的。你也可以这样做:

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)

当您的数据如下所示时,您会发现 Find 方法很有用:

<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>

这是一个 DiffGram,是 Microsoft .NET 的一部分。您可以使用 Find 方法来获取 Table1DecodeDecodeElement 方法也适用于 slice 。因此,如果 NewDataSet 恰好包含多个结果,则可以传入 []MethodCallResponse

我同意 Zippower 的观点,即 SOAP 确实很糟糕。但不幸的是,很多企业都在使用 SOAP,有时你不得不使用这些 API。有了 xmlutil 包,我希望使用起来不会那么痛苦。

关于soap - Go 上的 WSDL/SOAP 支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11767642/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com