如何在Go中进行SOAP调用?

huangapple go评论70阅读模式
英文:

How to do a SOAP call in Go?

问题

鉴于Adwords是Google的产品,而Go也是Google的产品,那么什么时候会有用Go编写的Adwords API版本?

与此问题相关的另一个问题是:目前是否有适用于Go的SOAP库?

英文:

Given that Adwords is a Google thing, and Go is a Google thing, how long until there's a version of the Adwords API written in Go?

Associated with that question, another: are there any SOAP libraries for Go yet?

答案1

得分: 37

我无法回答关于AdWords API的问题,因为我没有看到公司的任何公告,而且很难从外部预测发布的时间。

所以我会回答你的第二个问题。

我不知道Go语言中是否有任何SOAP库(go-lang.cat-v.org似乎没有提到),但是像大多数语言一样,处理简单SOAP消息的方法是使用基本的httpxml库。

两个重要的操作是:

1)通过进行POST查询来获取答案:

resp, err := httpClient.Post(query, "text/xml; charset=utf-8", someXMLasBytes)

2)使用xml.NewDecoder将其解码为所需的结构:

parser := xml.NewDecoder(bytes.NewBufferString(in)) 
err = parser.DecodeElement(&envelope, nil)

这是一个完整且有注释的在Go中执行SOAP查询的示例(简化自此处):

package main   

import (
    "bytes"
    "encoding/xml"
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "strings"
)

// SOAP服务器的URL
const MH_SOAP_URL = "http://sp.mountyhall.com/SP_WebService.php"

// 这只是我将用于查询的消息,带有占位符
// 用于我的参数
const SOAP_VUE_QUERY_FORMAT = `<?xml version="1.0" encoding="UTF-8" standalone="no"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:SP_WebService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" ><SOAP-ENV:Body><mns:Vue xmlns:mns="uri:mhSp" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><numero xsi:type="xsd:string">%d</numero><mdp xsi:type="xsd:string">%s</mdp></mns:Vue></SOAP-ENV:Body></SOAP-ENV:Envelope>`

// 在这里定义Go结构,几乎与我们将获取的XML消息的结构相同
// 注意注释(字符串“return&gt;item”)允许具有稍微不同的结构或不同的命名

type SoapItem struct {
    Numero    int
    Nom       string
    Type      string
    PositionX int
    PositionY int
    PositionN int
    Monde     int
}
type SoapVue struct {
    Items []SoapItem "return&gt;item" 
}
type SoapFault struct {
    Faultstring string
    Detail      string
}
type SoapBody struct {
    Fault          SoapFault
    ProfilResponse SoapProfil
    VueResponse    SoapVue
}
type SoapEnvelope struct {
    XMLName xml.Name
    Body    SoapBody
}

// 这是查询SOAP服务器的函数
// 它将整个答案作为Go结构(SoapEnvelope)返回
// 你也可以在第二个返回的参数中返回错误
func GetSoapEnvelope(query string, numero int, mdp string) (envelope *SoapEnvelope) {
    soapRequestContent := fmt.Sprintf(query, numero, mdp)
    httpClient := new(http.Client)
    resp, err := httpClient.Post(MH_SOAP_URL, "text/xml; charset=utf-8", bytes.NewBufferString(soapRequestContent)) 
    if err != nil {
        // 处理错误
    }
    b, e := ioutil.ReadAll(resp.Body) // 可能不高效,因为流不总是纯XML流,我必须修复一些东西(此处未显示)
    if e != nil {
        // 处理错误
    }
    in := string(b)
    parser := xml.NewDecoder(bytes.NewBufferString(in))
    envelope = new(SoapEnvelope) // 这将分配我们将解码XML的结构
    err = parser.DecodeElement(&envelope, nil)
    if err != nil {
        // 处理错误
    }
    resp.Body.Close()
    return
}
英文:

I can' answer about the adwords API as I saw no announcement from the company and predicting the time before a release can hardly be done from outside.

So I'll answer your second question.

I don't know any SOAP library in Go (go-lang.cat-v.org doesn't seem to reference one) but as in most languages, a way to deal with simple SOAP messages is to use the basic http and xml libraries.

