Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
357 lines (279 sloc) 15 KB

Martini wercker statusGoDoc

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 オーガナイゼーションにあるリポジトリを確認してください。

目次(Table of Contents)

Classic Martini

立ち上げ、すぐ実行できるように、martini.Classic() はほとんどのウェブアプリケーションで機能する、標準的な機能を提供します。

  m := martini.Classic()
  // ... middleware and routing goes here
  m.Run()

下記がmartini.Classic()が自動的に読み込む機能の一覧です。

ハンドラ

ハンドラはMartiniのコアであり、存在意義でもあります。ハンドラには基本的に、呼び出し可能な全ての関数が適応できます。

m.Get("/", func() {
  println("hello world")
})

Return Values

もしハンドラが何かを返す場合、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"
})

Service Injection

ハンドラはリフレクションによって実行されます。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()にはこれらのサービスが内包されています:

ルーティング

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)

サービス

サービスはハンドラの引数として注入されることで利用可能になるオブジェクトです。これらはグローバル、またはリクエストのレベルでマッピングすることができます。

Global Mapping

Martiniのインスタンスはinject.Injectorのインターフェースを実装しています。なので、サービスをマッピングすることは簡単です:

db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // the service will be available to all handlers as *MyDatabase
// ...
m.Run()

Request-Level Mapping

リクエストレベルでのマッピングはmartini.Contextを使い、ハンドラ内で行うことができます:

func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // mapped as *MyCustomLogger
}

Mapping values to Interfaces

サービスの最も強力なことの一つは、インターフェースにサービスをマッピングできる機能です。例えば、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)
  }
})

Next()

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 Env

いくつかのMartiniのハンドラはdevelopment環境とproduction環境で別々の動作を提供するためにmartini.Envグローバル変数を使用しています。Martiniサーバを本番環境にデプロイする際には、MARTINI_ENV=production環境変数をセットすることをおすすめします。

FAQ

Middlewareを見つけるには?

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"))

Live code reload?

ginfresh 両方がMartiniアプリケーションを自動リロードできます。

Contributing

Martini本体は小さく、クリーンであるべきであり、ほとんどのコントリビューションはmartini-contrib オーガナイゼーション内で完結すべきですが、もしMartiniのコアにコントリビュートすることがあるなら、自由に行ってください。

About

Inspired by express and sinatra

Martini is obsessively designed by none other than the Code Gangsta

You can’t perform that action at this time.