日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

soap协议_Go和SOAP

發布時間:2025/3/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 soap协议_Go和SOAP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在REST和RPC大行其道的今天,支持SOAP(簡答對象訪問協議)作為Web服務消息交換協議的情況是越來越少了。但在一些遺留系統中,尤其是采用微軟技術棧的服務系統中,SOAP依然占有一席之地,比如在一些醫院院內的IT系統中。

Go語言誕生后,主流的Web Service設計已經開始過渡到REST和RPC,Go相關開源項目也以對REST和RPC的支持為主。而對SOAP的支持則少而零散,社區里也沒有對SOAP支持的重量級開源項目,在awesome go的各種list中也難覓有關SOAP的推薦項目的身影。

但Gopher世界還是有以client身份與SOAP service交互或是實現SOAP server的需求的。在這篇文章中,我就和大家一起來探索一下如何基于一些開源項目,使用Go實現SOAP client和SOAP Server的。

一.SOAP簡介

如果你覺得SOAP這個協議很陌生也不奇怪,因為SOAP協議誕生于“遙遠”的1998年,2000年才提交到標準化組織。SOAP是一種消息傳遞協議規范,用于在計算機網絡的Web服務中實現交換結構化信息。其目的是促進可擴展性、中立性和獨立性。它使用XML作為承載消息的格式,并依賴于應用層協議,通常是HTTP或SMTP(簡單郵件傳輸協議),用于消息協商和傳輸。經過若干年的演進,其主要binding的協議是http,其支持SMTP Binding已經極少有應用了。現在,我們可以不嚴謹的說,SOAP可以理解為“xml over http”。并且從SOAP Body的形式來看,SOAP也像是一種使用XML作為序列化編碼格式的RPC調用。

SOAP目前存在兩個版本:1.1和1.2版本。一些比較old的SOAP服務僅支持1.1版本,而一些新的SOAP服務則兩個版本都支持。

下面是SOAP協議的通用結構:

基于這個結構,我們看看SOAP(over http)的Request和Response的樣子:

關于SOAP協議的更多細節,可以參見SOAP協議規范,這里限于篇幅就不細說了。

二.環境準備

