Negroni + Gorilla/Muxで簡単なサーバーアプリケーション作る

# Negroni + Gorilla/Muxで簡単なサーバーアプリケーション作る

使用するライブラリは以下のとおり
 - [Negroni](https://github.com/codegangsta/negroni)
 - [Gorilla/Mux](https://github.com/gorilla/mux)

## サンプルコード

作った機能としては、
 - GET "/" で名前の書き込みを依頼し
 - POST "/"で送信された名前を受け取り表示させる。
 - GET "/admin" でちょっとした認証機構


```go:main.go
package main

import (
    "fmt"
    "net/http"
    "html/template"

    "github.com/gorilla/mux"
    "github.com/codegangsta/negroni"
)

func main(){
    r := mux.NewRouter()

    // Root への処理
    r.HandleFunc("/", getRoot).Methods("GET")
    r.HandleFunc("/", postRoot).Methods("POST")

    // アドミン周りの処理
    authBase := mux.NewRouter()
    r.PathPrefix("/admin").Handler(negroni.New(
        negroni.NewRecovery(),
        negroni.NewLogger(),
        negroni.HandlerFunc(authenticate),
        negroni.Wrap(authBase)))
    auth := authBase.PathPrefix("/admin").Subrouter()
    auth.Path("/").HandlerFunc(getAdmin)


    n := negroni.Classic()
    n.UseHandler(r)
    n.Run(":3000")
}

func getRoot(w http.ResponseWriter, r *http.Request) {
    t := template.Must(template.ParseFiles("root.tmpl"))
    t.Execute(w, nil)
}

func postRoot(w http.ResponseWriter, r *http.Request) {
    name := r.FormValue("name")
    t := template.Must(template.ParseFiles("root.tmpl"))
    t.Execute(w, struct{Name string} {Name : name})
}

func getAdmin(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Authenticate Success!!")
}


func authenticate(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
    // ダメダメな実装例なので、真似ダメゼッタイ
    name := r.FormValue("name")
    if(name == "auth"){
        next(w,r)
    } else {
        fmt.Fprintf(w,"Please Authenticate!!")
    }

}
```



## Negroni についての解説

### Negroni の構造について

Negroni コード内に存在する重要な定義は、ほんの少ししか存在しません。

```go:negroni.go
// Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler.
// Negroni middleware is evaluated in the order that they are added to the stack using
// the Use and UseHandler methods.
type Negroni struct {
	middleware middleware
	handlers   []Handler
}

func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
	n.middleware.ServeHTTP(NewResponseWriter(rw), r)
}
```

まず、``negroni.Classci()``もしくは、``negroni.New()``を実行すると返されるNegroniインスタンスにフィールドは二つしか無く、ハンドラの配列とミドルウェアだけです。


### ハンドラって何やねん。

ハンドラとは、「ユーザーからの要求（GET /posts/ みたいなリクエスト）をどう処理して応答するか」を操作する何かの事。

まず、Golang には標準で``net/http``パッケージが用意されており、コレを使うだけで、以下のようにリクエストをハンドリングする事が出来ます。

```go:godocより引用
http.Handle("/foo", fooHandler)

http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})

log.Fatal(http.ListenAndServe(":8080", nil))
```

このことを踏まえた上で、Negroni はこの``http/net``と互換性を持たせるように設計されており、``http/net``のハンドラを、Negroni のハンドラとして利用することが出来るようになっています。それを実現しているのがNegroni.go の以下の部分。

```Negroni.go
type Handler interface {
	ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
}

// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.
// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.
type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	h(rw, r, next)
}
```



### ミドルウェアって何やねん！？

この概念を理解するのに結構時間がかかりました。参考文献にも同じ図が載っていますが、この図が全てだと思います。
https://mattstauffer.co/blog/laravel-5.0-middleware-filter-style#what-is-middleware
![オニオン](http://stackphp.com/img/onion.png)

コアロジックであるApp に対して、前処理と後処理を提供するものが、ミドルウェアです。セッション管理や認証などがそれに当たります。ではコードを見てみましょう。

```go:negroni.go
type middleware struct {
	handler Handler
	next    *middleware
}
```

middleware の定義はたったこれだけで、実行するハンドラと、次に実行するミドルウェアへのポインタが定義されています。``negroni.Classic``を呼び出すと、外側から順に、Recovery、Logging、Staticのミドルウェアが自動的に登録され、``negroni.New``を呼び出すと、ミドルウェアが一つもない状態でNegroniインスタンスが作成されます。

また、``n.Use``を用いると、自作のミドルウェアを登録することが出来ます。（セッション管理とか認証系とか自作するか別ライブラリを使う必要がある）　useを使ってミドルウェアを登録する時、たまねぎ構造の最も内側にミドルウェアが登録されます。

公式README曰く、以下の形で定義してねって書いてあるので、これに準拠しましょう。

```go:README.md
func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  // do some stuff before
  next(rw, r)
  // do some stuff after
}
```




## 使ってみた雑感
Martini のREADME.md に**The martini framework is no longer maintained.**と記述されているので、これからはNegroni/GorilalMux の組み合わせが主流になるのかもしれない。

けど、色々と面倒くさいところが多いし、開発速度を重視する人には向いていないかも……。

**ここもっと良い書き方出来る**とか**ココ間違ってる**等のご指摘がありましたら、いただけると幸いです。


## 参考資料
 - [https://gist.github.com/danesparza/eb3a63ab55a7cd33923e](https://gist.github.com/danesparza/eb3a63ab55a7cd33923e)
 - [Negroni and Gorilla Mux with Middleware example - golang
Raw](https://gist.github.com/pagreczner/227913794e096953972c)
 - [Go言語でServer作る時に必要な知識メモ](http://qiita.com/awakia/items/ef8978fc33ffb1d27460)