The two important operations are

  1. to get an answer by doing a POST query :

    resp, err := httpClient.Post(query, "text/xml; charset=utf-8", someXMLasBytes)

  2. to decode it using a xml.NewDecoder into the desired structure :

    parser := xml.NewDecoder(bytes.NewBufferString(in))
    err = parser.DecodeElement(&envelope, nil)

Here's a complete and commented example of a SOAP query done in Go (simplified from this) :

package main   

import (
	&quot;bytes&quot;
	&quot;encoding/xml&quot;
    &quot;fmt&quot;
	&quot;io&quot;
	&quot;io/ioutil&quot;
	&quot;net/http&quot;
	&quot;strings&quot;
)

// The URL of the SOAP server
const MH_SOAP_URL = &quot;http://sp.mountyhall.com/SP_WebService.php&quot;

// this is just the message I&#39;ll send for interrogation, with placeholders
//  for my parameters
const SOAP_VUE_QUERY_FORMAT = &quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot; standalone=\&quot;no\&quot;?&gt;&lt;SOAP-ENV:Envelope xmlns:SOAP-ENV=\&quot;http://schemas.xmlsoap.org/soap/envelope/\&quot; xmlns:xsd=\&quot;http://www.w3.org/2001/XMLSchema\&quot; xmlns:xsi=\&quot;http://www.w3.org/2001/XMLSchema-instance\&quot; xmlns:tns=\&quot;urn:SP_WebService\&quot; xmlns:soap=\&quot;http://schemas.xmlsoap.org/wsdl/soap/\&quot; xmlns:wsdl=\&quot;http://schemas.xmlsoap.org/wsdl/\&quot; xmlns:SOAP-ENC=\&quot;http://schemas.xmlsoap.org/soap/encoding/\&quot; &gt;&lt;SOAP-ENV:Body&gt;&lt;mns:Vue xmlns:mns=\&quot;uri:mhSp\&quot; SOAP-ENV:encodingStyle=\&quot;http://schemas.xmlsoap.org/soap/encoding/\&quot;&gt;&lt;numero xsi:type=\&quot;xsd:string\&quot;&gt;%d&lt;/numero&gt;&lt;mdp xsi:type=\&quot;xsd:string\&quot;&gt;%s&lt;/mdp&gt;&lt;/mns:Vue&gt;&lt;/SOAP-ENV:Body&gt;&lt;/SOAP-ENV:Envelope&gt;&quot;

// Here I define Go structures, almost identical to the structure of the
// XML message we&#39;ll fetch
// Note that annotations (the string &quot;return&gt;item&quot;) allow to have a slightly
//  different structure or different namings

type SoapItem struct {
	Numero    int
	Nom       string
	Type      string
	PositionX int
	PositionY int
	PositionN int
	Monde     int
}
type SoapVue struct {
	Items []SoapItem &quot;return&gt;item&quot; 
}
type SoapFault struct {
	Faultstring string
	Detail      string
}
type SoapBody struct {
	Fault          SoapFault
	ProfilResponse SoapProfil
	VueResponse    SoapVue
}
type SoapEnvelope struct {
	XMLName xml.Name
	Body    SoapBody
}

// Here is the function querying the SOAP server
// It returns the whole answer as a Go structure (a SoapEnvelope)
// You could also return an error in a second returned parameter
func GetSoapEnvelope(query string, numero int, mdp string) (envelope *SoapEnvelope) {
	soapRequestContent := fmt.Sprintf(query, numero, mdp)
	httpClient := new(http.Client)
	resp, err := httpClient.Post(MH_SOAP_URL, &quot;text/xml; charset=utf-8&quot;, bytes.NewBufferString(soapRequestContent)) 
	if err != nil {
		// handle error
	}
	b, e := ioutil.ReadAll(resp.Body) // probably not efficient, done because the stream isn&#39;t always a pure XML stream and I have to fix things (not shown here)
	if e != nil {
		// handle error
	}
	in := string(b)
	parser := xml.NewDecoder(bytes.NewBufferString(in))
	envelope = new(SoapEnvelope) // this allocates the structure in which we&#39;ll decode the XML
	err = parser.DecodeElement(&amp;envelope, nil)
	if err != nil {
		// handle error
	}
	resp.Body.Close()
	return
}

答案2

得分: 1

Google APIs for Go是一个正在进行中的工作。

英文:

The Google APIs for Go is a work in progress.

huangapple
  • 本文由 发表于 2012年9月4日 11:19:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/12256353.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定