Home About Contact
Go , Micronaut

Golang で POST する(備忘録)

Golang を使ってウェブサーバに POST する最小限のサンプルをつくる。 POSTを受けるサーバは Micronaut で用意する。

なお、OS は Ubuntu 20.04, go version go1.16.4 linux/amd64, Micronaut Version: 2.5.7 で試しています。

Micronaut で POST を受けるエンドポイントを用意

$ mn create-app myapp --build=gradle --lang=groovy
$ cd myapp
$ mn create-controller item

生成したコントローラ src/main/groovy/myapp/ItemController.groovy を編集:

package myapp

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.annotation.Body

@Controller("/item")
class ItemController {
    @Post(uri="/", consumes=["application/json"], produces="text/plain")
    String index(@Body def contents) {
        contents.toString()
    }
}

http://localhost:8080/item/ に POST すると POST された内容をそのままオウム返します。
./gradlew run してサーバを起動しておきます。

curl でテスト

$ curl -X POST "http://localhost:8080/item/" -d '{ "hello": "world" }' -H "Content-Type: application/json"
{ "hello": "world" }

できました。

golang で実装

curl と同じ機能を果たすクライアントを実装します。

$ mkdir client
$ cd client
$ go mod init client

main.go を準備:

package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

type Params struct {
    url  string
    json string
}

func contents(resp *http.Response) (string, error) {
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }
    return string(b), nil
}

func doPost(params *Params) (string, error) {
    req, err := http.NewRequest("POST", params.url, bytes.NewBuffer([]byte(params.json)))
    if err != nil {
        return "", err
    }

    client := &http.Client{Timeout: time.Second * 10}
    response, err := client.Do(req)
    if err != nil {
        return "", err
    }
    defer response.Body.Close()

    statusCode := response.StatusCode
    if statusCode != 200 {
        return "", fmt.Errorf("StatusCode %d is not expected.", statusCode)
    }

    result, err := contents(response)
    if err != nil {
        return "", err
    }
    return result, nil
}

func main() {
    params := Params{
        url:  "http://localhost:8080/item/",
        json: "{\"hello\":\"world\"}",
    }

    result, err := doPost(&params)
    if err != nil {
        fmt.Println(fmt.Errorf("Got error %s", err.Error()))
    }
    fmt.Println( fmt.Sprintf("%s", result) )
}

実行:

$ go run main.go
{"hello":"world"}

できました。