MartiniはGolangによる、モジュール形式のウェブアプリケーション/サービスを作成するパワフルなパッケージです。
Goをインストールし、GOPATHを設定した後、Martiniを始める最初の.go
ファイルを作りましょう。これをserver.go
とします。
package main
import "github.com/go-martini/martini"
func main() {
m := martini.Classic()
m.Get("/", func() string {
return "Hello world!"
})
m.Run()
}
そのあとで、Martini パッケージをインストールします。(go 1.1か、それ以上のバーションが必要です。)
go get github.com/go-martini/martini
インストールが完了したら、サーバを起動しましょう。
go run server.go
そうすればlocalhost:3000
でMartiniのサーバが起動します。
メーリングリストに入る
デモビデオをみる
Stackoverflowでmartini tagを使い質問する
GoDoc documentation
- 非常にシンプルに使用できる
- 押し付けがましくないデザイン
- 他のGolangパッケージとの協調性
- 素晴らしいパスマッチングとルーティング
- モジュラーデザイン - 機能性の付け外しが簡単
- たくさんの良いハンドラ/ミドルウェア
- 優れた 'すぐに使える' 機能たち
- http.HandlerFuncとの完全な互換性
さらに多くのミドルウェアとその機能について知りたいときは、martini-contrib オーガナイゼーションにあるリポジトリを確認してください。
立ち上げ、すぐ実行できるように、martini.Classic() はほとんどのウェブアプリケーションで機能する、標準的な機能を提供します。
m := martini.Classic()
// ... middleware and routing goes here
m.Run()
下記がmartini.Classic()が自動的に読み込む機能の一覧です。
- Request/Response Logging - martini.Logger
- Panic Recovery - martini.Recovery
- Static File serving - martini.Static
- Routing - martini.Router
ハンドラはMartiniのコアであり、存在意義でもあります。ハンドラには基本的に、呼び出し可能な全ての関数が適応できます。
m.Get("/", func() {
println("hello world")
})
もしハンドラが何かを返す場合、Martiniはその結果を現在のhttp.ResponseWriterにstringとして書き込みます。
m.Get("/", func() string {
return "hello world" // HTTP 200 : "hello world"
})
任意でステータスコードを返すこともできます。
m.Get("/", func() (int, string) {
return 418, "i'm a teapot" // HTTP 418 : "i'm a teapot"
})
ハンドラはリフレクションによって実行されます。Martiniはハンドラの引数内の依存関係を**依存性の注入(Dependency Injection)**を使って解決しています。これによって、Martiniはgolangのhttp.HandlerFunc
と完全な互換性を備えています。
ハンドラに引数を追加すると、Martiniは内部のサービスを検索し、依存性をtype assertionによって解決しようと試みます。
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
res.WriteHeader(200) // HTTP 200
})
martini.Classic()にはこれらのサービスが内包されています:
- *log.Logger - Martiniのためのグローバルなlogger.
- martini.Context - http request context.
- martini.Params -
map[string]string
型の、ルートマッチングによって検出されたパラメータ - martini.Routes - Route helper service.
- http.ResponseWriter - http Response writer interface.
- *http.Request - http Request.
Martiniでは、ルーティングはHTTPメソッドとURL-matching patternによって対になっており、それぞれが一つ以上のハンドラメソッドを持つことができます。
m.Get("/", func() {
// show something
})
m.Patch("/", func() {
// update something
})
m.Post("/", func() {
// create something
})
m.Put("/", func() {
// replace something
})
m.Delete("/", func() {
// destroy something
})
m.Options("/", func() {
// http options
})
m.NotFound(func() {
// handle 404
})
ルーティングはそれらの定義された順番に検索され、最初にマッチしたルーティングが呼ばれます。
名前付きパラメータを定義することもできます。これらのパラメータはmartini.Paramsサービスを通じてアクセスすることができます:
m.Get("/hello/:name", func(params martini.Params) string {
return "Hello " + params["name"]
})
ワイルドカードを使用することができます:
m.Get("/hello/**", func(params martini.Params) string {
return "Hello " + params["_1"]
})
正規表現も、このように使うことができます:
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
return fmt.Sprintf ("Hello %s", params["name"])
})
もっと正規表現の構文をしりたい場合は、Go documentation を見てください。
ハンドラは互いの上に積み重ねてることができます。これは、認証や承認処理の際に便利です:
m.Get("/secret", authorize, func() {
// this will execute as long as authorize doesn't write a response
})
ルーティンググループも、Groupメソッドを使用することで追加できます。
m.Group("/books", func(r martini.Router) {
r.Get("/:id", GetBooks)
r.Post("/new", NewBook)
r.Put("/update/:id", UpdateBook)
r.Delete("/delete/:id", DeleteBook)
})
ハンドラにミドルウェアを渡せるのと同じように、グループにもミドルウェアを渡すことができます:
m.Group("/books", func(r martini.Router) {
r.Get("/:id", GetBooks)
r.Post("/new", NewBook)
r.Put("/update/:id", UpdateBook)
r.Delete("/delete/:id", DeleteBook)
}, MyMiddleware1, MyMiddleware2)
サービスはハンドラの引数として注入されることで利用可能になるオブジェクトです。これらはグローバル、またはリクエストのレベルでマッピングすることができます。
Martiniのインスタンスはinject.Injectorのインターフェースを実装しています。なので、サービスをマッピングすることは簡単です:
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // the service will be available to all handlers as *MyDatabase
// ...
m.Run()
リクエストレベルでのマッピングはmartini.Contextを使い、ハンドラ内で行うことができます:
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
logger := &MyCustomLogger{req}
c.Map(logger) // mapped as *MyCustomLogger
}
サービスの最も強力なことの一つは、インターフェースにサービスをマッピングできる機能です。例えば、http.ResponseWriterを機能を追加して上書きしたい場合、このようにハンドラを書くことができます:
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
rw := NewSpecialResponseWriter(res)
c.MapTo(rw, (*http.ResponseWriter)(nil)) // override ResponseWriter with our wrapper ResponseWriter
}
martini.Classic() インスタンスは、自動的にルート直下の "public" ディレクトリ以下の静的ファイルを配信します。martini.Staticを追加することで、もっと多くのディレクトリを配信することもできます:
m.Use(martini.Static("assets")) // serve from the "assets" directory as well
ミドルウェア ハンドラは次に来るhttpリクエストとルーターの間に位置します。本質的には、その他のハンドラとの違いはありません。ミドルウェア ハンドラの追加はこのように行います:
m.Use(func() {
// do some middleware stuff
})
Handlers
関数を使えば、ミドルウェアスタックを完全に制御できます。これは以前に設定されている全てのハンドラを置き換えます:
m.Handlers(
Middleware1,
Middleware2,
Middleware3,
)
ミドルウェア ハンドラはロギング、認証、承認プロセス、セッション、gzipping、エラーページの表示、その他httpリクエストの前後で怒らなければならないような場合に素晴らしく効果を発揮します。
// validate an api key
m.Use(func(res http.ResponseWriter, req *http.Request) {
if req.Header.Get("X-API-KEY") != "secret123" {
res.WriteHeader(http.StatusUnauthorized)
}
})
Context.Next() は他のハンドラが実行されたことを取得するために使用する機能です。これはhttpリクエストのあとに実行したい任意の関数があるときに素晴らしく機能します:
// log before and after a request
m.Use(func(c martini.Context, log *log.Logger){
log.Println("before a request")
c.Next()
log.Println("after a request")
})
いくつかのMartiniのハンドラはdevelopment環境とproduction環境で別々の動作を提供するためにmartini.Env
グローバル変数を使用しています。Martiniサーバを本番環境にデプロイする際には、MARTINI_ENV=production
環境変数をセットすることをおすすめします。
martini-contribプロジェクトをみることから始めてください。もし望みのものがなければ、新しいリポジトリをオーガナイゼーションに追加するために、martini-contribチームのメンバーにコンタクトを取ってみてください。
- auth - Handlers for authentication.
- binding - Handler for mapping/validating a raw request into a structure.
- gzip - Handler for adding gzip compress to requests
- render - Handler that provides a service for easily rendering JSON and HTML templates.
- acceptlang - Handler for parsing the
Accept-Language
HTTP header. - sessions - Handler that provides a Session service.
- strip - URL Prefix stripping.
- method - HTTP method overriding via Header or form fields.
- secure - Implements a few quick security wins.
- encoder - Encoder service for rendering data in several formats and content negotiation.
- cors - Handler that enables CORS support.
- oauth2 - Handler that provides OAuth 2.0 login for Martini apps. Google Sign-in, Facebook Connect and Github login is supported.
Martiniのインスタンスはhttp.Handler
を実装しているので、既存のGoサーバ上でサブツリーを提供するのは簡単です。例えばこれは、Google App Engine上で動くMartiniアプリです:
package hello
import (
"net/http"
"github.com/go-martini/martini"
)
func init() {
m := martini.Classic()
m.Get("/", func() string {
return "Hello world!"
})
http.Handle("/", m)
}
MartiniのRun
関数はPORTとHOSTという環境変数を探し、その値を使用します。見つからない場合はlocalhost:3000がデフォルトで使用されます。もっと柔軟性をもとめるなら、martini.RunOnAddr
関数が役に立ちます:
m := martini.Classic()
// ...
log.Fatal(m.RunOnAddr(":8080"))
gin と fresh 両方がMartiniアプリケーションを自動リロードできます。
Martini本体は小さく、クリーンであるべきであり、ほとんどのコントリビューションはmartini-contrib オーガナイゼーション内で完結すべきですが、もしMartiniのコアにコントリビュートすることがあるなら、自由に行ってください。
Inspired by express and sinatra
Martini is obsessively designed by none other than the Code Gangsta