LoginSignup
17
14

More than 5 years have passed since last update.

Go製WAFのuconを触ってみた

Last updated at Posted at 2016-05-13

ucon

仕事で使うことになったので触ってみました。
とりあえず基本機能だけです。
https://github.com/favclip/ucon

まとめ

  • handlerの引数はBubble.Argumentsに設定されているものが使用される
  • handlerの型がinterface{}なので気をつけよう
  • reflectの知識が前提なのでreflect好きな人向け
  • 私みたいな一般人は大人しくGin,Echo,Beegoあたりを使うのがいいかも

基本

hello.go
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を使う

use_context.go
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を取得する

get_routing_parameter.go
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のようです。

use_requestObjectMapper.go
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のようです。

use_responseMapper.go
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を触ってみようと思います。

17
14
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
17
14