はじめに
本記事では、Go言語で代表的なWebフレームワークであるechoについて、基本的な利用方法についてまとめます。
公式ガイドの内容から抜粋して記載します。
echoについて
echoは高パフォーマンス、拡張可能、軽量なWebフレームワークです。次のような特徴を持っています。
echoの特徴
echoフレームワークの特徴は公式ページで以下のように記載されています。
- 最適化されたルーター
- 高度に最適化されたHTTPルーターで、動的メモリの割り当てがなく、経路の優先順位をスマートに決定します。
- 高度に最適化されたHTTPルーターで、動的メモリの割り当てがなく、経路の優先順位をスマートに決定します。
- 拡張性がある
- 頑健でスケーラブルなRESTful APIを構築し、簡単にグループにまとめることができます。
- 頑健でスケーラブルなRESTful APIを構築し、簡単にグループにまとめることができます。
- 自動TLS
- Let’s EncryptからTLS証明書を自動的にインストールします。
- Let’s EncryptからTLS証明書を自動的にインストールします。
- HTTP/2
- HTTP/2をサポートすることでスピードを改善し、より良いユーザ体験を提供します。
- HTTP/2をサポートすることでスピードを改善し、より良いユーザ体験を提供します。
- ミドルウェア
- 多くの組み込みミドルウェアを利用でき、独自のミドルウェアを定義する事もできます。ミドルウェアはルート(root)、グループ、ルート(route)レベルで設定できます。
- 多くの組み込みミドルウェアを利用でき、独自のミドルウェアを定義する事もできます。ミドルウェアはルート(root)、グループ、ルート(route)レベルで設定できます。
- Data Binding
- JSON、XML、form-dataなど、HTTPリクエストペイロードのデータバインディング。
- JSON、XML、form-dataなど、HTTPリクエストペイロードのデータバインディング。
- Data Rendering
- JSON、XML、HTML、File、Attachment、Inline Stream、Blobなど、様々なHTTPレスポンスを送信するAPIです。
- JSON、XML、HTML、File、Attachment、Inline Stream、Blobなど、様々なHTTPレスポンスを送信するAPIです。
- Templates
- 任意のテンプレートエンジンを使ったテンプレートレンダリング。
- 任意のテンプレートエンジンを使ったテンプレートレンダリング。
- 拡張可能
- カスタマイズされたセントラルHTTPエラーハンドリング。容易に拡張可能なAPI。
echoの使い方
公式ガイドの内容を抜粋して実装を進めていきます。
インストール
EchoをインストールするにはGO v1.13以上が必要です。Go v1.12ではサポートが限られており、一部のミドルウェアが利用できません。プロジェクトフォルダが$GOPATHの外にあることを確認してください。
$ mkdir myapp && cd myapp
$ go mod init myapp
$ go get github.com/labstack/echo/v4
動作させる
まずは簡易的に動作させてみます。以下の手順で簡単にAPIを作成することができます。
Echo#New() (e *Echo)
でインスタンスを作成Echo#GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route
でルーティング設定Echo#Start(address string) error
でサーバーをスタート
下記の例では、パス/
にGETでアクセスするとHello World!
の文字列を返却するようにルーティング設定しています。実際にブラウザでhttp://localhost:1323/にアクセスするとHello, World!
の文字が表示され、簡易的なAPIサーバとして動作していることがわかります。
package main
import (
"net/http"
"github.com/labstack/echo"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":1323"))
}
Routing
上記の項目で既に利用しましたが、echoではEcho.Any(path string, h Handler)
の形式で全てのHTTPメソッドのハンドラーを登録することができます。
// Handlers
func createUser(c echo.Context) error {
}
func findUser(c echo.Context) error {
}
func updateUser(c echo.Context) error {
}
func deleteUser(c echo.Context) error {
}
// Routes
e.POST("/users", createUser)
e.GET("/users", findUser)
e.PUT("/users", updateUser)
e.DELETE("/users", deleteUser)
また、Echo#Group(prefix string, m ...Middleware) *Group
を利用して、共通のプレフィックスを持つルートをグループ化する事もできます。下記の例では共通のプレフィックス/admin
を持つルートをグループ化し、そのグループに対してルーティング設定しています。そのため、/admin/users/new
と/admin/users/:id
がルートとして設定されます。
g := e.Group("/admin")
g.GET("/users/new", createUser)
g.GET("/users/:id", findUser)
Path Parameters
ルーティング設定に:name
の形式でパスを設定すると、パスパラメータとして登録することができます。パスパラメータを受け取る際は、Context#Param(name string) string
を利用します。
下記の例では、ブラウザでhttp://localhost:1323/users/Joe
にアクセスすると、Joe
の文字が表示されます。
e.GET("/users/:id", func(c echo.Context) error {
name := c.Param("id")
return c.String(http.StatusOK, id)
})
Query Parameters
クエリパラメータを受け取るには、Context#QueryParam(name string)
を利用します。
下記の例では、ブラウザでhttp://localhost:1323/show?team=x-men&member=wolverine
にアクセスすると、team:x-men, member:wolverine
と表示されます。
//e.GET("/show", show)
func show(c echo.Context) error {
// Get team and member from the query string
team := c.QueryParam("team")
member := c.QueryParam("member")
return c.String(http.StatusOK, "team:" + team + ", member:" + member)
}
Form application/x-www-form-urlencoded
Content-Typeがapplication/x-www-form-urlencoded
のデータを受け取るには、Context#FormValue(name string)
を利用します。
// e.POST("/save", save)
func save(c echo.Context) error {
// Get name and email
name := c.FormValue("name")
email := c.FormValue("email")
return c.String(http.StatusOK, "name:" + name + ", email:" + email)
}
次のコマンドを実行すると、受け取れていることが確認できます。
$ curl -F "name=Joe Smith" -F "email=joe@labstack.com" http://localhost:1323/save
// => name:Joe Smith, email:joe@labstack.com
Handling Request
Context#Bind(i interface{})
を用いることで、json
、xml
、form
、query
などのペイロードを、リクエストヘッダーのContent-Type
に基づいてGoの構造体にバインドすることができます。
また、Context#JSON(code int, i interface{})
や、Context#XML(code int, i interface{})
を利用することで、JSON
およびXML
にエンコードしてレスポンスコードと一緒にレスポンスを送信することができます。
type User struct {
Name string `json:"name" xml:"name" form:"name" query:"name"`
Email string `json:"email" xml:"email" form:"email" query:"email"`
}
e.POST("/users", func(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
return c.JSON(http.StatusCreated, u)
// or
// return c.XML(http.StatusCreated, u)
})
Static Content
静的コンテンツを提供するには、Echo#Static(prefix, root string)
を利用します。
下記の例では、パスが/static/*
のassetsディレクトリから任意のファイルを提供します。例えば、/static/js/main.js
へのリクエストは、assets/js/main.js
ファイルをフェッチして提供します。
e.Static("/static", "assets")
また、Echo#File(path, file string)
を利用することで静的ファイルを提供できます。
下記の例では、パス/
にアクセスするとpublic/index.html
を返却します。
e.File("/", "public/index.html")
Middleware
ミドルウェアとは、HTTPリクエスト・レスポンスサイクルの中で連鎖している機能で、Echo#Context
へのアクセス権を持ち、特定のアクションを実行するために使用されます。例えば、すべてのリクエストをログに記録したり、リクエスト数を制限したりすることができます。
ハンドラは、すべてのミドルウェアの実行が終了した後、最後に処理されます。
また、Echo#Use()
を使用して登録されたミドルウェアは、Echo#Use()
が呼び出された後に登録されたパスに対してのみ実行されます。
下記の例では、middleware.Logger()
とmiddleware.Recover()
はRoot Levelで設定しているため、全てのリクエストに対して適用されます。一方で、middleware.BasicAuth()
はグループe.Group("/admin")
に対して設定しているため、/admin
から始まるリクエストにのみ適用されます。
最後のtrack
変数は、自作したカスタムミドルウェアを代入しています。
// Root level middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Group level middleware
g := e.Group("/admin")
g.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if username == "joe" && password == "secret" {
return true, nil
}
return false, nil
}))
// Route level middleware
track := func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
println("request to /users")
return next(c)
}
}
e.GET("/users", func(c echo.Context) error {
return c.String(http.StatusOK, "/users")
}, track)
まとめ
本記事では公式ガイドに沿ってechoの基本的な利用方法についてまとめました。
様々な種類のあるmiddlewareの使い方など、echoの詳しい利用方法についても今後記事にできればと思います。
閲覧いただきありがとうございました。
他のパッケージやGo言語における基本的な利用方法についても記事を書いていますので、もし興味がありましたらご参照ください。
・【Go言語】ファイル/ディレクトリ操作方法 – 基本
・【Go言語】database/sqlパッケージによるデータベース操作入門 – sqlite3
・【Go言語】encoding/jsonパッケージでJSONをパースする
・【Go言語】net/httpパッケージでAPIリクエストを送信する
コメント