ucon
仕事で使うことになったので触ってみました。
とりあえず基本機能だけです。
https://github.com/favclip/ucon
まとめ
- handlerの引数は
Bubble.Arguments
に設定されているものが使用される - handlerの型が
interface{}
なので気をつけよう - reflectの知識が前提なのでreflect好きな人向け
- 私みたいな一般人は大人しく
Gin
,Echo
,Beego
あたりを使うのがいいかも
基本
package main
import (
"net/http"
"github.com/favclip/ucon"
)
func init() {
// register middleware
ucon.Middleware(ucon.HTTPRWDI())
ucon.HandleFunc("GET", "/hello", getHello)
http.Handle("/", ucon.DefaultMux) // appengine向け
// ucon.ListenAndServe(":8080") 普通のサーバ向け
}
func getHello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello"))
}
Point:
ucon.Middleware(ucon.HTTPRWDI())
を忘れるとエラーとなります。
なぜなら、ucon.HTTPRWDI()
を実行することでhandlerにw http.ResponseWriter, r *http.Request
が渡されるため。
context.Contextを使う
package main
import (
"net/http"
"github.com/favclip/ucon"
"golang.org/x/net/context"
)
func init() {
// register middleware
ucon.Middleware(ucon.HTTPRWDI())
ucon.Middleware(ucon.NetContextDI()) // 追加
ucon.HandleFunc("GET", "/hello", getHello)
http.Handle("/", ucon.DefaultMux)
// ucon.ListenAndServe(":8080")
}
func getHello(w http.ResponseWriter, r *http.Request, ctx context.Context) {
w.Write([]byte("Hello"))
}
Point:
上記の通り、ucon.Middleware(ucon.NetContextDI())
を追加する。理由は先ほどと同様。
そうすればhandler内でctx context.Context
などとして使用できる。
routing parameterを取得する
package main
import (
"net/http"
"github.com/favclip/ucon"
)
func init() {
// register middleware
ucon.Middleware(ucon.HTTPRWDI())
ucon.Middleware(ucon.NetContextDI())
ucon.HandleFunc("GET", "/hello/{id}", getHello)
http.Handle("/", ucon.DefaultMux)
// ucon.ListenAndServe(":8080")
}
func getHello(w http.ResponseWriter, r *http.Request, ctx context.Context) {
params := ctx.Value(ucon.PathParameterKey).(map[string]string)
id := params["id"]
w.Write([]byte(fmt.Sprintf("Hello, No.%s.", id)))
}
Point:
routing parameterの指定は{id}
のように{}
でくくらなければなりません。(内部で正規表現を使用しているため)
取得は、まずctx.Value(ucon.PathParameterKey).(map[string]string)
でparameter全てを取ってきます。
そこから{}
でくくった文字列をmapのkeyに指定します。
ucon.RequestObjectMapper()
requestのbodyを自動的にstructに変換するmiddlewareのようです。
package main
import (
"net/http"
"github.com/favclip/ucon"
)
type Hello struct {
msg string `json:"msg"`
name string `json:"name"`
}
func init() {
// register middleware
ucon.Middleware(ucon.HTTPRWDI())
ucon.Middleware(ucon.NetContextDI())
ucon.Middleware(ucon.RequestObjectMapper()) // 追加
ucon.HandleFunc("POST", "/hello/new", getHello)
http.Handle("/", ucon.DefaultMux)
// ucon.ListenAndServe(":8080")
}
func postHello(w http.ResponseWriter, r *http.Request, ctx context.Context, hello *Hello) {
err := json.NewEncoder(w).Encode(hello)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
Point:
ucon.Middleware(ucon.RequestObjectMapper())
を忘れるとエラーとなります。
parseしたいstructを引数に指定するだけでOK。なお、Hello
ではなく*Hello
とPoninterを指定する必要があります。
ucon.ResponseMapper()
responseのbodyを自動的にstructからjsonに変換するmiddlewareのようです。
package main
import (
"net/http"
"github.com/favclip/ucon"
)
type Hello struct {
msg string `json:"msg"`
name string `json:"name"`
}
func init() {
// register middleware
ucon.Middleware(ucon.HTTPRWDI())
ucon.Middleware(ucon.NetContextDI())
ucon.Middleware(ucon.RequestObjectMapper())
ucon.Middleware(ucon.ResponseMapper()) // 追加
ucon.HandleFunc("POST", "/hello/{id}", getHello)
http.Handle("/", ucon.DefaultMux)
// ucon.ListenAndServe(":8080")
}
func getHello(w http.ResponseWriter, r *http.Request, ctx context.Context) *Hello {
return &Hello{
msg: "Hello",
name: "rglay",
}
}
Point:
ucon.Middleware(ucon.ResponseMapper())
を忘れるとエラーとなります。
parseしたいstructをreturnするだけでOK。なお、Hello
ではなく*Hello
とPoninterを指定する必要があります。
ucon.HandleFunc
はhandlerがinterface{}
であることを許容するため出来る技かな、と思いました。
middleware
公式のREADMEにサンプルがあるのでそれをみてください。
handlerの引数で使う場合は、Bubble.Arguments
に設定することを忘れずに!!
大事なことなので何度でも言います!!
次回
次回はswaggerのpluginを触ってみようと思います。