LoginSignup
9
11

More than 5 years have passed since last update.

[Golang]RESTfulなAPIサーバー作成

Last updated at Posted at 2019-01-24

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

初心者になりますが、上記の記事を使ってAPIサーバーの作成を実践、自分なりにパッケージ等を調べて解説してみました。

概要

GolangでRESTサーバを起動し、POSTメソッドを受け付けるAPIを作成しました。(用語の使い方あってる?)

go-json-restパッケージを利用して、JSON形式のデータをやりとりする。

  1. httpieを使って localhost:9999/helloにアクセス
  2. JSON形式のName="gatapon"のデータを渡す
  3. Hello, gataponのレスポンスを受け取る

環境

  • go1.11.4
  • HTTPie/1.0.2

そのほか参考

実践

コーディング

server.go
package main

import (
    "log"
    "net/http"

    // githubから直接パッケージをいっポートできて便利
    "github.com/ant0ine/go-json-rest/rest"
)

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

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

func postHello(w rest.ResponseWriter, req *rest.Request) {
    input := postHelloInput{}
    // 各種バリデーションが行われている README.md参照
    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)
    }

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

    w.WriteJson(&postHelloOutput{
        "Hello, " + input.Name,
    })
}

func main() {
    api := rest.NewApi()
    api.Use(rest.DefaultDevStack...)
    router, err := rest.MakeRouter(
        rest.Post("/hello", postHello),
    )

    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Server started.")
    api.SetApp(router)
    log.Fatal(http.ListenAndServe(":9999", api.MakeHandler()))
}

実行準備

検証にhttpieを利用するのでインストール

$ brew install httpie

プログラムの実行。これでサーバが起動しAPIにアクセスができます。

$ go run server.go
2019/XX/XX XX:XX:XX Server started.

別のターミナルからhttpieを使ってアクセス

$ http -v POST localhost:9999/hello "Content-Type:application/json; charset=utf-8" Name="gatapon"

以下の内容でレスポンスが返ってくれば成功

POST /hello HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 15
Content-Type: application/json; charset=utf-8
Host: localhost:9999
User-Agent: HTTPie/1.0.2

{
    "Name": "gatapon"
}

HTTP/1.1 200 OK
Content-Length: 28
Content-Type: application/json; charset=utf-8
Date: XXX
X-Powered-By: go-json-rest

{
    "Result": "Hello, gatapon"
}

内容の詳細について

ターミナルで叩いたコマンドについて振り返ります。

http -v POST localhost:9999/hello "Content-Type:application/json; charset=utf-8" Name="gatapon"

これを簡単に訳すると、以下のようなことをしています。

localhost:9999/helloにPOSTメソッドでJSON形式のName="gatapon"を渡す。」

このコマンドを受け取ったサーバーの動きを見ていきます。

ファンクション:postHello() について

// 第一引数 "Content-Type:application/json; charset=utf-8"
// 第二引数 Name="gatapon"
func postHello(w rest.ResponseWriter, req *rest.Request) {
    input := postHelloInput{}
    err := req.DecodeJsonPayload(&input)

    if err != nil { // DecodeJsonPayload で検出されたエラーを返す
        rest.Error(w, err.Error(), http.StatusInternalServerError)
        return

DecodeJsonPayload

DecodeJsonPayloadで様々なバリデーションを行なっており、当てはまった場合はエラーを返す。

  • 文字列の終端まで読み込み、バイトスライス
  • 文字列が0の時のバリデーション
  • Json形式の文字列をパース:json.Unmarshal

便利なコンストラクタ:rest.NewApi()

NewApi()

NewApi()は3つの強力なメソッドを持っており、それらを使うことで艱難にAPIサーバーを立ち上げることができます。


api := NewApi()

api.Use()
api.SetApp()
api.MakeHandler()
  • api.Use => APIサーバーの環境に合わせて用意されたMiddlewareの設定ができる
    • DefaultDevStack : 開発時に利用するMiddleware群
    • DefaultProdStack : プロダクト時に利用するMiddleware群
    • DefaultCommonStack : どちらにしても一般的に利用するMiddleware群
  • api.SetApp => 主にrest.MakeRouterのrouterをセットするメソッド
  • api.MakeHandler()

感想

go-json-restを使えばとても簡単にRESTfullなAPIサーバーが作成できます。

パッケージを使えば、思ったより早く簡単なアプリが作成できそう。さらにGoの深淵を覗き込みたくなってきました。MakeHandlerメソッドは内容を理解するのには時間がかかりそうなので、スルー状態...

MakeHandler()

  • Useで指定したMiddlewareを取り出し、サーバで走らせる
  • http.Handlerの準備を行なっている

これらを行なっているそうですが、まだ私には難しかったです。少しずつ勉強していきます。

間違いがあればご指摘ください。

ソースコード

9
11
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
9
11