Go で SOAP 通信

初めまして、クリエイターブログは初めての投稿です。 MIRAILでサーバサイドを担当している、Senoue と申します。

初投稿はGoでSOAP 通信を行なった話です

MIRAILでは、APIをGAE上にGoで作っています。 今回はGoの標準パッケージのみを使った簡単な実装例をご紹介します。

そもそも、SOAP とは?

参考:Wikipedia

ja.wikipedia.org

RESTful API がすっかりデファクトとなってしまったため、最近ではあまり見かける機会も減ってますが、 歴史のあるサービスでは、未だ使われている場合があります。

では、早速解説をさせていだきます

まずは送信するXMLを作る方法ですが、これは html/templateパッケージ を利用して作成しています。 ベースとなるXMLのテンプレートと可変となる箇所を準備します。

// テンプレート
var getTemplate = `
<?xml version="1.0" encoding="UTF-8"?>
<Request>
    <Credentials>
        <id>{{.ID}}</id>
        <password>{{.Password}}</password>
    </Credentials>
    <Identity>
        <key>{{.Key}}</key>
   </Identity>
</Request>`

こうするとわかりやすいですね。 次に、このテンプレートを使用してSOAPのリクエストを生成する処理を作成します。

// SOAP リクエストの作成
func generateSOAPRequest(req *Request) (*http.Request, error) {
    // テンプレートを使ってXMLを作成
    tem, err := template.New("InputRequest").Parse(getTemplate)

    if err != nil {
        log.Printf("オブジェクトのマーシャルに失敗しました。 %s ", err.Error())
        return nil, err
    }

    doc := &bytes.Buffer{}
    err = tem.Execute(doc, req)
    if err != nil {
        log.Printf("テンプレートの実行に失敗しました。 %s ", err.Error())
        return nil, err
    }

    r, err := http.NewRequest(http.MethodPost, "{SOAP APIのURL}", doc)
    r.Header.Add("Content-Type", "application/xml; charset=utf-8")
    if err != nil {
        log.Printf("リクエストの作成に失敗しました。 %s ", err.Error())
        return nil, err
    }

    return r, nil
}

リクエスト先のURLもこの時点で準備しておきます。 こちらのテンプレートXML内で、仮に可変になる部分を指定する関数を用意しています。

適宜、受け取った値などを利用していただければ変更ができます。

// リクエストの型
type Request struct {
    Key      string
    ID       string
    Password string
}

// リクエストの内容
func populateRequest() *Request {
    req := Request{}
    req.Key = "12345678"
    req.ID = "Senoseno"
    req.Password = "Password"
    return &req
}

※ID、パスワードは仮のものを利用しています。

次に、生成したリクエストを用いてSOAP通信を行う処理を作成します。

// SOAP コール
func soapCall(req *http.Request) (*Response, error) {
    client := &http.Client{}
    resp, err := client.Do(req)

    if err != nil {
        return nil, err
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    r := &Response{}
    err = xml.Unmarshal(body, &r)

    if err != nil {
        return nil, err
    }
    return r, nil
}

最後に、それぞれの関数を実行するhandlerを作ります。

// SOAP アクセス
func handler(w http.ResponseWriter, r *http.Request) {
    req := populateRequest()

    httpReq, err := generateSOAPRequest(req)
    if err != nil {
        log.Println("リクエスト生成で問題が発生しました")
    }
    log.Println(httpReq)
    response, err := soapCall(httpReq)
    if err != nil {
        log.Println("SOAP呼び出しの実行中に問題が発生しました")
    }
    res, _ := json.Marshal(response)
    log.Println(res)
}

今回のサンプルでは、実行後の結果のXMLを取得できます。

これだけでSOAP 通信が実装できました。とても簡単ですね。

上記のSOAP通信と連携したAPIを利用したご紹介

MIRAILでは、東映様の『仮面ライダー 令和 ザ・ファースト・ジェネレーション』の 映画とコラボした、ムビチケ前売券 購入者向けの過去作を無料で視聴できるキャンペーンを実施しています。

kamenrider-winter.com

ムビチケ前売券をお持ちの方は2020年1月31日まで利用できますので、MIRAILで過去作もお楽しみください。

ちなみにこのソースのサンプルをこちらで公開しています。

github.com

ご興味あるかたはご覧ください。

参考元記事: Golang & SOAP Based Services - Level Up Coding