本文中使用的Go語言版本為go 1.11.2。

  • 獲取wsdl文件

  • 現在在互聯網上要找到一個面向公共的、免費的SOAP服務著實困難。free-web-services.com上的很多服務已經不提供SOAP服務了,并且多數提供SOAP的服務也已經打不開頁面了。在本文中,我們將使用www.dneonline.com/calculator.asmx這個calculator服務,至少目前它還是ready的(不過也不保證它在將來能一直ready)。

    我們可以通過下面命令獲得這個calculator服務的WSDL文件。

    $cd /Users/tony/go/src/github.com/bigwhite/experiments/go-soap/pkg



    $curl http://www.dneonline.com/calculator.asmx\?WSDL > calculator.wsdl



    $cat calculator.wsdl



    <?xml version="1.0" encoding="utf-8"?>

    l:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
    ... ...l:service name="Calculator">l:port name="CalculatorSoap" binding="tns:CalculatorSoap">
    "http://www.dneonline.com/calculator.asmx" />l:port>l:port name="CalculatorSoap12" binding="tns:CalculatorSoap12">"http://www.dneonline.com/calculator.asmx" />l:port>l:service>l:definitions>

    這個calculator.wsdl是后續實現soap client和soap server的基礎。

    2. 根據wsdl文件生成SOAP package

    雖然Go語言標準庫中擁有比較完善的XML操作package,但是我們也沒有必要從頭開始進行SOAP協議的封裝和解包。github上面的gowsdl項目可以幫助我們基于calculator.wsdl自動生成實現SOAP Client和SOAP Server所要使用的各種方法和結構體,這也是我們后續實現SOAP Client和SOAP Server的基本原理。

    $go get github.com/hooklift/gowsdl/...



    $gowsdl -i calculator.wsdl

    Reading file /Users/tony/go/src/github.com/bigwhite/experiments/go-soap/pkg/calculator.wsdl



    Done



    $tree

    .

    ├── calculator.wsdl

    └── myservice

    ? ?└── myservice.go



    1 directory, 2 files

    gowsdl根據calculator.wsdl生成了myservice.go,所有有關calculator soap service的結構體和方法都在這個Go源文件中。有了這個package,我們就可以來實現soap客戶端了。

    三.實現SOAP客戶端

    我們實現一個SOAP客戶端,用于調用www.dneonline.com/calculator服務中提供的Add方法來進行加法計算。

    我們先在$GOPATH/src/github.com/bigwhite/experiments/go-soap下面建立client目錄,進入client目錄,創建client的main.go文件。

    在前面根據calculator.wsdl生成的myservice.go文件中,我們找到了NewCalculatorSoap方法,該方法會返回一個到對應服務的client實例,通過該soap client實例,我們可以調用其包含的Add方法,我們來看一下main.go中的代碼實現:

    package main



    import (

    ? ?"fmt"



    ? ?soap "github.com/bigwhite/experiments/go-soap/pkg/myservice"

    )



    func main() {

    ? ?c := soap.NewCalculatorSoap("", false, nil)

    ? ?r, err := c.Add(&soap.Add{

    ? ? ? ?IntA: 2,

    ? ? ? ?IntB: 3,

    ? ?})



    ? ?if err != nil {

    ? ? ? ?fmt.Println(err)

    ? ? ? ?return

    ? ?}

    ? ?fmt.Println(r.AddResult)

    }

    Add方法的參數為soap.Add結構體的實例,Add結構有兩個字段IntA和IntB,分別代表了兩個加數。我們來執行一下該client實現:

    $go run main.go

    2019/01/08 12:54:31 <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Add xmlns="http://tempuri.org/"><intA>2intA><intB>3intB>Add>Body>Envelope>

    2019/01/08 12:54:31 xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AddResponse xmlns="http://tempuri.org/"><AddResult>5AddResult>AddResponse>soap:Body>soap:Envelope>

    5

    我們看到client輸出了加法服務調用后的正確結果:5。

    四.實現SOAP服務

    下面我們再來實現一個類似www.dneonline.com/calculator的服務,由于只是demo,我們只實現Add方法,其他方法的“套路”是一樣的。

    我們在$GOPATH/src/github.com/bigwhite/experiments/go-soap下面建立server目錄,進入server目錄,創建server的main.go文件。pkg/myservice/myservice.go中只是SOAP層協議數據負荷的marshal和unmarshal操作,并沒有網絡層面的支持,因此我們需要自己建立http server框架,我們就使用Go標準庫http server。代碼結構如下:

    package main



    import (

    ? ?"encoding/xml"

    ? ?"fmt"

    ? ?"io/ioutil"

    ? ?"log"

    ? ?"net/http"

    ? ?"regexp"



    ? ?soap "github.com/bigwhite/experiments/go-soap/pkg/myservice"

    )



    func main() {

    ? ?s := NewSOAPServer("localhost:8080")

    ? ?log.Fatal(s.ListenAndServe())

    }



    func NewSOAPMux() *http.ServeMux {

    ? ?mux := http.NewServeMux()

    ? ?mux.HandleFunc("/", soapHandler)

    ? ?return mux

    }



    func NewSOAPServer(addr string) *http.Server {

    ? ?mux := NewSOAPMux()

    ? ?server := &http.Server{

    ? ? ? ?Handler: mux,

    ? ? ? ?Addr: ? ?addr,

    ? ?}

    ? ?return server

    }



    func soapHandler(w http.ResponseWriter, r *http.Request) {



    ? ... ...



    }

    這個SOAP server的外層結構與普通http server并無太多差異。我們重點要關注的是soapHandler的實現邏輯。

    func soapHandler(w http.ResponseWriter, r *http.Request) {

    ? ?rawBody, err := ioutil.ReadAll(r.Body)

    ? ?if err != nil {

    ? ? ? ?w.WriteHeader(http.StatusInternalServerError)

    ? ? ? ?return

    ? ?}



    ? ?// match method

    ? ?var res interface{}

    ? ?m := regexp.MustCompile(`)if m.MatchString(string(rawBody)) {
    ? ? ? ?res = processAdd(rawBody)
    ? ?} else {
    ? ? ? ?res = nil
    ? ? ? ?fmt.Println("the method requested is not available")
    ? ?}
    ? ?v := soap.SOAPEnvelope{
    ? ? ? ?Body: soap.SOAPBody{
    ? ? ? ? ? ?Content: res,
    ? ? ? ?},
    ? ?}
    ? ?w.Header().Set("Content-Type", "text/xml")
    ? ?x, err := xml.MarshalIndent(v, "", " ?")if err != nil {
    ? ? ? ?w.WriteHeader(http.StatusInternalServerError)return
    ? ?}
    ? ?w.WriteHeader(http.StatusOK)
    ? ?w.Write(x)return
    }

    我們看到:

    首先,我們從http body中讀取出原始數據;

    接下來,我們通過一個正則表達式去匹配原始數據,如果匹配到方法,則進入方法的處理函數processAdd;否則提示方法不存在;

    最后將processAdd的返回結果marshall為SOAP格式后,返回給client端。

    processAdd是真正執行服務算法的函數:

    func processAdd(body []byte) *soap.AddResponse {

    ? ?envlop := &soap.SOAPEnvelope{

    ? ? ? ?Body: soap.SOAPBody{

    ? ? ? ? ? ?Content: &soap.Add{},

    ? ? ? ?},

    ? ?}

    ? ?err := xml.Unmarshal(body, envlop)

    ? ?if err != nil {

    ? ? ? ?fmt.Println("xml Unmarshal error:", err)

    ? ? ? ?return nil

    ? ?}



    ? ?fmt.Println(envlop.Body.Content)



    ? ?r, ok := envlop.Body.Content.(*soap.Add)

    ? ?if !ok {

    ? ? ? ?return nil

    ? ?} else {

    ? ? ? ?return &soap.AddResponse{

    ? ? ? ? ? ?AddResult: r.IntA + r.IntB,

    ? ? ? ?}

    ? ?}

    }

    processAdd首先將rawBody unmarshal到一個SOAPEnvelope結構體中,從而得到SOAP envelope中Body中的方法的輸入參數的值:IntA和IntB。將兩個加數的和賦值給AddResult,作為AddResponse的值返回。

    我們啟動一下該SOAP server,并修改一下前面client所要連接的soap server的地址,并讓client向我們自己實現的soap server發起服務請求調用:

    1.修改client main.go

    $GOPATH/src/github.com/bigwhite/experiments/go-soap/client/main.go



    ? ?//c := soap.NewCalculatorSoap("", false, nil)

    ? ?c := soap.NewCalculatorSoap("http://localhost:8080/", false, nil)

    2.啟動soap server

    $GOPATH/src/github.com/bigwhite/experiments/go-soap/server git:(master) ? $go run main.go

    3. 啟動client

    $go run main.go

    2019/01/08 14:55:20 <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Add xmlns="http://tempuri.org/"><intA>2intA><intB>3intB>Add>Body>Envelope>

    2019/01/08 14:55:20 <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">

    ?<Body xmlns="http://schemas.xmlsoap.org/soap/envelope/">

    ? ?<AddResponse xmlns="http://tempuri.org/">

    ? ? ?<AddResult>5AddResult>

    ? ?AddResponse>

    ?Body>

    Envelope>

    5

    4. server console輸出

    &{{http://tempuri.org/ Add} 2 3}

    我們看到,我們的client成功調用了我們實現的SOAP Server的服務方法,并獲得了正確的結果。一個簡單的SOAP server就這么實現了。不過明眼的朋友肯定已經看出代碼中的問題了,那就是method match那塊僅僅適用于demo,在真正的服務中,服務會有很多method,我們需要一種規范的、通用的匹配機制,一種可以通過SOAP Body匹配來做,另一種可以通過http header中的SOAP Action 來匹配(僅適用于SOAP 1.1,SOAP 1.2版本去掉了SOAP Action)。這里就留給大家自己去發揮吧。

    五.小結

    如果不是碰到了基于SOAP的遺留系統,我想我是不會研究SOAP的,畢竟基于SOAP的系統正在逐漸消逝在大眾的視野中。上面的demo應該可以讓大家對如何用Go與SOAP系統交互有了一個粗淺的認識。這里算是一個不錯的起點。如果大家對于Go與SOAP有更深刻地研究或者有更好的有關SOAP的開源項目,歡迎交流。

    文中源碼在這里https://github.com/bigwhite/experiments/tree/master/go-soap可以找到。


    我的網課“Kubernetes實戰:高可用集群搭建、配置、運維與應用”在慕課網上線了,感謝小伙伴們學習支持!

    我要發短信:企業級短信平臺定制開發專家 https://51smspush.com/

    smspush : 可部署在企業內部的定制化短信平臺,三網覆蓋,不懼大并發接入,可定制擴展; 短信內容你來定,不再受約束, 接口豐富,支持長短信,簽名可選。

    著名云主機服務廠商DigitalOcean發布最新的主機計劃,入門級Droplet配置升級為:1 core CPU、1G內存、25G高速SSD,價格5$/月。有使用DigitalOcean需求的朋友,可以打開這個鏈接地址:https://m.do.co/c/bff6eed92687 開啟你的DO主機之路。

    我的聯系方式:

    微博:https://weibo.com/bigwhite20xx

    微信公眾號:iamtonybai

    博客:tonybai.com

    github: https://github.com/bigwhite

    商務合作方式:撰稿、出書、培訓、在線課程、合伙創業、咨詢、廣告合作。

    ? 2019, bigwhite. 版權所有.

    總結

    以上是生活随笔為你收集整理的soap协议_Go和SOAP的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。