Go
rest
echo

Go の echo ってWebサーバーでサクッと REST しちゃう

Go言語勉強しながらWebサーバー立てたいなーどうしようかなーって思ってたときに

きっと色々候補はあるんだけど

labstack/echo


Echo is a fast :rocket: and unfancy micro web framework for Go.


っての見つけた。

Go言語そのものの勉強以外は最小限に抑えたいし、

RESTでjson返すだけならこれで十分かなって思った。

速いらしいし。


Echo の使い方

公式ドキュメントに大概載ってる。


インストール

go get github.com/labstack/echo

go get github.com/dgrijalva/jwt-go

一発でOK。


動かす


main.go

package main

import (
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"./handler"
)

func main() {
// Echoのインスタンス作る
e := echo.New()

// 全てのリクエストで差し込みたいミドルウェア(ログとか)はここ
e.Use(middleware.Logger())
e.Use(middleware.Recover())

// ルーティング
e.GET("/hello", handler.MainPage())

// サーバー起動
e.Start(":1323") //ポート番号指定してね
}



handler/handler.go

package handler

import (
"net/http"
"github.com/labstack/echo"
)

func MainPage() echo.HandlerFunc {
return func(c echo.Context) error { //c をいじって Request, Responseを色々する
return c.String(http.StatusOK, "Hello World")
}
}


go run main.go

http://localhost:1323/hello にアクセスします。

多分ファイル分けたくなるだろうから最初から分けておいた。

他のフレームワークとあんまり変わらないかな。簡単。

ルーティングで e.GET() って書いてるけど、

もちろん e.POST() とか e.PUT() とか書けばメソッドで分けれますよ。

ただ、他のフレームワークと違ってルーティングの文字列は前方一致のみみたい。

正規表現は多分使えないんじゃないかな。


Path parameter を使う

(2016/3/15 追記項目)

RESTと言えば Path parameter だよね。

リソースの場所を表さなきゃなんだから当然やね。


main.go

e.GET("/hello/:username", handle.MainPage())    //セミコロンの所がプレースホルダになる


って感じでセミコロン使ってプレースホルダを宣言しといて、

ハンドラの方で


handle.go



func MainPage() echo.HandlerFunc {
return func(c echo.Context) error {
username := c.Param("username") //プレースホルダusernameの値取り出し
return c.String(http.StatusOK, "Hello World " + username)
}
}


ってやるだけやね。

ちなみに c.Param("username") の所を c.P(0) みたいにインデックスで指定も出来るっぽい。

でもどうせプレースホルダ宣言するし、どういうときにインデックス使うかちょっとわかんない。

後クエリパラメータ(/hoge/?key=value みたいな、?付きのパラメータ)とか

フォームのデータとか送れるみたいだけど、

そっちもほとんど使い方一緒だから公式ドキュメントの該当ページ見てね。


Basic認証

認証はBasic認証のみ対応済み。

これも簡単。

main に


main.go

e.Use(interceptor.BasicAuth())


みたいなのを追加したら、

interceptor パッケージを作って、その中に


auth.go

package interceptor

import (
"github.com/labstack/echo/middleware"
"github.com/labstack/echo"
)

func BasicAuth() echo.MiddlewareFunc {
return middleware.BasicAuth(func(username string, password string, context echo.Context) (bool, error) {
if username == "joe" && password == "correct" {
return true,nil
}
return false,nil
})
}


usernamepassword の部分に Basic認証の情報が入ってくるので、

その値が正しいかどうかを判別します。

ココで true を返せば本来のリクエストされたハンドラへ処理がうつり、

false を返せば、401が返されます。

(@mztnnrt さんより、 コメントにて 2018/09/03 現在の方法をご指摘いただいた内容 へ修正しました!ありがとうございますありがとうございます!


個別のページで認証の有無を変えたい場合は?

さっきの方法では全ページにミドルウェアを挟んでしまうので、

認証が必要でないページを作りたいときに困ってしまう。

あるリクエストだけに特定のミドルウェアを挟みたいときは

e.GET() のところで


main.go

e.GET("/user/apps/:username", handle.MainPage(), interceptor.BasicAuth())


という感じで、ハンドラの後ろに足してあげるとOK。

公式ドキュメントでは「グループ機能制御出来るよ!」

って書いてあったけど良く分かんなかった。

また解決したら書き足すかも。


json の書き出し

json の出力も


handle.go



jsonMap := map[string]string{
"foo": "bar",
"hoge": "fuga",
}

return c.JSON(http.StatusOK, jsonMap)


みたいな感じで、c.Stringc.JSON にしてマップなりなんなり渡すだけ。

余裕やね。


CORS

json 出力できたら次はやっぱり CORS じゃんね。


main.go



e.Use(standard.WrapMiddleware(cors.New(cors.Options{
AllowedOrigins: []string{"http://example.com"},
}).Handler))


ミドルウェアとしてこれをはさむだけで OK っぽい。


echo を使ってみて。

他にもファイルアップロードとか websocket も使えるみたいだし、

簡単なデータのやりとりは一通りできる。

あと印象に残ってるのは、コードをちょっと読んでたら router の所に


// NOTE: Slow zone...


ってコメントが入ってた。

スピードを上げることを意識してコーディングしてるんだなーって思った。

Go自体速いし、大した影響はないと思うんだけどね。


2017/04/30 編集

shinriyo@github さんにインストール方法など、記事を書いた当時と変わっていた部分を

編集していただきました。


2018/09/03 編集

@mztnnrt さんに Basic 認証について、記事を書いた当時と変更されていた部分についてコメントより指摘いただき、修正いたしました。


2019/04/22 編集

@naka_kyon さんに メソッド名に関する編集リクエストをいただき、適用いたしました。