search
LoginSignup
137

More than 5 years have passed since last update.

posted at

Organization

こんなに簡単! Goで作るRESTサーバー

Goを始めて4日たった。仕事関係のウェブサービスで、負荷分散のためにバックエンドを冗長化する必要がでてきた。そういうとなんかすごそうだが、高負荷の外部コマンドを叩くだけのサービスを作ればいい。複雑さはない。今回はそのサービスをRESTサーバーとしてGoで作る。

この記事のゴール

Goで作ったRESTサーバーをLinuxにデプロイし、httpieで叩いてみる

準備

まず、Macで作ってLinuxにデプロイしようと思うので、Mac, Linux, Windowsにコンパイルできるように、クロスコンパイル可能な状態でGoをインストールする:

brew install go --cross-compile-common

次に、適当にフォルダを作る

mkdir ~/Desktop/gorest
cd ~/Desktop/gorest/

つぎに、service.goファイルを作る

touch service.go

それを、エディタで開く

最後に、$GOPATHをセットしてなければ、とりあえず ~/Desktop/gorest にしておく

export GOPATH=$(pwd)

APIの仕様

名前を入力すると、Hello, <名前> で返してくる

  • POST /hello
HTTPリクエストのBody
{
    "Name": "Alice"
}
HTTPレスポンスのBody
{
    "Result": "Hello, Alice"
}

RESTサーバーを簡単に作れるライブラリを取ってくる

go get github.com/ant0ine/go-json-rest

サーバー(service.go)のコードを書く

賞味40行くらい

service.go
package main

import (
    "github.com/ant0ine/go-json-rest"
    "log"
    "net/http"
)

// 入力の定義
type postHelloInput struct {
    Name string
}

// 出力の定義
type postHelloOutput struct {
    Result string
}

func postHello(w *rest.ResponseWriter, req *rest.Request) {
    input := postHelloInput{}
    err := req.DecodeJsonPayload(&input)

    // そもそも入力の形式と違うとここでエラーになる
    if err != nil {
        rest.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // 適当なバリデーション
    if input.Name == "" {
        rest.Error(w, "Name is required", 400)
        return
    }

    log.Printf("%#v", input)

    // 結果を返す部分
    w.WriteJson(&postHelloOutput{
        "Hello, " + input.Name,
    })
}

func main() {
    handler := rest.ResourceHandler{}
    handler.SetRoutes(
        rest.Route{"POST", "/hello", postHello},
    )
    log.Printf("Server started")
    http.ListenAndServe(":9999", &handler) // ポート9999で立ち上がる
}

実行してみる

go run server.go でサーバーを起動する

go run service.go

ターミナルの別タブを開いて、httpieでリクエストを投げてみる

http -v POST localhost:9999/hello "Content-Type:application/json; charset=UTF-8" Name="Suin"
POST /hello HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Length: 16
Content-Type: application/json; charset=UTF-8
Host: localhost:9999
User-Agent: HTTPie/0.6.0

{
    "Name": "Suin"
}

HTTP/1.1 200 OK
Content-Length: 29
Content-Type: application/json
Date: Fri, 06 Dec 2013 16:10:15 GMT

{
    "Result": "Hello, Suin"
}

うまく動いている様子。

Linux用にビルドする

Linux 64ビット用のバイナリを作る:

GOOS=linux GOARCH=amd64 go build service.go

ビルドが終わると service という名前で7MBくらいの実行形式のバイナリができあがる。

ポート9999が開けてあるLinuxに持ってく

scpとかで転送する

scp service vagrant:

サーバにログインして、今転送したserviceを起動する

vagrant@suin:~$ ./service
2013/12/07 01:15:02 Server started

手元のMacから httpie で叩いてみる

http -v POST 11.11.11.11:9999/hello "Content-Type:application/json; charset=UTF-8" Name="Suin"
POST /hello HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Length: 16
Content-Type: application/json; charset=UTF-8
Host: 11.11.11.11:9999
User-Agent: HTTPie/0.6.0

{
    "Name": "Suin"
}

HTTP/1.1 200 OK
Content-Length: 29
Content-Type: application/json
Date: Fri, 06 Dec 2013 16:16:15 GMT

{
    "Result": "Hello, Suin"
}

Apacheも必要なくファイル一個だけで動くLinuxのRESTサーバーができました!

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
What you can do with signing up
137