LoginSignup
14
13

More than 5 years have passed since last update.

GoでRESTfulなWebアプリを作りたい (go-restfulを触ってみる)

Last updated at Posted at 2016-01-02

概要

GoでAPIサーバーを書こうと思ったらどうなるのかなーっと思い立ったのでやってみた。
APIの受け答えはJSON形式で行い、加えてダッシュボードみたいなUIも提供できるようなものを想定している。
DBとかデザインとかはそれぞれ別のレイヤーになるので今回はリクエストとレスポンスまで。

準備

今回使うのは go-restfulというパッケージ。RESTfulなHTTPサーバーを作るのに使う様子。
https://github.com/emicklei/go-restful

予め go get しておこう。

go get github.com/emicklei/go-restful

似たもので go-json-rest というものもあったが、JSONでの受け答え専用のようだったので今回はパスした。

コード全文

コードを説明して回るのも大変長くなるのでザッと書き出しておく :ghost:

package main

import (
    "github.com/emicklei/go-restful"
    "io"
    "net/http"
)

// Helloに渡す値を格納する
type resHello struct {
    Name string
    Memo string `json:",omitempty"`
}

// エラーレスポンス用の構造体
type resError struct {
    Error string
}

// "GET /hello" を処理する関数
func getHello(req *restful.Request, resp *restful.Response) {
    // GETのときは text/plain で文字列を返す
    io.WriteString(resp, "please tell me your name to /hello by POST method :)")
}

// "POST /hello" を処理する関数
func postHello(req *restful.Request, resp *restful.Response) {
    // リクエストを resHello に割り当てる
    param := new(resHello)
    req.ReadEntity(&param)

    // 適当なエラーハンドリング
    if param.Name == "" {
        // エラーの内容をJSONで返す
        resp.WriteHeaderAndJson(http.StatusInternalServerError, &resError{"Name is required"}, restful.MIME_JSON)
        return
    }

    // 結果を出力する (自動で application/json が指定される)
    resp.WriteAsJson(&resHello{Name: param.Name})
}

func main() {
    // restfulを初期化してルーティングの設定を行う
    ws := new(restful.WebService)
    ws.Route(ws.GET("/hello").To(getHello))
    ws.Route(ws.POST("/hello").To(postHello))
    restful.Add(ws)

    // 8080ポートで待ち受ける
    http.ListenAndServe(":8080", nil)
}

実行結果

上記のコードは go run でサーバーを立ち上げられる。
立ち上げたサーバーにはブラウザアクセスか、cURLでアクセスできる。

GET /hello

ブラウザやcURLで http://localhost:8080/hello にアクセスすると下記のような結果が得られる。

$ curl -i http://127.0.0.1:8080/hello
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    52  100    52    0     0   3250      0 --:--:-- --:--:-- --:--:--  3250HTTP/1.1 200 OK
Date: Sat, 02 Jan 2016 13:20:14 GMT
Content-Length: 52
Content-Type: text/plain; charset=utf-8

please tell me your name to /hello by POST method :)

ちなみにあえて指定を入れていない /404 Page Not Found となる

$ curl -i http://127.0.0.1:8080/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    19  100    19    0     0     19      0  0:00:01 --:--:--  0:00:01 19000HTTP/1.1 404 Not Found
Date: Sat, 02 Jan 2016 13:20:42 GMT
Content-Length: 19
Content-Type: text/plain; charset=utf-8

404: Page Not Found

POST /hello

cURLを使ってPOSTを叩くと下記のような応答になる。WriteAsJson で Content-type はよしなにやってくれる。
resHelloMemo に指定した omitempty (空の時は切り捨て) は有効な様子。

$ curl -i -H 'Content-Type: application/json' -d '{"Name":"Gopher"}' http://127.0.0.1:8080/hello
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    40  100    23  100    17   1437   1062 --:--:-- --:--:-- --:--:--  1437HTTP/1.1 200 OK
Content-Type: application/json
Date: Sat, 02 Jan 2016 13:11:48 GMT
Content-Length: 23

{
  "Name": "Gopher"
 }

ちなみにエラーハンドリングしている箇所はこのような応答になる。
JSONであることがわかっているのに WriteHeaderAndJsonrestful.MIME_JSON を指定してあげないといけないのは
ちょっと微妙かもと思ったが、もしかしたら使いどころが別にあるのかもしれない。

$ curl -i -H 'Content-Type: application/json' -d '{"Name":""}' http://127.0.0.1:8080/hello
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    45  100    34  100    11   2125    687 --:--:-- --:--:-- --:--:--  2125HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Date: Sat, 02 Jan 2016 13:09:46 GMT
Content-Length: 34

{
  "Error": "Name is required"
 }

感想

  • GoでHTTPサーバーと一体なアプリは意外とサクッと作れた。
  • サンプルコードも多めでGoDoc対応にも対応していたので割と安心。
  • go-restful はXMLの受け答えにも対応している様子。
  • WebアプリってPHP(CakePHPやLaravel)とかRuby(Rails、Sinatra)とかで作るイメージが強いけど、
    Goで実運用したりして問題になったりしないかは未知数。net/httpのベンチマークとかあるのかな?
14
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
13