Full Code of go-martini/martini for AI

master 22fa46961aab cached
32 files
216.6 KB
65.2k tokens
159 symbols
1 requests
Download .txt
Showing preview only (227K chars total). Download the full file or copy to clipboard to get everything.
Repository: go-martini/martini
Branch: master
Commit: 22fa46961aab
Files: 32
Total size: 216.6 KB

Directory structure:
gitextract_1zcxk7ip/

├── .gitignore
├── Godeps/
│   └── Godeps.json
├── LICENSE
├── README.md
├── env.go
├── env_test.go
├── go_version.go
├── logger.go
├── logger_test.go
├── martini.go
├── martini_test.go
├── recovery.go
├── recovery_test.go
├── response_writer.go
├── response_writer_test.go
├── return_handler.go
├── router.go
├── router_test.go
├── static.go
├── static_test.go
├── translations/
│   ├── README_de_DE.md
│   ├── README_es_ES.md
│   ├── README_fr_FR.md
│   ├── README_ja_JP.md
│   ├── README_ko_kr.md
│   ├── README_pl_PL.md
│   ├── README_pt_br.md
│   ├── README_ru_RU.md
│   ├── README_tr_TR.md
│   ├── README_zh_cn.md
│   └── README_zh_tw.md
└── wercker.yml

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test

/.godeps
/.envrc

# Godeps
Godeps/_workspace
Godeps/Readme

### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

.idea/

## File-based project format:
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties


================================================
FILE: Godeps/Godeps.json
================================================
{
	"ImportPath": "github.com/go-martini/martini",
	"GoVersion": "go1.4.2",
	"Deps": [
		{
			"ImportPath": "github.com/codegangsta/inject",
			"Comment": "v1.0-rc1-10-g33e0aa1",
			"Rev": "33e0aa1cb7c019ccc3fbe049a8262a6403d30504"
		}
	]
}


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 Jeremy Saenz

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

### **NOTE:** The martini framework is no longer maintained.

Martini is a powerful package for quickly writing modular web applications/services in Golang.

Language Translations:
* [繁體中文](translations/README_zh_tw.md)
* [简体中文](translations/README_zh_cn.md)
* [Português Brasileiro (pt_BR)](translations/README_pt_br.md)
* [Español](translations/README_es_ES.md)
* [한국어 번역](translations/README_ko_kr.md)
* [Русский](translations/README_ru_RU.md)
* [日本語](translations/README_ja_JP.md)
* [French](translations/README_fr_FR.md)
* [Turkish](translations/README_tr_TR.md)
* [German](translations/README_de_DE.md)
* [Polski](translations/README_pl_PL.md)

## Getting Started

After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello world!"
  })
  m.Run()
}
~~~

Then install the Martini package (**go 1.1** or greater is required):
~~~
go get github.com/go-martini/martini
~~~

Then run your server:
~~~
go run server.go
~~~

You will now have a Martini webserver running on `localhost:3000`.

## Getting Help

Join the [Mailing list](https://groups.google.com/forum/#!forum/martini-go)

Watch the [Demo Video](http://martini.codegangsta.io/#demo)

Ask questions on Stackoverflow using the [martini tag](http://stackoverflow.com/questions/tagged/martini)

GoDoc [documentation](http://godoc.org/github.com/go-martini/martini)


## Features
* Extremely simple to use.
* Non-intrusive design.
* Plays nice with other Golang packages.
* Awesome path matching and routing.
* Modular design - Easy to add functionality, easy to rip stuff out.
* Lots of good handlers/middlewares to use.
* Great 'out of the box' feature set.
* **Fully compatible with the [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc) interface.**
* Default document serving (e.g., for serving AngularJS apps in HTML5 mode).

## More Middleware
For more middleware and functionality, check out the repositories in the  [martini-contrib](https://github.com/martini-contrib) organization.

## Table of Contents
* [Classic Martini](#classic-martini)
  * [Handlers](#handlers)
  * [Routing](#routing)
  * [Services](#services)
  * [Serving Static Files](#serving-static-files)
* [Middleware Handlers](#middleware-handlers)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
To get up and running quickly, [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) provides some reasonable defaults that work well for most web applications:
~~~ go
  m := martini.Classic()
  // ... middleware and routing goes here
  m.Run()
~~~

Below is some of the functionality [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) pulls in automatically:
  * Request/Response Logging - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Static File serving - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Routing - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Handlers
Handlers are the heart and soul of Martini. A handler is basically any kind of callable function:
~~~ go
m.Get("/", func() {
  println("hello world")
})
~~~

#### Return Values
If a handler returns something, Martini will write the result to the current [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) as a string:
~~~ go
m.Get("/", func() string {
  return "hello world" // HTTP 200 : "hello world"
})
~~~

You can also optionally return a status code:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "i'm a teapot" // HTTP 418 : "i'm a teapot"
})
~~~

#### Service Injection
Handlers are invoked via reflection. Martini makes use of *Dependency Injection* to resolve dependencies in a Handlers argument list. **This makes Martini completely  compatible with golang's `http.HandlerFunc` interface.**

If you add an argument to your Handler, Martini will search its list of services and attempt to resolve the dependency via type assertion:
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
  res.WriteHeader(200) // HTTP 200
})
~~~

The following services are included with [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):
  * [*log.Logger](http://godoc.org/log#Logger) - Global logger for Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request context.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` of named params found by route matching.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Route helper service.
  * [martini.Route](http://godoc.org/github.com/go-martini/martini#Route) - Current active route.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response writer interface.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request.

### Routing
In Martini, a route is an HTTP method paired with a URL-matching pattern.
Each route can take one or more handler methods:
~~~ go
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
})
~~~

Routes are matched in the order they are defined. The first route that
matches the request is invoked.

Route patterns may include named parameters, accessible via the [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) service:
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

Routes can be matched with globs:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

Regular expressions can be used as well:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
Take a look at the [Go documentation](http://golang.org/pkg/regexp/syntax/) for more info about regular expressions syntax .

Route handlers can be stacked on top of each other, which is useful for things like authentication and authorization:
~~~ go
m.Get("/secret", authorize, func() {
  // this will execute as long as authorize doesn't write a response
})
~~~

Route groups can be added too using the Group method.
~~~ go
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)
})
~~~

Just like you can pass middlewares to a handler you can pass middlewares to groups.
~~~ go
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)
~~~

### Services
Services are objects that are available to be injected into a Handler's argument list. You can map a service on a *Global* or *Request* level.

#### Global Mapping
A Martini instance implements the inject.Injector interface, so mapping a service is easy:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // the service will be available to all handlers as *MyDatabase
// ...
m.Run()
~~~

#### Request-Level Mapping
Mapping on the request level can be done in a handler via [martini.Context](http://godoc.org/github.com/go-martini/martini#Context):
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // mapped as *MyCustomLogger
}
~~~

#### Mapping values to Interfaces
One of the most powerful parts about services is the ability to map a service to an interface. For instance, if you wanted to override the [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) with an object that wrapped it and performed extra operations, you can write the following handler:
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // override ResponseWriter with our wrapper ResponseWriter
}
~~~

### Serving Static Files
A [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) instance automatically serves static files from the "public" directory in the root of your server.
You can serve from more directories by adding more [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) handlers.
~~~ go
m.Use(martini.Static("assets")) // serve from the "assets" directory as well
~~~

#### Serving a Default Document
You can specify the URL of a local file to serve when the requested URL is not
found. You can also specify an exclusion prefix so that certain URLs are ignored.
This is useful for servers that serve both static files and have additional
handlers defined (e.g., REST API). When doing so, it's useful to define the
static handler as a part of the NotFound chain.

The following example serves the `/index.html` file whenever any URL is
requested that does not match any local file and does not start with `/api/v`:
~~~ go
static := martini.Static("assets", martini.StaticOptions{Fallback: "/index.html", Exclude: "/api/v"})
m.NotFound(static, http.NotFound)
~~~

## Middleware Handlers
Middleware Handlers sit between the incoming http request and the router. In essence they are no different than any other Handler in Martini. You can add a middleware handler to the stack like so:
~~~ go
m.Use(func() {
  // do some middleware stuff
})
~~~

You can have full control over the middleware stack with the `Handlers` function. This will replace any handlers that have been previously set:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

Middleware Handlers work really well for things like logging, authorization, authentication, sessions, gzipping, error pages and any other operations that must happen before or after an http request:
~~~ go
// 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://godoc.org/github.com/go-martini/martini#Context) is an optional function that Middleware Handlers can call to yield the until after the other Handlers have been executed. This works really well for any operations that must happen after an http request:
~~~ go
// 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

Some Martini handlers make use of the `martini.Env` global variable to provide special functionality for development environments vs production environments. It is recommended that the `MARTINI_ENV=production` environment variable to be set when deploying a Martini server into a production environment.

## FAQ

### Where do I find middleware X?

Start by looking in the [martini-contrib](https://github.com/martini-contrib) projects. If it is not there feel free to contact a martini-contrib team member about adding a new repo to the organization.

* [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler for parsing the `Accept-Language` HTTP header.
* [accessflags](https://github.com/martini-contrib/accessflags) - Handler to enable Access Control.
* [auth](https://github.com/martini-contrib/auth) - Handlers for authentication.
* [binding](https://github.com/martini-contrib/binding) - Handler for mapping/validating a raw request into a structure.
* [cors](https://github.com/martini-contrib/cors) - Handler that enables CORS support.
* [csrf](https://github.com/martini-contrib/csrf) - CSRF protection for applications
* [encoder](https://github.com/martini-contrib/encoder) - Encoder service for rendering data in several formats and content negotiation.
* [gzip](https://github.com/martini-contrib/gzip) - Handler for adding gzip compress to requests
* [gorelic](https://github.com/martini-contrib/gorelic) - NewRelic middleware
* [logstasher](https://github.com/martini-contrib/logstasher) - Middleware that prints logstash-compatible JSON 
* [method](https://github.com/martini-contrib/method) - HTTP method overriding via Header or form fields.
* [oauth2](https://github.com/martini-contrib/oauth2) - Handler that provides OAuth 2.0 login for Martini apps. Google Sign-in, Facebook Connect and Github login is supported.
* [permissions2](https://github.com/xyproto/permissions2) - Handler for keeping track of users, login states and permissions.
* [render](https://github.com/martini-contrib/render) - Handler that provides a service for easily rendering JSON and HTML templates.
* [secure](https://github.com/martini-contrib/secure) - Implements a few quick security wins.
* [sessions](https://github.com/martini-contrib/sessions) - Handler that provides a Session service.
* [sessionauth](https://github.com/martini-contrib/sessionauth) - Handler that provides a simple way to make routes require a login, and to handle user logins in the session
* [strict](https://github.com/martini-contrib/strict) - Strict Mode 
* [strip](https://github.com/martini-contrib/strip) - URL Prefix stripping.
* [staticbin](https://github.com/martini-contrib/staticbin) - Handler for serving static files from binary data
* [throttle](https://github.com/martini-contrib/throttle) - Request rate throttling middleware.
* [vauth](https://github.com/rafecolton/vauth) - Handlers for vender webhook authentication (currently GitHub and TravisCI)
* [web](https://github.com/martini-contrib/web) - hoisie web.go's Context

### How do I integrate with existing servers?

A Martini instance implements `http.Handler`, so it can easily be used to serve subtrees
on existing Go servers. For example this is a working Martini app for Google App Engine:

~~~ go
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)
}
~~~

### How do I change the port/host?

Martini's `Run` function looks for the PORT and HOST environment variables and uses those. Otherwise Martini will default to localhost:3000.
To have more flexibility over port and host, use the `martini.RunOnAddr` function instead.

~~~ go
  m := martini.Classic()
  // ...
  m.RunOnAddr(":8080")
~~~

### Live code reload?

[gin](https://github.com/codegangsta/gin) and [fresh](https://github.com/pilu/fresh) both live reload martini apps.

## Contributing
Martini is meant to be kept tiny and clean. Most contributions should end up in a repository in the [martini-contrib](https://github.com/martini-contrib) organization. If you do have a contribution for the core of Martini feel free to put up a Pull Request.

## License
Martini is distributed by The MIT License, see LICENSE

## About

Inspired by [express](https://github.com/visionmedia/express) and [sinatra](https://github.com/sinatra/sinatra)

Martini is obsessively designed by none other than the [Code Gangsta](http://codegangsta.io/)


================================================
FILE: env.go
================================================
package martini

import (
	"os"
)

// Envs
const (
	Dev  string = "development"
	Prod string = "production"
	Test string = "test"
)

// Env is the environment that Martini is executing in. The MARTINI_ENV is read on initialization to set this variable.
var Env = Dev
var Root string

func setENV(e string) {
	if len(e) > 0 {
		Env = e
	}
}

func init() {
	setENV(os.Getenv("MARTINI_ENV"))
	var err error
	Root, err = os.Getwd()
	if err != nil {
		panic(err)
	}
}


================================================
FILE: env_test.go
================================================
package martini

import (
	"testing"
)

func Test_SetENV(t *testing.T) {
	tests := []struct {
		in  string
		out string
	}{
		{"", "development"},
		{"not_development", "not_development"},
	}

	for _, test := range tests {
		setENV(test.in)
		if Env != test.out {
			expect(t, Env, test.out)
		}
	}
}

func Test_Root(t *testing.T) {
	if len(Root) == 0 {
		t.Errorf("Expected root path will be set")
	}
}


================================================
FILE: go_version.go
================================================
// +build !go1.1

package martini

func MartiniDoesNotSupportGo1Point0() {
	"Martini requires Go 1.1 or greater."
}


================================================
FILE: logger.go
================================================
package martini

import (
	"log"
	"net/http"
	"time"
)

// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
func Logger() Handler {
	return func(res http.ResponseWriter, req *http.Request, c Context, log *log.Logger) {
		start := time.Now()

		addr := req.Header.Get("X-Real-IP")
		if addr == "" {
			addr = req.Header.Get("X-Forwarded-For")
			if addr == "" {
				addr = req.RemoteAddr
			}
		}

		log.Printf("Started %s %s for %s", req.Method, req.URL.Path, addr)

		rw := res.(ResponseWriter)
		c.Next()

		log.Printf("Completed %v %s in %v\n", rw.Status(), http.StatusText(rw.Status()), time.Since(start))
	}
}


================================================
FILE: logger_test.go
================================================
package martini

import (
	"bytes"
	"log"
	"net/http"
	"net/http/httptest"
	"testing"
)

func Test_Logger(t *testing.T) {
	buff := bytes.NewBufferString("")
	recorder := httptest.NewRecorder()

	m := New()
	// replace log for testing
	m.Map(log.New(buff, "[martini] ", 0))
	m.Use(Logger())
	m.Use(func(res http.ResponseWriter) {
		res.WriteHeader(http.StatusNotFound)
	})

	req, err := http.NewRequest("GET", "http://localhost:3000/foobar", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(recorder, req)
	expect(t, recorder.Code, http.StatusNotFound)
	refute(t, len(buff.String()), 0)
}


================================================
FILE: martini.go
================================================
// Package martini is a powerful package for quickly writing modular web applications/services in Golang.
//
// For a full guide visit http://github.com/go-martini/martini
//
//  package main
//
//  import "github.com/go-martini/martini"
//
//  func main() {
//    m := martini.Classic()
//
//    m.Get("/", func() string {
//      return "Hello world!"
//    })
//
//    m.Run()
//  }
package martini

import (
	"log"
	"net/http"
	"os"
	"reflect"

	"github.com/codegangsta/inject"
)

// Martini represents the top level web application. inject.Injector methods can be invoked to map services on a global level.
type Martini struct {
	inject.Injector
	handlers []Handler
	action   Handler
	logger   *log.Logger
}

// New creates a bare bones Martini instance. Use this method if you want to have full control over the middleware that is used.
func New() *Martini {
	m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[martini] ", 0)}
	m.Map(m.logger)
	m.Map(defaultReturnHandler())
	return m
}

// Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
// Will panic if any of the handlers is not a callable function
func (m *Martini) Handlers(handlers ...Handler) {
	m.handlers = make([]Handler, 0)
	for _, handler := range handlers {
		m.Use(handler)
	}
}

// Action sets the handler that will be called after all the middleware has been invoked. This is set to martini.Router in a martini.Classic().
func (m *Martini) Action(handler Handler) {
	validateHandler(handler)
	m.action = handler
}

// Logger sets the logger
func (m *Martini) Logger(logger *log.Logger) {
	m.logger = logger
	m.Map(m.logger)
}

// Use adds a middleware Handler to the stack. Will panic if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added.
func (m *Martini) Use(handler Handler) {
	validateHandler(handler)

	m.handlers = append(m.handlers, handler)
}

// ServeHTTP is the HTTP Entry point for a Martini instance. Useful if you want to control your own HTTP server.
func (m *Martini) ServeHTTP(res http.ResponseWriter, req *http.Request) {
	m.createContext(res, req).run()
}

// Run the http server on a given host and port.
func (m *Martini) RunOnAddr(addr string) {
	// TODO: Should probably be implemented using a new instance of http.Server in place of
	// calling http.ListenAndServer directly, so that it could be stored in the martini struct for later use.
	// This would also allow to improve testing when a custom host and port are passed.

	logger := m.Injector.Get(reflect.TypeOf(m.logger)).Interface().(*log.Logger)
	logger.Printf("listening on %s (%s)\n", addr, Env)
	logger.Fatalln(http.ListenAndServe(addr, m))
}

// Run the http server. Listening on os.GetEnv("PORT") or 3000 by default.
func (m *Martini) Run() {
	port := os.Getenv("PORT")
	if len(port) == 0 {
		port = "3000"
	}

	host := os.Getenv("HOST")

	m.RunOnAddr(host + ":" + port)
}

func (m *Martini) createContext(res http.ResponseWriter, req *http.Request) *context {
	c := &context{inject.New(), m.handlers, m.action, NewResponseWriter(res), 0}
	c.SetParent(m)
	c.MapTo(c, (*Context)(nil))
	c.MapTo(c.rw, (*http.ResponseWriter)(nil))
	c.Map(req)
	return c
}

// ClassicMartini represents a Martini with some reasonable defaults. Embeds the router functions for convenience.
type ClassicMartini struct {
	*Martini
	Router
}

// Classic creates a classic Martini with some basic default middleware - martini.Logger, martini.Recovery and martini.Static.
// Classic also maps martini.Routes as a service.
func Classic() *ClassicMartini {
	r := NewRouter()
	m := New()
	m.Use(Logger())
	m.Use(Recovery())
	m.Use(Static("public"))
	m.MapTo(r, (*Routes)(nil))
	m.Action(r.Handle)
	return &ClassicMartini{m, r}
}

// Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
// Martini will panic if an argument could not be fullfilled via dependency injection.
type Handler interface{}

func validateHandler(handler Handler) {
	if reflect.TypeOf(handler).Kind() != reflect.Func {
		panic("martini handler must be a callable func")
	}
}

// Context represents a request context. Services can be mapped on the request level from this interface.
type Context interface {
	inject.Injector
	// Next is an optional function that Middleware Handlers can call to yield the until after
	// the other Handlers have been executed. This works really well for any operations that must
	// happen after an http request
	Next()
	// Written returns whether or not the response for this context has been written.
	Written() bool
}

type context struct {
	inject.Injector
	handlers []Handler
	action   Handler
	rw       ResponseWriter
	index    int
}

func (c *context) handler() Handler {
	if c.index < len(c.handlers) {
		return c.handlers[c.index]
	}
	if c.index == len(c.handlers) {
		return c.action
	}
	panic("invalid index for context handler")
}

func (c *context) Next() {
	c.index += 1
	c.run()
}

func (c *context) Written() bool {
	return c.rw.Written()
}

func (c *context) run() {
	for c.index <= len(c.handlers) {
		_, err := c.Invoke(c.handler())
		if err != nil {
			panic(err)
		}
		c.index += 1

		if c.Written() {
			return
		}
	}
}


================================================
FILE: martini_test.go
================================================
package martini

import (
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"
)

/* Test Helpers */
func expect(t *testing.T, a interface{}, b interface{}) {
	if a != b {
		t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
	}
}

func refute(t *testing.T, a interface{}, b interface{}) {
	if a == b {
		t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
	}
}

func Test_New(t *testing.T) {
	m := New()
	if m == nil {
		t.Error("martini.New() cannot return nil")
	}
}

func Test_Martini_RunOnAddr(t *testing.T) {
	// just test that Run doesn't bomb
	go New().RunOnAddr("127.0.0.1:8080")
}

func Test_Martini_Run(t *testing.T) {
	go New().Run()
}

func Test_Martini_ServeHTTP(t *testing.T) {
	result := ""
	response := httptest.NewRecorder()

	m := New()
	m.Use(func(c Context) {
		result += "foo"
		c.Next()
		result += "ban"
	})
	m.Use(func(c Context) {
		result += "bar"
		c.Next()
		result += "baz"
	})
	m.Action(func(res http.ResponseWriter, req *http.Request) {
		result += "bat"
		res.WriteHeader(http.StatusBadRequest)
	})

	m.ServeHTTP(response, (*http.Request)(nil))

	expect(t, result, "foobarbatbazban")
	expect(t, response.Code, http.StatusBadRequest)
}

func Test_Martini_Handlers(t *testing.T) {
	result := ""
	response := httptest.NewRecorder()

	batman := func(c Context) {
		result += "batman!"
	}

	m := New()
	m.Use(func(c Context) {
		result += "foo"
		c.Next()
		result += "ban"
	})
	m.Handlers(
		batman,
		batman,
		batman,
	)
	m.Action(func(res http.ResponseWriter, req *http.Request) {
		result += "bat"
		res.WriteHeader(http.StatusBadRequest)
	})

	m.ServeHTTP(response, (*http.Request)(nil))

	expect(t, result, "batman!batman!batman!bat")
	expect(t, response.Code, http.StatusBadRequest)
}

func Test_Martini_EarlyWrite(t *testing.T) {
	result := ""
	response := httptest.NewRecorder()

	m := New()
	m.Use(func(res http.ResponseWriter) {
		result += "foobar"
		res.Write([]byte("Hello world"))
	})
	m.Use(func() {
		result += "bat"
	})
	m.Action(func(res http.ResponseWriter) {
		result += "baz"
		res.WriteHeader(http.StatusBadRequest)
	})

	m.ServeHTTP(response, (*http.Request)(nil))

	expect(t, result, "foobar")
	expect(t, response.Code, http.StatusOK)
}

func Test_Martini_Written(t *testing.T) {
	response := httptest.NewRecorder()

	m := New()
	m.Handlers(func(res http.ResponseWriter) {
		res.WriteHeader(http.StatusOK)
	})

	ctx := m.createContext(response, (*http.Request)(nil))
	expect(t, ctx.Written(), false)

	ctx.run()
	expect(t, ctx.Written(), true)
}

func Test_Martini_Basic_NoRace(t *testing.T) {
	m := New()
	handlers := []Handler{func() {}, func() {}}
	// Ensure append will not realloc to trigger the race condition
	m.handlers = handlers[:1]
	req, _ := http.NewRequest("GET", "/", nil)
	for i := 0; i < 2; i++ {
		go func() {
			response := httptest.NewRecorder()
			m.ServeHTTP(response, req)
		}()
	}
}


================================================
FILE: recovery.go
================================================
package martini

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"runtime"

	"github.com/codegangsta/inject"
)

const (
	panicHtml = `<html>
<head><title>PANIC: %s</title>
<style type="text/css">
html, body {
	font-family: "Roboto", sans-serif;
	color: #333333;
	background-color: #ea5343;
	margin: 0px;
}
h1 {
	color: #d04526;
	background-color: #ffffff;
	padding: 20px;
	border-bottom: 1px dashed #2b3848;
}
pre {
	margin: 20px;
	padding: 20px;
	border: 2px solid #2b3848;
	background-color: #ffffff;
}
</style>
</head><body>
<h1>PANIC</h1>
<pre style="font-weight: bold;">%s</pre>
<pre>%s</pre>
</body>
</html>`
)

var (
	dunno     = []byte("???")
	centerDot = []byte("·")
	dot       = []byte(".")
	slash     = []byte("/")
)

// stack returns a nicely formated stack frame, skipping skip frames
func stack(skip int) []byte {
	buf := new(bytes.Buffer) // the returned data
	// As we loop, we open files and read them. These variables record the currently
	// loaded file.
	var lines [][]byte
	var lastFile string
	for i := skip; ; i++ { // Skip the expected number of frames
		pc, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		// Print this much at least.  If we can't find the source, it won't show.
		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
		if file != lastFile {
			data, err := ioutil.ReadFile(file)
			if err != nil {
				continue
			}
			lines = bytes.Split(data, []byte{'\n'})
			lastFile = file
		}
		fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
	}
	return buf.Bytes()
}

// source returns a space-trimmed slice of the n'th line.
func source(lines [][]byte, n int) []byte {
	n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
	if n < 0 || n >= len(lines) {
		return dunno
	}
	return bytes.TrimSpace(lines[n])
}

// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
	fn := runtime.FuncForPC(pc)
	if fn == nil {
		return dunno
	}
	name := []byte(fn.Name())
	// The name includes the path name to the package, which is unnecessary
	// since the file name is already included.  Plus, it has center dots.
	// That is, we see
	//	runtime/debug.*T·ptrmethod
	// and want
	//	*T.ptrmethod
	// Also the package path might contains dot (e.g. code.google.com/...),
	// so first eliminate the path prefix
	if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
		name = name[lastslash+1:]
	}
	if period := bytes.Index(name, dot); period >= 0 {
		name = name[period+1:]
	}
	name = bytes.Replace(name, centerDot, dot, -1)
	return name
}

// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.
// While Martini is in development mode, Recovery will also output the panic as HTML.
func Recovery() Handler {
	return func(c Context, log *log.Logger) {
		defer func() {
			if err := recover(); err != nil {
				stack := stack(3)
				log.Printf("PANIC: %s\n%s", err, stack)

				// Lookup the current responsewriter
				val := c.Get(inject.InterfaceOf((*http.ResponseWriter)(nil)))
				res := val.Interface().(http.ResponseWriter)

				// respond with panic message while in development mode
				var body []byte
				if Env == Dev {
					res.Header().Set("Content-Type", "text/html")
					body = []byte(fmt.Sprintf(panicHtml, err, err, stack))
				} else {
					body = []byte("500 Internal Server Error")
				}

				res.WriteHeader(http.StatusInternalServerError)
				if nil != body {
					res.Write(body)
				}
			}
		}()

		c.Next()
	}
}


================================================
FILE: recovery_test.go
================================================
package martini

import (
	"bytes"
	"log"
	"net/http"
	"net/http/httptest"
	"testing"
)

func Test_Recovery(t *testing.T) {
	buff := bytes.NewBufferString("")
	recorder := httptest.NewRecorder()

	setENV(Dev)
	m := New()
	// replace log for testing
	m.Map(log.New(buff, "[martini] ", 0))
	m.Use(func(res http.ResponseWriter, req *http.Request) {
		res.Header().Set("Content-Type", "unpredictable")
	})
	m.Use(Recovery())
	m.Use(func(res http.ResponseWriter, req *http.Request) {
		panic("here is a panic!")
	})
	m.ServeHTTP(recorder, (*http.Request)(nil))
	expect(t, recorder.Code, http.StatusInternalServerError)
	expect(t, recorder.HeaderMap.Get("Content-Type"), "text/html")
	refute(t, recorder.Body.Len(), 0)
	refute(t, len(buff.String()), 0)
}

func Test_Recovery_ResponseWriter(t *testing.T) {
	recorder := httptest.NewRecorder()
	recorder2 := httptest.NewRecorder()

	setENV(Dev)
	m := New()
	m.Use(Recovery())
	m.Use(func(c Context) {
		c.MapTo(recorder2, (*http.ResponseWriter)(nil))
		panic("here is a panic!")
	})
	m.ServeHTTP(recorder, (*http.Request)(nil))

	expect(t, recorder2.Code, http.StatusInternalServerError)
	expect(t, recorder2.HeaderMap.Get("Content-Type"), "text/html")
	refute(t, recorder2.Body.Len(), 0)
}


================================================
FILE: response_writer.go
================================================
package martini

import (
	"bufio"
	"fmt"
	"net"
	"net/http"
)

// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
// if the functionality calls for it.
type ResponseWriter interface {
	http.ResponseWriter
	http.Flusher
	http.Hijacker
	// Status returns the status code of the response or 0 if the response has not been written.
	Status() int
	// Written returns whether or not the ResponseWriter has been written.
	Written() bool
	// Size returns the size of the response body.
	Size() int
	// Before allows for a function to be called before the ResponseWriter has been written to. This is
	// useful for setting headers or any other operations that must happen before a response has been written.
	Before(BeforeFunc)
}

// BeforeFunc is a function that is called before the ResponseWriter has been written to.
type BeforeFunc func(ResponseWriter)

// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
	newRw := responseWriter{rw, 0, 0, nil}
	if cn, ok := rw.(http.CloseNotifier); ok {
		return &closeNotifyResponseWriter{newRw, cn}
	}
	return &newRw
}

type responseWriter struct {
	http.ResponseWriter
	status      int
	size        int
	beforeFuncs []BeforeFunc
}

func (rw *responseWriter) WriteHeader(s int) {
	rw.callBefore()
	rw.ResponseWriter.WriteHeader(s)
	rw.status = s
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	if !rw.Written() {
		// The status will be StatusOK if WriteHeader has not been called yet
		rw.WriteHeader(http.StatusOK)
	}
	size, err := rw.ResponseWriter.Write(b)
	rw.size += size
	return size, err
}

func (rw *responseWriter) Status() int {
	return rw.status
}

func (rw *responseWriter) Size() int {
	return rw.size
}

func (rw *responseWriter) Written() bool {
	return rw.status != 0
}

func (rw *responseWriter) Before(before BeforeFunc) {
	rw.beforeFuncs = append(rw.beforeFuncs, before)
}

func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	hijacker, ok := rw.ResponseWriter.(http.Hijacker)
	if !ok {
		return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
	}
	return hijacker.Hijack()
}

func (rw *responseWriter) callBefore() {
	for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
		rw.beforeFuncs[i](rw)
	}
}

func (rw *responseWriter) Flush() {
	flusher, ok := rw.ResponseWriter.(http.Flusher)
	if ok {
		flusher.Flush()
	}
}

type closeNotifyResponseWriter struct {
	responseWriter
	closeNotifier http.CloseNotifier
}

func (rw *closeNotifyResponseWriter) CloseNotify() <-chan bool {
	return rw.closeNotifier.CloseNotify()
}


================================================
FILE: response_writer_test.go
================================================
package martini

import (
	"bufio"
	"io"
	"net"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

type closeNotifyingRecorder struct {
	*httptest.ResponseRecorder
	closed chan bool
}

func newCloseNotifyingRecorder() *closeNotifyingRecorder {
	return &closeNotifyingRecorder{
		httptest.NewRecorder(),
		make(chan bool, 1),
	}
}

func (c *closeNotifyingRecorder) close() {
	c.closed <- true
}

func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
	return c.closed
}

type hijackableResponse struct {
	Hijacked bool
}

func newHijackableResponse() *hijackableResponse {
	return &hijackableResponse{}
}

func (h *hijackableResponse) Header() http.Header           { return nil }
func (h *hijackableResponse) Write(buf []byte) (int, error) { return 0, nil }
func (h *hijackableResponse) WriteHeader(code int)          {}
func (h *hijackableResponse) Flush()                        {}
func (h *hijackableResponse) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	h.Hijacked = true
	return nil, nil, nil
}

func Test_ResponseWriter_WritingString(t *testing.T) {
	rec := httptest.NewRecorder()
	rw := NewResponseWriter(rec)

	rw.Write([]byte("Hello world"))

	expect(t, rec.Code, rw.Status())
	expect(t, rec.Body.String(), "Hello world")
	expect(t, rw.Status(), http.StatusOK)
	expect(t, rw.Size(), 11)
	expect(t, rw.Written(), true)
}

func Test_ResponseWriter_WritingStrings(t *testing.T) {
	rec := httptest.NewRecorder()
	rw := NewResponseWriter(rec)

	rw.Write([]byte("Hello world"))
	rw.Write([]byte("foo bar bat baz"))

	expect(t, rec.Code, rw.Status())
	expect(t, rec.Body.String(), "Hello worldfoo bar bat baz")
	expect(t, rw.Status(), http.StatusOK)
	expect(t, rw.Size(), 26)
}

func Test_ResponseWriter_WritingHeader(t *testing.T) {
	rec := httptest.NewRecorder()
	rw := NewResponseWriter(rec)

	rw.WriteHeader(http.StatusNotFound)

	expect(t, rec.Code, rw.Status())
	expect(t, rec.Body.String(), "")
	expect(t, rw.Status(), http.StatusNotFound)
	expect(t, rw.Size(), 0)
}

func Test_ResponseWriter_Before(t *testing.T) {
	rec := httptest.NewRecorder()
	rw := NewResponseWriter(rec)
	result := ""

	rw.Before(func(ResponseWriter) {
		result += "foo"
	})
	rw.Before(func(ResponseWriter) {
		result += "bar"
	})

	rw.WriteHeader(http.StatusNotFound)

	expect(t, rec.Code, rw.Status())
	expect(t, rec.Body.String(), "")
	expect(t, rw.Status(), http.StatusNotFound)
	expect(t, rw.Size(), 0)
	expect(t, result, "barfoo")
}

func Test_ResponseWriter_Hijack(t *testing.T) {
	hijackable := newHijackableResponse()
	rw := NewResponseWriter(hijackable)
	hijacker, ok := rw.(http.Hijacker)
	expect(t, ok, true)
	_, _, err := hijacker.Hijack()
	if err != nil {
		t.Error(err)
	}
	expect(t, hijackable.Hijacked, true)
}

func Test_ResponseWrite_Hijack_NotOK(t *testing.T) {
	hijackable := new(http.ResponseWriter)
	rw := NewResponseWriter(*hijackable)
	hijacker, ok := rw.(http.Hijacker)
	expect(t, ok, true)
	_, _, err := hijacker.Hijack()

	refute(t, err, nil)
}

func Test_ResponseWriter_CloseNotify(t *testing.T) {
	rec := newCloseNotifyingRecorder()
	rw := NewResponseWriter(rec)
	closed := false
	notifier := rw.(http.CloseNotifier).CloseNotify()
	rec.close()
	select {
	case <-notifier:
		closed = true
	case <-time.After(time.Second):
	}
	expect(t, closed, true)
}

func Test_ResponseWriter_Flusher(t *testing.T) {

	rec := httptest.NewRecorder()
	rw := NewResponseWriter(rec)

	_, ok := rw.(http.Flusher)
	expect(t, ok, true)
}

func Test_ResponseWriter_FlusherHandler(t *testing.T) {

	// New martini instance
	m := Classic()

	m.Get("/events", func(w http.ResponseWriter, r *http.Request) {

		f, ok := w.(http.Flusher)
		expect(t, ok, true)

		w.Header().Set("Content-Type", "text/event-stream")
		w.Header().Set("Cache-Control", "no-cache")
		w.Header().Set("Connection", "keep-alive")

		for i := 0; i < 2; i++ {
			time.Sleep(10 * time.Millisecond)
			io.WriteString(w, "data: Hello\n\n")
			f.Flush()
		}

	})

	recorder := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "/events", nil)
	m.ServeHTTP(recorder, r)

	if recorder.Code != 200 {
		t.Error("Response not 200")
	}

	if recorder.Body.String() != "data: Hello\n\ndata: Hello\n\n" {
		t.Error("Didn't receive correct body, got:", recorder.Body.String())
	}

}


================================================
FILE: return_handler.go
================================================
package martini

import (
	"github.com/codegangsta/inject"
	"net/http"
	"reflect"
)

// ReturnHandler is a service that Martini provides that is called
// when a route handler returns something. The ReturnHandler is
// responsible for writing to the ResponseWriter based on the values
// that are passed into this function.
type ReturnHandler func(Context, []reflect.Value)

func defaultReturnHandler() ReturnHandler {
	return func(ctx Context, vals []reflect.Value) {
		rv := ctx.Get(inject.InterfaceOf((*http.ResponseWriter)(nil)))
		res := rv.Interface().(http.ResponseWriter)
		var responseVal reflect.Value
		if len(vals) > 1 && vals[0].Kind() == reflect.Int {
			res.WriteHeader(int(vals[0].Int()))
			responseVal = vals[1]
		} else if len(vals) > 0 {
			responseVal = vals[0]
		}
		if canDeref(responseVal) {
			responseVal = responseVal.Elem()
		}
		if isByteSlice(responseVal) {
			res.Write(responseVal.Bytes())
		} else {
			res.Write([]byte(responseVal.String()))
		}
	}
}

func isByteSlice(val reflect.Value) bool {
	return val.Kind() == reflect.Slice && val.Type().Elem().Kind() == reflect.Uint8
}

func canDeref(val reflect.Value) bool {
	return val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr
}


================================================
FILE: router.go
================================================
package martini

import (
	"fmt"
	"net/http"
	"reflect"
	"regexp"
	"strconv"
	"sync"
)

// Params is a map of name/value pairs for named routes. An instance of martini.Params is available to be injected into any route handler.
type Params map[string]string

// Router is Martini's de-facto routing interface. Supports HTTP verbs, stacked handlers, and dependency injection.
type Router interface {
	Routes

	// Group adds a group where related routes can be added.
	Group(string, func(Router), ...Handler)
	// Get adds a route for a HTTP GET request to the specified matching pattern.
	Get(string, ...Handler) Route
	// Patch adds a route for a HTTP PATCH request to the specified matching pattern.
	Patch(string, ...Handler) Route
	// Post adds a route for a HTTP POST request to the specified matching pattern.
	Post(string, ...Handler) Route
	// Put adds a route for a HTTP PUT request to the specified matching pattern.
	Put(string, ...Handler) Route
	// Delete adds a route for a HTTP DELETE request to the specified matching pattern.
	Delete(string, ...Handler) Route
	// Options adds a route for a HTTP OPTIONS request to the specified matching pattern.
	Options(string, ...Handler) Route
	// Head adds a route for a HTTP HEAD request to the specified matching pattern.
	Head(string, ...Handler) Route
	// Any adds a route for any HTTP method request to the specified matching pattern.
	Any(string, ...Handler) Route
	// AddRoute adds a route for a given HTTP method request to the specified matching pattern.
	AddRoute(string, string, ...Handler) Route

	// NotFound sets the handlers that are called when a no route matches a request. Throws a basic 404 by default.
	NotFound(...Handler)

	// Handle is the entry point for routing. This is used as a martini.Handler
	Handle(http.ResponseWriter, *http.Request, Context)
}

type router struct {
	routes     []*route
	notFounds  []Handler
	groups     []group
	routesLock sync.RWMutex
}

type group struct {
	pattern  string
	handlers []Handler
}

// NewRouter creates a new Router instance.
// If you aren't using ClassicMartini, then you can add Routes as a
// service with:
//
//	m := martini.New()
//	r := martini.NewRouter()
//	m.MapTo(r, (*martini.Routes)(nil))
//
// If you are using ClassicMartini, then this is done for you.
func NewRouter() Router {
	return &router{notFounds: []Handler{http.NotFound}, groups: make([]group, 0)}
}

func (r *router) Group(pattern string, fn func(Router), h ...Handler) {
	r.groups = append(r.groups, group{pattern, h})
	fn(r)
	r.groups = r.groups[:len(r.groups)-1]
}

func (r *router) Get(pattern string, h ...Handler) Route {
	return r.addRoute("GET", pattern, h)
}

func (r *router) Patch(pattern string, h ...Handler) Route {
	return r.addRoute("PATCH", pattern, h)
}

func (r *router) Post(pattern string, h ...Handler) Route {
	return r.addRoute("POST", pattern, h)
}

func (r *router) Put(pattern string, h ...Handler) Route {
	return r.addRoute("PUT", pattern, h)
}

func (r *router) Delete(pattern string, h ...Handler) Route {
	return r.addRoute("DELETE", pattern, h)
}

func (r *router) Options(pattern string, h ...Handler) Route {
	return r.addRoute("OPTIONS", pattern, h)
}

func (r *router) Head(pattern string, h ...Handler) Route {
	return r.addRoute("HEAD", pattern, h)
}

func (r *router) Any(pattern string, h ...Handler) Route {
	return r.addRoute("*", pattern, h)
}

func (r *router) AddRoute(method, pattern string, h ...Handler) Route {
	return r.addRoute(method, pattern, h)
}

func (r *router) Handle(res http.ResponseWriter, req *http.Request, context Context) {
	bestMatch := NoMatch
	var bestVals map[string]string
	var bestRoute *route
	for _, route := range r.getRoutes() {
		match, vals := route.Match(req.Method, req.URL.Path)
		if match.BetterThan(bestMatch) {
			bestMatch = match
			bestVals = vals
			bestRoute = route
			if match == ExactMatch {
				break
			}
		}
	}
	if bestMatch != NoMatch {
		params := Params(bestVals)
		context.Map(params)
		bestRoute.Handle(context, res)
		return
	}

	// no routes exist, 404
	c := &routeContext{context, 0, r.notFounds}
	context.MapTo(c, (*Context)(nil))
	c.run()
}

func (r *router) NotFound(handler ...Handler) {
	r.notFounds = handler
}

func (r *router) addRoute(method string, pattern string, handlers []Handler) *route {
	if len(r.groups) > 0 {
		groupPattern := ""
		h := make([]Handler, 0)
		for _, g := range r.groups {
			groupPattern += g.pattern
			h = append(h, g.handlers...)
		}

		pattern = groupPattern + pattern
		h = append(h, handlers...)
		handlers = h
	}

	route := newRoute(method, pattern, handlers)
	route.Validate()
	r.appendRoute(route)
	return route
}

func (r *router) appendRoute(rt *route) {
	r.routesLock.Lock()
	defer r.routesLock.Unlock()
	r.routes = append(r.routes, rt)
}

func (r *router) getRoutes() []*route {
	r.routesLock.RLock()
	defer r.routesLock.RUnlock()
	return r.routes[:]
}

func (r *router) findRoute(name string) *route {
	for _, route := range r.getRoutes() {
		if route.name == name {
			return route
		}
	}

	return nil
}

// Route is an interface representing a Route in Martini's routing layer.
type Route interface {
	// URLWith returns a rendering of the Route's url with the given string params.
	URLWith([]string) string
	// Name sets a name for the route.
	Name(string)
	// GetName returns the name of the route.
	GetName() string
	// Pattern returns the pattern of the route.
	Pattern() string
	// Method returns the method of the route.
	Method() string
}

type route struct {
	method   string
	regex    *regexp.Regexp
	handlers []Handler
	pattern  string
	name     string
}

var routeReg1 = regexp.MustCompile(`:[^/#?()\.\\]+`)
var routeReg2 = regexp.MustCompile(`\*\*`)

func newRoute(method string, pattern string, handlers []Handler) *route {
	route := route{method, nil, handlers, pattern, ""}
	pattern = routeReg1.ReplaceAllStringFunc(pattern, func(m string) string {
		return fmt.Sprintf(`(?P<%s>[^/#?]+)`, m[1:])
	})
	var index int
	pattern = routeReg2.ReplaceAllStringFunc(pattern, func(m string) string {
		index++
		return fmt.Sprintf(`(?P<_%d>[^#?]*)`, index)
	})
	pattern += `\/?`
	route.regex = regexp.MustCompile(pattern)
	return &route
}

type RouteMatch int

const (
	NoMatch RouteMatch = iota
	StarMatch
	OverloadMatch
	ExactMatch
)

//Higher number = better match
func (r RouteMatch) BetterThan(o RouteMatch) bool {
	return r > o
}

func (r route) MatchMethod(method string) RouteMatch {
	switch {
	case method == r.method:
		return ExactMatch
	case method == "HEAD" && r.method == "GET":
		return OverloadMatch
	case r.method == "*":
		return StarMatch
	default:
		return NoMatch
	}
}

func (r route) Match(method string, path string) (RouteMatch, map[string]string) {
	// add Any method matching support
	match := r.MatchMethod(method)
	if match == NoMatch {
		return match, nil
	}

	matches := r.regex.FindStringSubmatch(path)
	if len(matches) > 0 && matches[0] == path {
		params := make(map[string]string)
		for i, name := range r.regex.SubexpNames() {
			if len(name) > 0 {
				params[name] = matches[i]
			}
		}
		return match, params
	}
	return NoMatch, nil
}

func (r *route) Validate() {
	for _, handler := range r.handlers {
		validateHandler(handler)
	}
}

func (r *route) Handle(c Context, res http.ResponseWriter) {
	context := &routeContext{c, 0, r.handlers}
	c.MapTo(context, (*Context)(nil))
	c.MapTo(r, (*Route)(nil))
	context.run()
}

var urlReg = regexp.MustCompile(`:[^/#?()\.\\]+|\(\?P<[a-zA-Z0-9]+>.*\)`)

// URLWith returns the url pattern replacing the parameters for its values
func (r *route) URLWith(args []string) string {
	if len(args) > 0 {
		argCount := len(args)
		i := 0
		url := urlReg.ReplaceAllStringFunc(r.pattern, func(m string) string {
			var val interface{}
			if i < argCount {
				val = args[i]
			} else {
				val = m
			}
			i += 1
			return fmt.Sprintf(`%v`, val)
		})

		return url
	}
	return r.pattern
}

func (r *route) Name(name string) {
	r.name = name
}

func (r *route) GetName() string {
	return r.name
}

func (r *route) Pattern() string {
	return r.pattern
}

func (r *route) Method() string {
	return r.method
}

// Routes is a helper service for Martini's routing layer.
type Routes interface {
	// URLFor returns a rendered URL for the given route. Optional params can be passed to fulfill named parameters in the route.
	URLFor(name string, params ...interface{}) string
	// MethodsFor returns an array of methods available for the path
	MethodsFor(path string) []string
	// All returns an array with all the routes in the router.
	All() []Route
}

// URLFor returns the url for the given route name.
func (r *router) URLFor(name string, params ...interface{}) string {
	route := r.findRoute(name)

	if route == nil {
		panic("route not found")
	}

	var args []string
	for _, param := range params {
		switch v := param.(type) {
		case int:
			args = append(args, strconv.FormatInt(int64(v), 10))
		case string:
			args = append(args, v)
		default:
			if v != nil {
				panic("Arguments passed to URLFor must be integers or strings")
			}
		}
	}

	return route.URLWith(args)
}

func (r *router) All() []Route {
	routes := r.getRoutes()
	var ri = make([]Route, len(routes))

	for i, route := range routes {
		ri[i] = Route(route)
	}

	return ri
}

func hasMethod(methods []string, method string) bool {
	for _, v := range methods {
		if v == method {
			return true
		}
	}
	return false
}

// MethodsFor returns all methods available for path
func (r *router) MethodsFor(path string) []string {
	methods := []string{}
	for _, route := range r.getRoutes() {
		matches := route.regex.FindStringSubmatch(path)
		if len(matches) > 0 && matches[0] == path && !hasMethod(methods, route.method) {
			methods = append(methods, route.method)
		}
	}
	return methods
}

type routeContext struct {
	Context
	index    int
	handlers []Handler
}

func (r *routeContext) Next() {
	r.index += 1
	r.run()
}

func (r *routeContext) run() {
	for r.index < len(r.handlers) {
		handler := r.handlers[r.index]
		vals, err := r.Invoke(handler)
		if err != nil {
			panic(err)
		}
		r.index += 1

		// if the handler returned something, write it to the http response
		if len(vals) > 0 {
			ev := r.Get(reflect.TypeOf(ReturnHandler(nil)))
			handleReturn := ev.Interface().(ReturnHandler)
			handleReturn(r, vals)
		}

		if r.Written() {
			return
		}
	}
}


================================================
FILE: router_test.go
================================================
package martini

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func Test_Routing(t *testing.T) {
	router := NewRouter()
	recorder := httptest.NewRecorder()

	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)

	req2, _ := http.NewRequest("POST", "http://localhost:3000/bar/bat", nil)
	context2 := New().createContext(recorder, req2)

	req3, _ := http.NewRequest("DELETE", "http://localhost:3000/baz", nil)
	context3 := New().createContext(recorder, req3)

	req4, _ := http.NewRequest("PATCH", "http://localhost:3000/bar/foo", nil)
	context4 := New().createContext(recorder, req4)

	req5, _ := http.NewRequest("GET", "http://localhost:3000/fez/this/should/match", nil)
	context5 := New().createContext(recorder, req5)

	req6, _ := http.NewRequest("PUT", "http://localhost:3000/pop/blah/blah/blah/bap/foo/", nil)
	context6 := New().createContext(recorder, req6)

	req7, _ := http.NewRequest("DELETE", "http://localhost:3000/wap//pow", nil)
	context7 := New().createContext(recorder, req7)

	req8, _ := http.NewRequest("HEAD", "http://localhost:3000/wap//pow", nil)
	context8 := New().createContext(recorder, req8)

	req9, _ := http.NewRequest("OPTIONS", "http://localhost:3000/opts", nil)
	context9 := New().createContext(recorder, req9)

	req10, _ := http.NewRequest("HEAD", "http://localhost:3000/foo", nil)
	context10 := New().createContext(recorder, req10)

	req11, _ := http.NewRequest("GET", "http://localhost:3000/bazz/inga", nil)
	context11 := New().createContext(recorder, req11)

	req12, _ := http.NewRequest("POST", "http://localhost:3000/bazz/inga", nil)
	context12 := New().createContext(recorder, req12)

	req13, _ := http.NewRequest("GET", "http://localhost:3000/bazz/in/ga", nil)
	context13 := New().createContext(recorder, req13)

	req14, _ := http.NewRequest("GET", "http://localhost:3000/bzz", nil)
	context14 := New().createContext(recorder, req14)

	result := ""
	router.Get("/foo", func(req *http.Request) {
		result += "foo"
	})
	router.Patch("/bar/:id", func(params Params) {
		expect(t, params["id"], "foo")
		result += "barfoo"
	})
	router.Post("/bar/:id", func(params Params) {
		expect(t, params["id"], "bat")
		result += "barbat"
	})
	router.Put("/fizzbuzz", func() {
		result += "fizzbuzz"
	})
	router.Delete("/bazzer", func(c Context) {
		result += "baz"
	})
	router.Get("/fez/**", func(params Params) {
		expect(t, params["_1"], "this/should/match")
		result += "fez"
	})
	router.Put("/pop/**/bap/:id/**", func(params Params) {
		expect(t, params["id"], "foo")
		expect(t, params["_1"], "blah/blah/blah")
		expect(t, params["_2"], "")
		result += "popbap"
	})
	router.Delete("/wap/**/pow", func(params Params) {
		expect(t, params["_1"], "")
		result += "wappow"
	})
	router.Options("/opts", func() {
		result += "opts"
	})
	router.Head("/wap/**/pow", func(params Params) {
		expect(t, params["_1"], "")
		result += "wappow"
	})
	router.Group("/bazz", func(r Router) {
		r.Get("/inga", func() {
			result += "get"
		})

		r.Post("/inga", func() {
			result += "post"
		})

		r.Group("/in", func(r Router) {
			r.Get("/ga", func() {
				result += "ception"
			})
		}, func() {
			result += "group"
		})
	}, func() {
		result += "bazz"
	}, func() {
		result += "inga"
	})
	router.AddRoute("GET", "/bzz", func(c Context) {
		result += "bzz"
	})

	router.Handle(recorder, req, context)
	router.Handle(recorder, req2, context2)
	router.Handle(recorder, req3, context3)
	router.Handle(recorder, req4, context4)
	router.Handle(recorder, req5, context5)
	router.Handle(recorder, req6, context6)
	router.Handle(recorder, req7, context7)
	router.Handle(recorder, req8, context8)
	router.Handle(recorder, req9, context9)
	router.Handle(recorder, req10, context10)
	router.Handle(recorder, req11, context11)
	router.Handle(recorder, req12, context12)
	router.Handle(recorder, req13, context13)
	router.Handle(recorder, req14, context14)
	expect(t, result, "foobarbatbarfoofezpopbapwappowwappowoptsfoobazzingagetbazzingapostbazzingagroupceptionbzz")
	expect(t, recorder.Code, http.StatusNotFound)
	expect(t, recorder.Body.String(), "404 page not found\n")
}

func Test_RouterHandlerStatusCode(t *testing.T) {
	router := NewRouter()
	router.Get("/foo", func() string {
		return "foo"
	})
	router.Get("/bar", func() (int, string) {
		return http.StatusForbidden, "bar"
	})
	router.Get("/baz", func() (string, string) {
		return "baz", "BAZ!"
	})
	router.Get("/bytes", func() []byte {
		return []byte("Bytes!")
	})
	router.Get("/interface", func() interface{} {
		return "Interface!"
	})

	// code should be 200 if none is returned from the handler
	recorder := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)
	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusOK)
	expect(t, recorder.Body.String(), "foo")

	// if a status code is returned, it should be used
	recorder = httptest.NewRecorder()
	req, _ = http.NewRequest("GET", "http://localhost:3000/bar", nil)
	context = New().createContext(recorder, req)
	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusForbidden)
	expect(t, recorder.Body.String(), "bar")

	// shouldn't use the first returned value as a status code if not an integer
	recorder = httptest.NewRecorder()
	req, _ = http.NewRequest("GET", "http://localhost:3000/baz", nil)
	context = New().createContext(recorder, req)
	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusOK)
	expect(t, recorder.Body.String(), "baz")

	// Should render bytes as a return value as well.
	recorder = httptest.NewRecorder()
	req, _ = http.NewRequest("GET", "http://localhost:3000/bytes", nil)
	context = New().createContext(recorder, req)
	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusOK)
	expect(t, recorder.Body.String(), "Bytes!")

	// Should render interface{} values.
	recorder = httptest.NewRecorder()
	req, _ = http.NewRequest("GET", "http://localhost:3000/interface", nil)
	context = New().createContext(recorder, req)
	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusOK)
	expect(t, recorder.Body.String(), "Interface!")
}

func Test_RouterHandlerStacking(t *testing.T) {
	router := NewRouter()
	recorder := httptest.NewRecorder()

	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)

	result := ""

	f1 := func() {
		result += "foo"
	}

	f2 := func(c Context) {
		result += "bar"
		c.Next()
		result += "bing"
	}

	f3 := func() string {
		result += "bat"
		return "Hello world"
	}

	f4 := func() {
		result += "baz"
	}

	router.Get("/foo", f1, f2, f3, f4)

	router.Handle(recorder, req, context)
	expect(t, result, "foobarbatbing")
	expect(t, recorder.Body.String(), "Hello world")
}

var routeTests = []struct {
	// in
	method string
	path   string

	// out
	match  RouteMatch
	params map[string]string
}{
	{"GET", "/foo/123/bat/321", ExactMatch, map[string]string{"bar": "123", "baz": "321"}},
	{"POST", "/foo/123/bat/321", NoMatch, map[string]string{}},
	{"GET", "/foo/hello/bat/world", ExactMatch, map[string]string{"bar": "hello", "baz": "world"}},
	{"GET", "foo/hello/bat/world", NoMatch, map[string]string{}},
	{"GET", "/foo/123/bat/321/", ExactMatch, map[string]string{"bar": "123", "baz": "321"}},
	{"GET", "/foo/123/bat/321//", NoMatch, map[string]string{}},
	{"GET", "/foo/123//bat/321/", NoMatch, map[string]string{}},
	{"HEAD", "/foo/123/bat/321/", OverloadMatch, map[string]string{"bar": "123", "baz": "321"}},
}

func Test_RouteMatching(t *testing.T) {
	route := newRoute("GET", "/foo/:bar/bat/:baz", nil)
	for _, tt := range routeTests {
		match, params := route.Match(tt.method, tt.path)
		if match != tt.match || params["bar"] != tt.params["bar"] || params["baz"] != tt.params["baz"] {
			t.Errorf("expected: (%v, %v) got: (%v, %v)", tt.match, tt.params, match, params)
		}
	}
}

func Test_MethodsFor(t *testing.T) {
	router := NewRouter()
	recorder := httptest.NewRecorder()

	req, _ := http.NewRequest("POST", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)
	context.MapTo(router, (*Routes)(nil))
	router.Post("/foo/bar", func() {
	})

	router.Post("/fo", func() {
	})

	router.Get("/foo", func() {
	})

	router.Put("/foo", func() {
	})

	router.NotFound(func(routes Routes, w http.ResponseWriter, r *http.Request) {
		methods := routes.MethodsFor(r.URL.Path)
		if len(methods) != 0 {
			w.Header().Set("Allow", strings.Join(methods, ","))
			w.WriteHeader(http.StatusMethodNotAllowed)
		}
	})
	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusMethodNotAllowed)
	expect(t, recorder.Header().Get("Allow"), "GET,PUT")
}

func Test_NotFound(t *testing.T) {
	router := NewRouter()
	recorder := httptest.NewRecorder()

	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)

	router.NotFound(func(res http.ResponseWriter) {
		http.Error(res, "Nope", http.StatusNotFound)
	})

	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusNotFound)
	expect(t, recorder.Body.String(), "Nope\n")
}

func Test_NotFoundAsHandler(t *testing.T) {
	router := NewRouter()
	recorder := httptest.NewRecorder()

	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)

	router.NotFound(func() string {
		return "not found"
	})

	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusOK)
	expect(t, recorder.Body.String(), "not found")

	recorder = httptest.NewRecorder()

	context = New().createContext(recorder, req)

	router.NotFound(func() (int, string) {
		return 404, "not found"
	})

	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusNotFound)
	expect(t, recorder.Body.String(), "not found")

	recorder = httptest.NewRecorder()

	context = New().createContext(recorder, req)

	router.NotFound(func() (int, string) {
		return 200, ""
	})

	router.Handle(recorder, req, context)
	expect(t, recorder.Code, http.StatusOK)
	expect(t, recorder.Body.String(), "")
}

func Test_NotFoundStacking(t *testing.T) {
	router := NewRouter()
	recorder := httptest.NewRecorder()

	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)

	result := ""

	f1 := func() {
		result += "foo"
	}

	f2 := func(c Context) {
		result += "bar"
		c.Next()
		result += "bing"
	}

	f3 := func() string {
		result += "bat"
		return "Not Found"
	}

	f4 := func() {
		result += "baz"
	}

	router.NotFound(f1, f2, f3, f4)

	router.Handle(recorder, req, context)
	expect(t, result, "foobarbatbing")
	expect(t, recorder.Body.String(), "Not Found")
}

func Test_Any(t *testing.T) {
	router := NewRouter()
	router.Any("/foo", func(res http.ResponseWriter) {
		http.Error(res, "Nope", http.StatusNotFound)
	})

	recorder := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)
	router.Handle(recorder, req, context)

	expect(t, recorder.Code, http.StatusNotFound)
	expect(t, recorder.Body.String(), "Nope\n")

	recorder = httptest.NewRecorder()
	req, _ = http.NewRequest("PUT", "http://localhost:3000/foo", nil)
	context = New().createContext(recorder, req)
	router.Handle(recorder, req, context)

	expect(t, recorder.Code, http.StatusNotFound)
	expect(t, recorder.Body.String(), "Nope\n")
}

func Test_URLFor(t *testing.T) {
	router := NewRouter()

	router.Get("/foo", func() {
		// Nothing
	}).Name("foo")

	router.Post("/bar/:id", func(params Params) {
		// Nothing
	}).Name("bar")

	router.Get("/baz/:id/(?P<name>[a-z]*)", func(params Params, routes Routes) {
		// Nothing
	}).Name("baz_id")

	router.Get("/bar/:id/:name", func(params Params, routes Routes) {
		expect(t, routes.URLFor("foo", nil), "/foo")
		expect(t, routes.URLFor("bar", 5), "/bar/5")
		expect(t, routes.URLFor("baz_id", 5, "john"), "/baz/5/john")
		expect(t, routes.URLFor("bar_id", 5, "john"), "/bar/5/john")
	}).Name("bar_id")

	// code should be 200 if none is returned from the handler
	recorder := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "http://localhost:3000/bar/foo/bar", nil)
	context := New().createContext(recorder, req)
	context.MapTo(router, (*Routes)(nil))
	router.Handle(recorder, req, context)
}

func Test_AllRoutes(t *testing.T) {
	router := NewRouter()

	patterns := []string{"/foo", "/fee", "/fii"}
	methods := []string{"GET", "POST", "DELETE"}
	names := []string{"foo", "fee", "fii"}

	router.Get("/foo", func() {}).Name("foo")
	router.Post("/fee", func() {}).Name("fee")
	router.Delete("/fii", func() {}).Name("fii")

	for i, r := range router.All() {
		expect(t, r.Pattern(), patterns[i])
		expect(t, r.Method(), methods[i])
		expect(t, r.GetName(), names[i])
	}
}

func Test_ActiveRoute(t *testing.T) {
	router := NewRouter()

	router.Get("/foo", func(r Route) {
		expect(t, r.Pattern(), "/foo")
		expect(t, r.GetName(), "foo")
	}).Name("foo")

	// code should be 200 if none is returned from the handler
	recorder := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "http://localhost:3000/foo", nil)
	context := New().createContext(recorder, req)
	context.MapTo(router, (*Routes)(nil))
	router.Handle(recorder, req, context)
}


================================================
FILE: static.go
================================================
package martini

import (
	"log"
	"net/http"
	"net/url"
	"path"
	"path/filepath"
	"strings"
)

// StaticOptions is a struct for specifying configuration options for the martini.Static middleware.
type StaticOptions struct {
	// Prefix is the optional prefix used to serve the static directory content
	Prefix string
	// SkipLogging will disable [Static] log messages when a static file is served.
	SkipLogging bool
	// IndexFile defines which file to serve as index if it exists.
	IndexFile string
	// Expires defines which user-defined function to use for producing a HTTP Expires Header
	// https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
	Expires func() string
	// Fallback defines a default URL to serve when the requested resource was
	// not found.
	Fallback string
	// Exclude defines a pattern for URLs this handler should never process.
	Exclude string
}

func prepareStaticOptions(options []StaticOptions) StaticOptions {
	var opt StaticOptions
	if len(options) > 0 {
		opt = options[0]
	}

	// Defaults
	if len(opt.IndexFile) == 0 {
		opt.IndexFile = "index.html"
	}
	// Normalize the prefix if provided
	if opt.Prefix != "" {
		// Ensure we have a leading '/'
		if opt.Prefix[0] != '/' {
			opt.Prefix = "/" + opt.Prefix
		}
		// Remove any trailing '/'
		opt.Prefix = strings.TrimRight(opt.Prefix, "/")
	}
	return opt
}

// Static returns a middleware handler that serves static files in the given directory.
func Static(directory string, staticOpt ...StaticOptions) Handler {
	if !filepath.IsAbs(directory) {
		directory = filepath.Join(Root, directory)
	}
	dir := http.Dir(directory)
	opt := prepareStaticOptions(staticOpt)

	return func(res http.ResponseWriter, req *http.Request, log *log.Logger) {
		if req.Method != "GET" && req.Method != "HEAD" {
			return
		}
		if opt.Exclude != "" && strings.HasPrefix(req.URL.Path, opt.Exclude) {
			return
		}
		file := req.URL.Path
		// if we have a prefix, filter requests by stripping the prefix
		if opt.Prefix != "" {
			if !strings.HasPrefix(file, opt.Prefix) {
				return
			}
			file = file[len(opt.Prefix):]
			if file != "" && file[0] != '/' {
				return
			}
		}
		f, err := dir.Open(file)
		if err != nil {
			// try any fallback before giving up
			if opt.Fallback != "" {
				file = opt.Fallback // so that logging stays true
				f, err = dir.Open(opt.Fallback)
			}

			if err != nil {
				// discard the error?
				return
			}
		}
		defer f.Close()

		fi, err := f.Stat()
		if err != nil {
			return
		}

		// try to serve index file
		if fi.IsDir() {
			// redirect if missing trailing slash
			if !strings.HasSuffix(req.URL.Path, "/") {
				dest := url.URL{
					Path:     req.URL.Path + "/",
					RawQuery: req.URL.RawQuery,
					Fragment: req.URL.Fragment,
				}
				http.Redirect(res, req, dest.String(), http.StatusFound)
				return
			}

			file = path.Join(file, opt.IndexFile)
			f, err = dir.Open(file)
			if err != nil {
				return
			}
			defer f.Close()

			fi, err = f.Stat()
			if err != nil || fi.IsDir() {
				return
			}
		}

		if !opt.SkipLogging {
			log.Println("[Static] Serving " + file)
		}

		// Add an Expires header to the static content
		if opt.Expires != nil {
			res.Header().Set("Expires", opt.Expires())
		}

		http.ServeContent(res, req, file, fi.ModTime(), f)
	}
}


================================================
FILE: static_test.go
================================================
package martini

import (
	"bytes"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"path"
	"testing"

	"github.com/codegangsta/inject"
)

var currentRoot, _ = os.Getwd()

func Test_Static(t *testing.T) {
	response := httptest.NewRecorder()
	response.Body = new(bytes.Buffer)

	m := New()
	r := NewRouter()

	m.Use(Static(currentRoot))
	m.Action(r.Handle)

	req, err := http.NewRequest("GET", "http://localhost:3000/martini.go", nil)
	if err != nil {
		t.Error(err)
	}
	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	expect(t, response.Header().Get("Expires"), "")
	if response.Body.Len() == 0 {
		t.Errorf("Got empty body for GET request")
	}
}

func Test_Static_Local_Path(t *testing.T) {
	Root = os.TempDir()
	response := httptest.NewRecorder()
	response.Body = new(bytes.Buffer)

	m := New()
	r := NewRouter()

	m.Use(Static("."))
	f, err := ioutil.TempFile(Root, "static_content")
	if err != nil {
		t.Error(err)
	}
	f.WriteString("Expected Content")
	f.Close()
	m.Action(r.Handle)

	req, err := http.NewRequest("GET", "http://localhost:3000/"+path.Base(f.Name()), nil)
	if err != nil {
		t.Error(err)
	}
	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	expect(t, response.Header().Get("Expires"), "")
	expect(t, response.Body.String(), "Expected Content")
}

func Test_Static_Head(t *testing.T) {
	response := httptest.NewRecorder()
	response.Body = new(bytes.Buffer)

	m := New()
	r := NewRouter()

	m.Use(Static(currentRoot))
	m.Action(r.Handle)

	req, err := http.NewRequest("HEAD", "http://localhost:3000/martini.go", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	if response.Body.Len() != 0 {
		t.Errorf("Got non-empty body for HEAD request")
	}
}

func Test_Static_As_Post(t *testing.T) {
	response := httptest.NewRecorder()

	m := New()
	r := NewRouter()

	m.Use(Static(currentRoot))
	m.Action(r.Handle)

	req, err := http.NewRequest("POST", "http://localhost:3000/martini.go", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusNotFound)
}

func Test_Static_BadDir(t *testing.T) {
	response := httptest.NewRecorder()

	m := Classic()

	req, err := http.NewRequest("GET", "http://localhost:3000/martini.go", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	refute(t, response.Code, http.StatusOK)
}

func Test_Static_Options_Logging(t *testing.T) {
	response := httptest.NewRecorder()

	var buffer bytes.Buffer
	m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(&buffer, "[martini] ", 0)}
	m.Map(m.logger)
	m.Map(defaultReturnHandler())

	opt := StaticOptions{}
	m.Use(Static(currentRoot, opt))

	req, err := http.NewRequest("GET", "http://localhost:3000/martini.go", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	expect(t, buffer.String(), "[martini] [Static] Serving /martini.go\n")

	// Now without logging
	m.Handlers()
	buffer.Reset()

	// This should disable logging
	opt.SkipLogging = true
	m.Use(Static(currentRoot, opt))

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	expect(t, buffer.String(), "")
}

func Test_Static_Options_ServeIndex(t *testing.T) {
	response := httptest.NewRecorder()

	var buffer bytes.Buffer
	m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(&buffer, "[martini] ", 0)}
	m.Map(m.logger)
	m.Map(defaultReturnHandler())

	opt := StaticOptions{IndexFile: "martini.go"} // Define martini.go as index file
	m.Use(Static(currentRoot, opt))

	req, err := http.NewRequest("GET", "http://localhost:3000/", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	expect(t, buffer.String(), "[martini] [Static] Serving /martini.go\n")
}

func Test_Static_Options_Prefix(t *testing.T) {
	response := httptest.NewRecorder()

	var buffer bytes.Buffer
	m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(&buffer, "[martini] ", 0)}
	m.Map(m.logger)
	m.Map(defaultReturnHandler())

	// Serve current directory under /public
	m.Use(Static(currentRoot, StaticOptions{Prefix: "/public"}))

	// Check file content behaviour
	req, err := http.NewRequest("GET", "http://localhost:3000/public/martini.go", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	expect(t, buffer.String(), "[martini] [Static] Serving /martini.go\n")
}

func Test_Static_Options_Expires(t *testing.T) {
	response := httptest.NewRecorder()

	var buffer bytes.Buffer
	m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(&buffer, "[martini] ", 0)}
	m.Map(m.logger)
	m.Map(defaultReturnHandler())

	// Serve current directory under /public
	m.Use(Static(currentRoot, StaticOptions{Expires: func() string { return "46" }}))

	// Check file content behaviour
	req, err := http.NewRequest("GET", "http://localhost:3000/martini.go", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Header().Get("Expires"), "46")
}

func Test_Static_Options_Fallback(t *testing.T) {
	response := httptest.NewRecorder()

	var buffer bytes.Buffer
	m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(&buffer, "[martini] ", 0)}
	m.Map(m.logger)
	m.Map(defaultReturnHandler())

	// Serve current directory under /public
	m.Use(Static(currentRoot, StaticOptions{Fallback: "/martini.go"}))

	// Check file content behaviour
	req, err := http.NewRequest("GET", "http://localhost:3000/initram.go", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusOK)
	expect(t, buffer.String(), "[martini] [Static] Serving /martini.go\n")
}

func Test_Static_Redirect(t *testing.T) {
	response := httptest.NewRecorder()

	m := New()
	m.Use(Static(currentRoot, StaticOptions{Prefix: "/public"}))

	req, err := http.NewRequest("GET", "http://localhost:3000/public?param=foo#bar", nil)
	if err != nil {
		t.Error(err)
	}

	m.ServeHTTP(response, req)
	expect(t, response.Code, http.StatusFound)
	expect(t, response.Header().Get("Location"), "/public/?param=foo#bar")
}


================================================
FILE: translations/README_de_DE.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

Martini ist ein mächtiges Package zur schnellen Entwicklung von modularen Webanwendungen und -services in Golang. 

## Ein Projekt starten

Nach der Installation von Go und dem Einrichten des [GOPATH](http://golang.org/doc/code.html#GOPATH), erstelle Deine erste `.go`-Datei. Speichere sie unter `server.go`.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hallo Welt!"
  })
  m.Run()
}
~~~

Installiere anschließend das Martini Package (**Go 1.1** oder höher wird vorausgesetzt):
~~~
go get github.com/go-martini/martini
~~~

Starte den Server:
~~~
go run server.go
~~~

Der Martini-Webserver ist nun unter `localhost:3000` erreichbar.

## Hilfe

Abonniere den [Emailverteiler](https://groups.google.com/forum/#!forum/martini-go)

Schaue das [Demovideo](http://martini.codegangsta.io/#demo)

Stelle Fragen auf Stackoverflow mit dem [Martini-Tag](http://stackoverflow.com/questions/tagged/martini)

GoDoc [Dokumentation](http://godoc.org/github.com/go-martini/martini)


## Eigenschaften
* Sehr einfach nutzbar
* Nicht-intrusives Design
* Leicht kombinierbar mit anderen Golang Packages
* Ausgezeichnetes Path Matching und Routing
* Modulares Design - einfaches Hinzufügen und Entfernen von Funktionen
* Eine Vielzahl von guten Handlern/Middlewares nutzbar
* Großer Funktionsumfang mitgeliefert
* **Voll kompatibel mit dem [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc) Interface.**
* Standardmäßiges Ausliefern von Dateien (z.B. von AngularJS-Apps im HTML5-Modus)

## Mehr Middleware
Mehr Informationen zur Middleware und Funktionalität findest Du in den Repositories der [martini-contrib](https://github.com/martini-contrib) Gruppe.

## Inhaltsverzeichnis
* [Classic Martini](#classic-martini)
  * [Handler](#handler)
  * [Routing](#routing)
  * [Services](#services)
  * [Statische Dateien bereitstellen](#statische-dateien-bereitstellen)
* [Middleware Handler](#middleware-handler)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
Einen schnellen Start in ein Projekt ermöglicht [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic), dessen Voreinstellungen sich für die meisten Webanwendungen eignen:
~~~ go
  m := martini.Classic()
  // ... Middleware und Routing hier einfügen
  m.Run()
~~~

Aufgelistet findest Du einige Aspekte, die [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) automatich berücksichtigt:

  * Request/Response Logging - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Static File serving - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Routing - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Handler
Handler sind das Herz und die Seele von Martini. Ein Handler ist grundsätzlich jede Art von aufrufbaren Funktionen:
~~~ go
m.Get("/", func() {
  println("Hallo Welt")
})
~~~

#### Rückgabewerte
Wenn ein Handler Rückgabewerte beinhaltet, übergibt Martini diese an den aktuellen [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) in Form eines String:
~~~ go
m.Get("/", func() string {
  return "Hallo Welt" // HTTP 200 : "Hallo Welt"
})
~~~

Die Rückgabe eines Statuscode ist optional:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "Ich bin eine Teekanne" // HTTP 418 : "Ich bin eine Teekanne"
})
~~~

#### Service Injection
Handler werden per Reflection aufgerufen. Martini macht Gebrauch von *Dependency Injection*, um Abhängigkeiten in der Argumentliste von Handlern aufzulösen. **Dies macht Martini komplett kompatibel mit Golangs `http.HandlerFunc` Interface.**

Fügst Du einem Handler ein Argument hinzu, sucht Martini in seiner Liste von Services und versucht, die Abhängigkeiten via Type Assertion aufzulösen. 
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res und req wurden von Martini injiziert
  res.WriteHeader(200) // HTTP 200
})
~~~

Die Folgenden Services sind Bestandteil von [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):

  * [*log.Logger](http://godoc.org/log#Logger) - Globaler Logger für Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request context.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` von benannten Parametern, welche durch Route Matching gefunden wurden.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Routen Hilfeservice.
  * [martini.Route](http://godoc.org/github.com/go-martini/martini#Route) - Aktuelle, aktive Route.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response writer interface.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request.

### Routing
Eine Route ist in Martini eine HTTP-Methode gepaart mit einem URL-Matching-Pattern. Jede Route kann eine oder mehrere Handler-Methoden übernehmen:
~~~ go
m.Get("/", func() {
  // zeige etwas an
})

m.Patch("/", func() {
  // aktualisiere etwas
})

m.Post("/", func() {
  // erstelle etwas
})

m.Put("/", func() {
  // ersetze etwas
})

m.Delete("/", func() {
  // lösche etwas
})

m.Options("/", func() {
  // HTTP-Optionen
})

m.NotFound(func() {
  // bearbeite 404-Fehler
})
~~~

Routen werden in der Reihenfolge, in welcher sie definiert wurden, zugeordnet. Die bei einer Anfrage zuerst zugeordnete Route wird daraufhin aufgerufen.  

Routenmuster enthalten ggf. benannte Parameter, die über den [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) Service abrufbar sind:
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hallo " + params["name"]
})
~~~

Routen können mit Globs versehen werden:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hallo " + params["_1"]
})
~~~

Reguläre Ausdrücke sind ebenfalls möglich:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hallo %s", params["name"])
})
~~~
Weitere Informationen zum Syntax regulärer Ausdrücke findest Du in der [Go Dokumentation](http://golang.org/pkg/regexp/syntax/).

Routen-Handler können auch ineinander verschachtelt werden. Dies ist bei der Authentifizierung und den Berechtigungen nützlich.
~~~ go
m.Get("/secret", authorize, func() {
  // wird ausgeführt, solange authorize nichts zurückgibt
})
~~~

Routengruppen können durch die Group-Methode hinzugefügt werden.
~~~ go
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)
})
~~~

Sowohl Handlern als auch Middlewares können Gruppen übergeben werden.
~~~ go
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)
~~~

### Services
Services sind Objekte, welche der Argumentliste von Handlern beigefügt werden können.
Du kannst einem Service der *Global* oder *Request* Ebene zuordnen.

#### Global Mapping
Eine Martini-Instanz implementiert das inject.Injector Interface, sodass ein Service leicht zugeordnet werden kann:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // der Service ist allen Handlern unter *MyDatabase verfügbar
// ...
m.Run()
~~~

#### Request-Level Mapping
Das Zuordnen auf der Request-Ebene kann in einem Handler via  [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) realisiert werden:
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // zugeordnet als *MyCustomLogger
}
~~~

#### Werten einem Interface zuordnen
Einer der mächtigsten Aspekte von Services ist dessen Fähigkeit, einen Service einem Interface zuzuordnen. Möchtest Du den [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) mit einem Decorator (Objekt) und dessen Zusatzfunktionen überschreiben, definiere den Handler wie folgt:
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // überschribe ResponseWriter mit dem  ResponseWriter Decorator
}
~~~

### Statische Dateien bereitstellen
Eine [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) Instanz übertragt automatisch statische Dateien aus dem "public"-Ordner im Stammverzeichnis Deines Servers. Dieses Verhalten lässt sich durch weitere [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) Handler auf andere Verzeichnisse übertragen.
~~~ go
m.Use(martini.Static("assets")) // überträgt auch vom "assets"-Verzeichnis
~~~

#### Eine voreingestelle Datei übertragen
Du kannst die URL zu einer lokalen Datei angeben, sollte die URL einer Anfrage nicht gefunden werden. Durch einen Präfix können bestimmte URLs ignoriert werden.
Dies ist für Server nützlich, welche statische Dateien übertragen und ggf. zusätzliche Handler defineren (z.B. eine REST-API). Ist dies der Fall, so ist das Anlegen eines Handlers in der NotFound-Reihe nützlich.

Das gezeigte Beispiel zeigt die `/index.html` immer an, wenn die angefrage URL keiner lokalen Datei zugeordnet werden kann bzw. wenn sie nicht mit `/api/v` beginnt:
~~~ go
static := martini.Static("assets", martini.StaticOptions{Fallback: "/index.html", Exclude: "/api/v"})
m.NotFound(static, http.NotFound)
~~~

## Middleware Handler
Middleware-Handler befinden sich logisch zwischen einer Anfrage via HTTP und dem Router. Im wesentlichen unterscheiden sie sich nicht von anderen Handlern in Martini.
Du kannst einen Middleware-Handler dem Stack folgendermaßen anfügen:
~~~ go
m.Use(func() {
  // durchlaufe die Middleware
})
~~~

Volle Kontrolle über den Middleware Stack erlangst Du mit der `Handlers`-Funktion.
Sie ersetzt jeden zuvor definierten Handler:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

Middleware Handler arbeiten gut mit Aspekten wie Logging, Berechtigungen, Authentifizierung, Sessions, Komprimierung durch gzip, Fehlerseiten und anderen Operationen zusammen, die vor oder nach einer Anfrage passieren.
~~~ go
// überprüfe einen API-Schlüssel
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://godoc.org/github.com/go-martini/martini#Context) ist eine optionale Funktion, die Middleware-Handler aufrufen können, um sie nach dem Beenden der anderen Handler auszuführen. Dies funktioniert besonders gut, wenn Operationen nach einer HTTP-Anfrage ausgeführt werden müssen.
~~~ go
// protokolliere vor und nach einer Anfrage
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("vor einer Anfrage")

  c.Next()

  log.Println("nach einer Anfrage")
})
~~~

## Martini Env

Einige Martini-Handler machen von der globalen `martini.Env` Variable gebrauch, die der Entwicklungsumgebung erweiterte Funktionen bietet, welche die Produktivumgebung nicht enthält. Es wird empfohlen, die `MARTINI_ENV=production` Umgebungsvariable zu setzen, sobald der Martini-Server in den Live-Betrieb übergeht.

## FAQ

### Wo finde ich eine bestimmte Middleware?

Starte die Suche mit einem Blick in die Projekte von [martini-contrib](https://github.com/martini-contrib). Solltest Du nicht fündig werden, kontaktiere ein Mitglied des martini-contrib Teams, um eine neue Repository anzulegen.

 * [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler zum Parsen des `Accept-Language` HTTP-Header.
 * [accessflags](https://github.com/martini-contrib/accessflags) - Handler zur Ermöglichung von Zugriffskontrollen.
 * [auth](https://github.com/martini-contrib/auth) - Handler zur Authentifizierung.
 * [binding](https://github.com/martini-contrib/binding) - Handler zum Zuordnen/Validieren einer Anfrage zu einem Struct.
 * [cors](https://github.com/martini-contrib/cors) - Handler für CORS-Support.
 * [csrf](https://github.com/martini-contrib/csrf) - CSRF-Schutz für Applikationen
 * [encoder](https://github.com/martini-contrib/encoder) - Enkodierungsservice zum Datenrendering in den verschiedensten Formaten.
 * [gzip](https://github.com/martini-contrib/gzip) - Handler zum Ermöglichen von gzip-Kompression bei HTTP-Anfragen.
 * [gorelic](https://github.com/martini-contrib/gorelic) - NewRelic Middleware
 * [logstasher](https://github.com/martini-contrib/logstasher) - Middlewaredie Logstashkompatibles JSON ausgibt
 * [method](https://github.com/martini-contrib/method) - Überschreibe eine HTTP-Method via Header oder Formularfelder.
 * [oauth2](https://github.com/martini-contrib/oauth2) - Handler der den Login mit OAuth 2.0 in Martinianwendungen ermöglicht. Google Sign-in, Facebook Connect und Github werden ebenfalls unterstützt.
 * [permissions2](https://github.com/xyproto/permissions2) - Handler zum Mitverfolgen von Benutzern, Loginstatus und Berechtigungen.
 * [render](https://github.com/martini-contrib/render) - Handler, der einen einfachen Service zum Rendern von JSON und HTML-Templates bereitstellt.
 * [secure](https://github.com/martini-contrib/secure) - Implementation von Sicherheitsfunktionen
 * [sessions](https://github.com/martini-contrib/sessions) - Handler mit einem Session service.
 * [sessionauth](https://github.com/martini-contrib/sessionauth) - Handler zur einfachen Aufforderung eines Logins für Routes und zur Bearbeitung von Benutzerlogins in der Sitzung
 * [strict](https://github.com/martini-contrib/strict) - Strikter Modus.
 * [strip](https://github.com/martini-contrib/strip) - URL-Prefix Stripping.
 * [staticbin](https://github.com/martini-contrib/staticbin) - Handler for serving static files from binary data
 * [throttle](https://github.com/martini-contrib/throttle) - Middleware zum Drosseln von HTTP-Anfragen.
 * [vauth](https://github.com/rafecolton/vauth) - Handler zur Webhook-Authentifizierung (momentan nur GitHub und TravisCI)
 * [web](https://github.com/martini-contrib/web) - hoisie web.go's Kontext

### Wie integriere ich in bestehende Systeme?

Eine Martiniinstanz implementiert `http.Handler`, sodass Subrouten in bestehenden Servern einfach genutzt werden können. Hier ist eine funktionierende Martinianwendungen für die Google App Engine:

~~~ go
package hello

import (
  "net/http"
  "github.com/go-martini/martini"
)

func init() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hallo Welt!"
  })
  http.Handle("/", m)
}
~~~

### Wie ändere ich den Port/Host?

Martinis `Run` Funktion sucht automatisch nach den PORT und HOST Umgebungsvariablen, um diese zu nutzen. Andernfalls ist localhost:3000 voreingestellt.
Für mehr Flexibilität über den Port und den Host nutze stattdessen die `martini.RunOnAddr` Funktion.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### Automatisches Aktualisieren?

[Gin](https://github.com/codegangsta/gin) und [Fresh](https://github.com/pilu/fresh) aktualisieren Martini-Apps live.

## Bei Martini mitwirken

Martinis Maxime ist Minimalismus und sauberer Code. Die meisten Beiträge sollten sich in den Repositories der [martini-contrib](https://github.com/martini-contrib) Gruppe wiederfinden. Beinhaltet Dein Beitrag Veränderungen am Kern von Martini, zögere nicht, einen Pull Request zu machen.

## Über das Projekt

Inspiriert von [Express](https://github.com/visionmedia/express) und [Sinatra](https://github.com/sinatra/sinatra)

Martini wird leidenschaftlich von niemand Geringerem als dem [Code Gangsta](http://codegangsta.io/) entwickelt


================================================
FILE: translations/README_es_ES.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

Martini es un poderoso paquete para escribir rápidamente aplicaciones/servicios web modulares en Golang.


## Vamos a iniciar

Después de instalar Go y de configurar su [GOPATH](http://golang.org/doc/code.html#GOPATH), cree su primer archivo `.go`. Vamos a llamar a este `server.go`.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hola Mundo!"
  })
  m.Run()
}
~~~

Luego instale el paquete Martini (Es necesario **go 1.1** o superior):
~~~
go get github.com/go-martini/martini
~~~

Después corra su servidor:
~~~
go run server.go
~~~

Ahora tendrá un webserver Martini corriendo en el puerto `localhost:3000`.

## Obtenga ayuda

Suscribase a la [Lista de email](https://groups.google.com/forum/#!forum/martini-go)

Observe el [Video demostrativo](http://martini.codegangsta.io/#demo)

Use la etiqueta [martini](http://stackoverflow.com/questions/tagged/martini) para preguntas en Stackoverflow

Documentación [GoDoc](http://godoc.org/github.com/go-martini/martini)


## Caracteríticas
* Extremadamente simple de usar.
* Diseño no intrusivo.
* Buena integración con otros paquetes Golang.
* Enrutamiento impresionante.
* Diseño modular - Fácil de añadir y remover funcionalidades.
* Muy buen uso de handlers/middlewares.
* Grandes características innovadoras.
* **Compatibilidad total con la interface [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc).**
* Sirviendo documentos por defecto (e.g. para servir aplicaciones AngularJS en modo HTML5).

## Más Middlewares
Para más middlewares y funcionalidades, revisar los repositorios en [martini-contrib](https://github.com/martini-contrib).

## Lista de contenidos
* [Classic Martini](#classic-martini)
  * [Handlers](#handlers)
  * [Routing](#routing)
  * [Services](#services)
  * [Serving Static Files](#serving-static-files)
* [Middleware Handlers](#middleware-handlers)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
Para iniciar rápidamente, [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) prevee algunas herramientas que funcionan bien para la mayoría de aplicaciones web:
~~~ go
  m := martini.Classic()
  // middlewares y rutas aquí
  m.Run()
~~~

Algunas funcionalidades que [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) ofrece automáticamente son:
  * Request/Response Logging - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Static File serving - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Routing - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Handlers
Handlers son el corazón y el alma de Martini. Un handler es básicamente cualquier tipo de función que puede ser llamada.
~~~ go
m.Get("/", func() {
  println("hola mundo")
})
~~~

#### Retorno de Valores
Si un handler retorna cualquier cosa, Martini escribirá el valor retornado como una cadena [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter):
~~~ go
m.Get("/", func() string {
  return "hola mundo" // HTTP 200 : "hola mundo"
})
~~~

Usted también puede retornar un código de estado:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "soy una tetera" // HTTP 418 : "soy una tetera"
})
~~~

#### Inyección de Servicios
Handlers son invocados vía reflexión. Martini utiliza *Inyección de Dependencia* para resolver dependencias en la lista de argumentos Handlers. **Esto hace que Martini sea completamente compatible con  la interface `http.HandlerFunc` de golang.**

Si agrega un argumento a su Handler, Martini buscará en su lista de servicios e intentará resolver su dependencia vía su tipo de aserción:
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res y req son inyectados por Martini
  res.WriteHeader(200) // HTTP 200
})
~~~

Los siguientes servicios son incluidos con [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):
  * [*log.Logger](http://godoc.org/log#Logger) - Log Global para Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request context.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` de nombres de los parámetros buscados por la ruta.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Servicio de ayuda para las Rutas.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response escribe la interfaz.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request.

### Rutas
En Martini, una ruta es un método HTTP emparejado con un patrón URL. Cada ruta puede tener uno o más métodos handler:
~~~ go
m.Get("/", func() {
  // mostrar algo
})

m.Patch("/", func() {
  // actualizar algo
})

m.Post("/", func() {
  // crear algo
})

m.Put("/", func() {
  // reemplazar algo
})

m.Delete("/", func() {
  // destruir algo
})

m.Options("/", func() {
  // opciones HTTP
})

m.NotFound(func() {
  // manipula 404
})
~~~

Las rutas son emparejadas en el orden en que son definidas. La primera ruta que coincide con la solicitud es invocada.

Los patrones de rutas puede incluir nombres como parámetros accesibles vía el servicio [martini.Params](http://godoc.org/github.com/go-martini/martini#Params):
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

Las rutas se pueden combinar con globs:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

Las expresiones regulares pueden ser usadas también:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
Observe la [documentación](http://golang.org/pkg/regexp/syntax/) para mayor información sobre la sintaxis de expresiones regulares.


Handlers de ruta pueden ser apilados encima de otros, lo cual es útil para cosas como autenticación y autorización:
~~~ go
m.Get("/secret", authorize, func() {
  // será ejecutado cuando autorice escribir una respuesta
})
~~~

Grupos de rutas puede ser añadidas usando el método Group.
~~~ go
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)
})
~~~

Al igual que usted puede pasar middlewares a un handler, puede pasar middlewares a grupos.
~~~ go
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)
~~~

### Servicios
Lo servicios son objetos que están disponibles para ser inyectados en una lista de argumentos Handler. Usted puede mapear un servicio a nivel *Global* o *Request*.

#### Mapeo Global
Una instancia de Martini implementa la interface `inject.Injector`, asi que el mapeo de un servicio es sencillo:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // el servicio estará disponible para todos los handlers como *MyDatabase.
// ...
m.Run()
~~~

#### Mapeo por Request
El mapeo a nivel de request puede ser hecho en un handler via  [martini.Context](http://godoc.org/github.com/go-martini/martini#Context):
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // mapeado como *MyCustomLogger
}
~~~

#### Valores de Mapeo para Interfaces
Una de las partes más poderosas sobre servicios es la capacidad de mapear un servicio para una interface. Por ejemplo, si desea sobreescribir [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) con un objeto que envuelva y realice operaciones extra, puede escribir el siguiente handler:
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // sobreescribir ResponseWriter con nuestro ResponseWriter
}
~~~

### Sirviendo Archivos Estáticos
Una instancia de [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) sirve automáticamente archivos estáticos del directorio "public" en la raíz de su servidor.
Usted puede servir más directorios, añadiendo más [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) handlers.
~~~ go
m.Use(martini.Static("assets")) // sirviendo los archivos del directorio "assets"
~~~

## Middleware Handlers
Los Middleware Handlers se sitúan entre una solicitud HTTP y un router. En esencia, ellos no son diferentes de cualquier otro Handler en Martini. Usted puede añadir un handler de middleware para la pila de la siguiente forma:
~~~ go
m.Use(func() {
  // Hacer algo con middleware
})
~~~

Puede tener el control total sobre la pila del Middleware con la función `Handlers`. Esto reemplazará a cualquier handler que haya sido establecido previamente:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

Middleware Handlers trabaja realmente bien como logging, autorización, autenticación, sesión, gzipping, páginas de errores y una serie de otras operaciones que deben suceder antes o después de una solicitud http:
~~~ go
// Valida una llave de api
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://godoc.org/github.com/go-martini/martini#Context) es una función opcional que Middleware Handlers puede llamar para entregar hasta después de que una solicitud http haya sido ejecutada. Esto trabaja muy bien para calquier operación que debe suceder luego de una solicitud http:
~~~ go
// log antes y después de una solicitud
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("antes de una solicitud")

  c.Next()

  log.Println("luego de una solicitud")
})
~~~

## Martini Env

Martini handlers hace uso de `martini.Env`, una variable global para proveer funcionalidad especial en ambientes de desarrollo y ambientes de producción. Es recomendado que una variable `MARTINI_ENV=production` sea definida cuando se despliegue en un ambiente de producción.

## FAQ

### ¿Dónde puedo encontrar una middleware X?

Inicie su búsqueda en los proyectos [martini-contrib](https://github.com/martini-contrib). Si no esta allí, no dude en contactar a algún miembro del equipo martini-contrib para adicionar un nuevo repositorio para la organización.

* [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler para analizar el `Accept-Language` HTTP header.
* [accessflags](https://github.com/martini-contrib/accessflags) - Handler para habilitar Access Control.
* [auth](https://github.com/martini-contrib/auth) - Handlers para autenticación.
* [binding](https://github.com/martini-contrib/binding) - Handler para mapeo/validación de un request en una estructura.
* [cors](https://github.com/martini-contrib/cors) - Handler habilita soporte para CORS.
* [csrf](https://github.com/martini-contrib/csrf) - CSRF protección para aplicaciones.
* [encoder](https://github.com/martini-contrib/encoder) - Servicio de codificador para renderizado de datos en varios formatos y gestión de contenidos.
* [gzip](https://github.com/martini-contrib/gzip) - Handler para agregar compresión gzip para los requests.
* [gorelic](https://github.com/martini-contrib/gorelic) - NewRelic middleware
* [logstasher](https://github.com/martini-contrib/logstasher) - Middleware que imprime logstash-compatiable JSON.
* [method](https://github.com/martini-contrib/method) - HTTP method overriding via cabecera o campos de formulario.
* [oauth2](https://github.com/martini-contrib/oauth2) - Handler que provee OAuth 2.0 login para Martini apps. Google Sign-in, Facebook Connect y Github login son soportados.
* [permissions2](https://github.com/xyproto/permissions2) - Handler para hacer seguimiento de usuarios, estados de login y permisos.
* [render](https://github.com/martini-contrib/render) - Handler que provee un servicio para fácil renderizado de plantillas HTML y JSON.
* [secure](https://github.com/martini-contrib/secure) - Implementa un par de rápidos triunfos de seguridad.
* [sessions](https://github.com/martini-contrib/sessions) - Handler que provee un servicio de sesiones.
* [sessionauth](https://github.com/martini-contrib/sessionauth) - Handler que provee una simple forma de hacer routes, requerir un login y manejar login de usuarios en la sesión.
* [strict](https://github.com/martini-contrib/strict) - Modo estricto (Strict Mode)
* [strip](https://github.com/martini-contrib/strip) - Prefijo de extracción de URL.
* [staticbin](https://github.com/martini-contrib/staticbin) - Handler para servir archivos estáticos desde datos binarios.
* [throttle](https://github.com/martini-contrib/throttle) - Request rate throttling middleware.
* [vauth](https://github.com/rafecolton/vauth) - Handlers para expender autenticación con webhooks (actualmente GitHub y TravisCI)
* [web](https://github.com/martini-contrib/web) - Contexto hoisie web.go's

### ¿Cómo se integra con los servidores existentes?

Una instancia de Martini implementa `http.Handler`, de modo que puede ser fácilmente utilizado para servir sub-rutas y directorios en servidores Go existentes. Por ejemplo, este es un aplicativo Martini trabajando para Google App Engine:

~~~ go
package hello

import (
  "net/http"
  "github.com/go-martini/martini"
)

func init() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hola Mundo!"
  })
  http.Handle("/", m)
}
~~~

### ¿Cómo cambiar el puerto/host?

La función `Run` de Martini observa las variables de entorno `PORT` y `HOST` para utilizarlas. De lo contrário, Martini asume por defecto `localhost:3000`. Para tener mayor flexibilidad sobre el puerto y host, use la función `martini.RunOnAddr`.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### ¿Servidor con autoreload?

[gin](https://github.com/codegangsta/gin) y [fresh](https://github.com/pilu/fresh) son ambas aplicaciones para autorecarga de Martini.

## Contribuyendo
Martini se desea mantener pequeño y limpio. La mayoría de contribuciones deben realizarse en el repositorio [martini-contrib](https://github.com/martini-contrib). Si desea hacer una contribución al core de Martini es libre de realizar un Pull Request.

## Sobre

Inspirado por [Express](https://github.com/visionmedia/express) y [Sinatra](https://github.com/sinatra/sinatra)

Martini está diseñado obsesivamente por nada menos que [Code Gangsta](http://codegangsta.io/)



================================================
FILE: translations/README_fr_FR.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

Martini est une puissante bibliothèque pour développer rapidement des applications et services web en Golang.


## Pour commencer

Après avoir installé Go et configuré le chemin d'accès pour [GOPATH](http://golang.org/doc/code.html#GOPATH), créez votre premier fichier '.go'. Nous l'appellerons 'server.go'.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello world!"
  })
  m.Run()
}
~~~

Installez ensuite le paquet Martini (**go 1.1** ou supérieur est requis) :

~~~
go get github.com/go-martini/martini
~~~

La commande suivante vous permettra de lancer votre serveur :
~~~
go run server.go
~~~

Vous avez à présent un serveur web Martini à l'écoute sur l'adresse et le port suivants : `localhost:3000`.

## Besoin d'aide
- Souscrivez à la [Liste d'emails](https://groups.google.com/forum/#!forum/martini-go)
- Regardez les vidéos [Demo en vidéo](http://martini.codegangsta.io/#demo)
- Posez vos questions sur StackOverflow.com en utilisant le tag [martini](http://stackoverflow.com/questions/tagged/martini)
- La documentation GoDoc [documentation](http://godoc.org/github.com/go-martini/martini)


## Caractéristiques
* Simple d'utilisation
* Design non-intrusif
* Compatible avec les autres paquets Golang
* Gestionnaire d'URL et routeur disponibles
* Modulable, permettant l'ajout et le retrait de fonctionnalités
* Un grand nombre de handlers/middlewares disponibles
* Prêt pour une utilisation immédiate
* **Entièrement compatible avec l'interface [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc).**

## Plus de Middleware
Pour plus de middlewares et de fonctionnalités, consultez le dépôt [martini-contrib](https://github.com/martini-contrib).

## Table des matières
* [Classic Martini](#classic-martini)
  * [Handlers](#handlers)
  * [Routage](#routing)
  * [Services](#services)
  * [Serveur de fichiers statiques](#serving-static-files)
* [Middleware Handlers](#middleware-handlers)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
Pour vous faire gagner un temps précieux, [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) est configuré avec des paramètres qui devraient couvrir les besoins de la plupart des applications web :

~~~ go
  m := martini.Classic()
  // ... les middlewares and le routage sont insérés ici...
  m.Run()
~~~

Voici quelques handlers/middlewares que [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) intègre par défault :
  * Logging des requêtes/réponses - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Récupération sur erreur - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Serveur de fichiers statiques - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Routage - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Handlers
Les Handlers sont le coeur et l'âme de Martini. N'importe quelle fonction peut être utilisée comme un handler.
~~~ go
m.Get("/", func() {
  println("hello world")
})
~~~

#### Valeurs retournées
Si un handler retourne une valeur, Martini écrira le résultat dans l'instance [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) courante sous forme de ```string```:
~~~ go
m.Get("/", func() string {
  return "hello world" // HTTP 200 : "hello world"
})
~~~
Vous pouvez aussi optionnellement renvoyer un code de statut HTTP :
~~~ go
m.Get("/", func() (int, string) {
  return 418, "i'm a teapot" // HTTP 418 : "i'm a teapot"
})
~~~

#### Injection de services
Les handlers sont appelés via réflexion. Martini utilise "l'injection par dépendance" pour résoudre les dépendances des handlers dans la liste d'arguments. **Cela permet à Martini d'être parfaitement compatible avec l'interface golang ```http.HandlerFunc```.**

Si vous ajoutez un argument à votre Handler, Martini parcourera la liste des services et essayera de déterminer ses dépendances selon son type :
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
  res.WriteHeader(200) // HTTP 200
})
~~~
Les services suivants sont inclus avec [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):
  * [log.Logger](http://godoc.org/log#Logger) - Global logger for Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - Contexte d'une requête HTTP.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` contenant les paramètres retrouvés par correspondance des routes.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Service d'aide au routage.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - Interface d'écriture de réponses HTTP.
  * [*http.Request](http://godoc.org/net/http/#Request) - Requête HTTP.

### Routeur
Dans Martini, un chemin est une méthode HTTP liée à un modèle d'adresse URL.
Chaque chemin peut avoir un seul ou plusieurs méthodes *handler* :
~~~ go
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
})
~~~
Les chemins seront traités dans l'ordre dans lequel ils auront été définis. Le *handler* du premier chemin trouvé qui correspondra à la requête sera invoqué.


Les chemins peuvent inclure des paramètres nommés, accessibles avec le service [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) :
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

Les chemins peuvent correspondre à des globs :
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~
Les expressions régulières peuvent aussi être utilisées :
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
Jetez un oeil à la documentation [Go documentation](http://golang.org/pkg/regexp/syntax/) pour plus d'informations sur la syntaxe des expressions régulières.

Les handlers d'un chemins peuvent être superposés, ce qui s'avère particulièrement pratique pour des tâches comme la gestion de l'authentification et des autorisations :
~~~ go
m.Get("/secret", authorize, func() {
  // this will execute as long as authorize doesn't write a response
})
~~~

Un groupe de chemins peut aussi être ajouté en utilisant la méthode ```Group``` :
~~~ go
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)
})
~~~

Comme vous pouvez passer des middlewares à un handler, vous pouvez également passer des middlewares à des groupes :
~~~ go
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)
~~~

### Services
Les services sont des objets injectés dans la liste d'arguments d'un handler. Un service peut être défini pour une *requête*, ou de manière *globale*.


#### Global Mapping
Les instances Martini implémentent l'interace inject.Injector, ce qui facilite grandement le mapping de services :
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // the service will be available to all handlers as *MyDatabase
// ...
m.Run()
~~~

#### Requête-Level Mapping
Pour une déclaration au niveau d'une requête, il suffit d'utiliser un handler via [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) :
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // mapped as *MyCustomLogger
}
~~~

#### Mapping de valeurs à des interfaces
L'un des aspects les plus intéressants des services réside dans le fait qu'ils peuvent être liés à des interfaces. Par exemple, pour surcharger [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) avec un objet qui l'enveloppe et étend ses fonctionnalités, vous pouvez utiliser le handler suivant :
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // override ResponseWriter with our wrapper ResponseWriter
}
~~~

### Serveur de fichiers statiques
Une instance [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) est déjà capable de servir les fichiers statiques qu'elle trouvera dans le dossier *public* à la racine de votre serveur.
Vous pouvez indiquer d'autres dossiers sources à l'aide du handler  [martini.Static](http://godoc.org/github.com/go-martini/martini#Static).
~~~ go
m.Use(martini.Static("assets")) // serve from the "assets" directory as well
~~~

## Les middleware Handlers
Les *middleware handlers* sont placés entre la requête HTTP entrante et le routeur. Ils ne sont aucunement différents des autres handlers présents dans Martini. Vous pouvez ajouter un middleware handler comme ceci :
~~~ go
m.Use(func() {
  // do some middleware stuff
})
~~~
Vous avez un contrôle total sur la structure middleware avec la fonction ```Handlers```. Son exécution écrasera tous les handlers configurés précédemment :
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~
Middleware Handlers est très pratique pour automatiser des fonctions comme le logging, l'autorisation, l'authentification, sessions, gzipping, pages d'erreur, et toutes les opérations qui se font avant ou après chaque requête HTTP :
~~~ go
// 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() (Suivant)
[Context.Next()](http://godoc.org/github.com/go-martini/martini#Context) est une fonction optionnelle que les Middleware Handlers peuvent appeler pour patienter jusqu'à ce que tous les autres handlers aient été exécutés. Cela fonctionne très bien pour toutes opérations qui interviennent après une requête HTTP :
~~~ go
// log before and after a request
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("avant la requête")

  c.Next()

  log.Println("après la requête")
})
~~~

## Martini Env
Plusieurs Martini handlers utilisent 'martini.Env' comme variable globale pour fournir des fonctionnalités particulières qui diffèrent entre l'environnement de développement et l'environnement de production. Il est recommandé que la variable 'MARTINI_ENV=production' soit définie pour déployer un serveur Martini en environnement de production.

## FAQ (Foire aux questions)

### Où puis-je trouver des middleware ?
Commencer par regarder dans le [martini-contrib](https://github.com/martini-contrib) projet. S'il n'y est pas, n'hésitez pas à contacter un membre de l'équipe martini-contrib pour ajouter un nouveau dépôt à l'organisation.

* [auth](https://github.com/martini-contrib/auth) - Handlers for authentication.
* [binding](https://github.com/martini-contrib/binding) - Handler for mapping/validating a raw request into a structure.
* [gzip](https://github.com/martini-contrib/gzip) - Handler for adding gzip compress to requests
* [render](https://github.com/martini-contrib/render) - Handler that provides a service for easily rendering JSON and HTML templates.
* [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler for parsing the `Accept-Language` HTTP header.
* [sessions](https://github.com/martini-contrib/sessions) - Handler that provides a Session service.
* [strip](https://github.com/martini-contrib/strip) - URL Prefix stripping.
* [method](https://github.com/martini-contrib/method) - HTTP method overriding via Header or form fields.
* [secure](https://github.com/martini-contrib/secure) - Implements a few quick security wins.
* [encoder](https://github.com/martini-contrib/encoder) - Encoder service for rendering data in several formats and content negotiation.
* [cors](https://github.com/martini-contrib/cors) - Handler that enables CORS support.
* [oauth2](https://github.com/martini-contrib/oauth2) - Handler that provides OAuth 2.0 login for Martini apps. Google Sign-in, Facebook Connect and Github login is supported.
* [vauth](https://github.com/rafecolton/vauth) - Handlers for vender webhook authentication (currently GitHub and TravisCI)

### Comment puis-je m'intègrer avec des serveurs existants ?
Une instance Martini implémente ```http.Handler```. Elle peut donc utilisée pour alimenter des sous-arbres sur des serveurs Go existants. Voici l'exemple d'une application Martini pour Google App Engine :

~~~ go
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)
}
~~~

### Comment changer le port/adresse ?

La fonction ```Run``` de Martini utilise le port et l'adresse spécifiés dans les variables d'environnement. Si elles ne peuvent y être trouvées, Martini utilisera *localhost:3000* par default.
Pour avoir plus de flexibilité sur le port et l'adresse, utilisez la fonction `martini.RunOnAddr` à la place.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### Rechargement du code en direct ?

[gin](https://github.com/codegangsta/gin) et [fresh](https://github.com/pilu/fresh) sont tous les capables de recharger le code des applications martini chaque fois qu'il est modifié.

## Contribuer
Martini est destiné à rester restreint et épuré. Toutes les contributions doivent finir dans un dépot dans l'organisation [martini-contrib](https://github.com/martini-contrib). Si vous avez une contribution pour le noyau de Martini, n'hésitez pas à envoyer une Pull Request.

## A propos de Martini

Inspiré par [express](https://github.com/visionmedia/express) et [Sinatra](https://github.com/sinatra/sinatra), Martini est l'oeuvre de nul d'autre que [Code Gangsta](http://codegangsta.io/), votre serviteur.


================================================
FILE: translations/README_ja_JP.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

MartiniはGolangによる、モジュール形式のウェブアプリケーション/サービスを作成するパワフルなパッケージです。

## はじめに

Goをインストールし、[GOPATH](http://golang.org/doc/code.html#GOPATH)を設定した後、Martiniを始める最初の`.go`ファイルを作りましょう。これを`server.go`とします。

~~~ 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のサーバが起動します。

## 分からないことがあったら?

[メーリングリスト](https://groups.google.com/forum/#!forum/martini-go)に入る

[デモビデオ](http://martini.codegangsta.io/#demo)をみる

Stackoverflowで[martini tag](http://stackoverflow.com/questions/tagged/martini)を使い質問する

GoDoc [documentation](http://godoc.org/github.com/go-martini/martini)


## 特徴
* 非常にシンプルに使用できる
* 押し付けがましくないデザイン
* 他のGolangパッケージとの協調性
* 素晴らしいパスマッチングとルーティング
* モジュラーデザイン - 機能性の付け外しが簡単
* たくさんの良いハンドラ/ミドルウェア
* 優れた 'すぐに使える' 機能たち
* **[http.HandlerFunc](http://godoc.org/net/http#HandlerFunc)との完全な互換性**

## もっとミドルウェアについて知るには?
さらに多くのミドルウェアとその機能について知りたいときは、[martini-contrib](https://github.com/martini-contrib) オーガナイゼーションにあるリポジトリを確認してください。

## 目次(Table of Contents)
* [Classic Martini](#classic-martini)
  * [ハンドラ](#handlers)
  * [ルーティング](#routing)
  * [サービス](#services)
  * [静的ファイル配信](#serving-static-files)
* [ミドルウェアハンドラ](#middleware-handlers)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
立ち上げ、すぐ実行できるように、[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) はほとんどのウェブアプリケーションで機能する、標準的な機能を提供します。
~~~ go
  m := martini.Classic()
  // ... middleware and routing goes here
  m.Run()
~~~

下記が[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic)が自動的に読み込む機能の一覧です。
  * Request/Response Logging - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Static File serving - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Routing - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### ハンドラ
ハンドラはMartiniのコアであり、存在意義でもあります。ハンドラには基本的に、呼び出し可能な全ての関数が適応できます。
~~~ go
m.Get("/", func() {
  println("hello world")
})
~~~

#### Return Values
もしハンドラが何かを返す場合、Martiniはその結果を現在の[http.ResponseWriter](http://godoc.org/net/http#ResponseWriter)にstringとして書き込みます。
~~~ go
m.Get("/", func() string {
  return "hello world" // HTTP 200 : "hello world"
})
~~~

任意でステータスコードを返すこともできます。
~~~ go
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によって解決しようと試みます。
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
  res.WriteHeader(200) // HTTP 200
})
~~~

[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic)にはこれらのサービスが内包されています:
  * [*log.Logger](http://godoc.org/log#Logger) - Martiniのためのグローバルなlogger.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request context.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string`型の、ルートマッチングによって検出されたパラメータ
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Route helper service.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response writer interface.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request.

### ルーティング
Martiniでは、ルーティングはHTTPメソッドとURL-matching patternによって対になっており、それぞれが一つ以上のハンドラメソッドを持つことができます。
~~~ go
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](http://godoc.org/github.com/go-martini/martini#Params)サービスを通じてアクセスすることができます:
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

ワイルドカードを使用することができます:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

正規表現も、このように使うことができます:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~

もっと正規表現の構文をしりたい場合は、[Go documentation](http://golang.org/pkg/regexp/syntax/) を見てください。


ハンドラは互いの上に積み重ねてることができます。これは、認証や承認処理の際に便利です:
~~~ go
m.Get("/secret", authorize, func() {
  // this will execute as long as authorize doesn't write a response
})
~~~

ルーティンググループも、Groupメソッドを使用することで追加できます。
~~~ go
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)
})
~~~

ハンドラにミドルウェアを渡せるのと同じように、グループにもミドルウェアを渡すことができます:
~~~ go
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のインターフェースを実装しています。なので、サービスをマッピングすることは簡単です:
~~~ go
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](http://godoc.org/github.com/go-martini/martini#Context)を使い、ハンドラ内で行うことができます:
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // mapped as *MyCustomLogger
}
~~~

#### Mapping values to Interfaces
サービスの最も強力なことの一つは、インターフェースにサービスをマッピングできる機能です。例えば、[http.ResponseWriter](http://godoc.org/net/http#ResponseWriter)を機能を追加して上書きしたい場合、このようにハンドラを書くことができます:
~~~ go
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()](http://godoc.org/github.com/go-martini/martini#Classic) インスタンスは、自動的にルート直下の "public" ディレクトリ以下の静的ファイルを配信します。[martini.Static](http://godoc.org/github.com/go-martini/martini#Static)を追加することで、もっと多くのディレクトリを配信することもできます:
~~~ go
m.Use(martini.Static("assets")) // serve from the "assets" directory as well
~~~

## ミドルウェア ハンドラ
ミドルウェア ハンドラは次に来るhttpリクエストとルーターの間に位置します。本質的には、その他のハンドラとの違いはありません。ミドルウェア ハンドラの追加はこのように行います:
~~~ go
m.Use(func() {
  // do some middleware stuff
})
~~~

`Handlers`関数を使えば、ミドルウェアスタックを完全に制御できます。これは以前に設定されている全てのハンドラを置き換えます:

~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

ミドルウェア ハンドラはロギング、認証、承認プロセス、セッション、gzipping、エラーページの表示、その他httpリクエストの前後で怒らなければならないような場合に素晴らしく効果を発揮します。
~~~ go
// 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://godoc.org/github.com/go-martini/martini#Context) は他のハンドラが実行されたことを取得するために使用する機能です。これはhttpリクエストのあとに実行したい任意の関数があるときに素晴らしく機能します:
~~~ go
// 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](https://github.com/martini-contrib)プロジェクトをみることから始めてください。もし望みのものがなければ、新しいリポジトリをオーガナイゼーションに追加するために、martini-contribチームのメンバーにコンタクトを取ってみてください。

* [auth](https://github.com/martini-contrib/auth) - Handlers for authentication.
* [binding](https://github.com/martini-contrib/binding) - Handler for mapping/validating a raw request into a structure.
* [gzip](https://github.com/martini-contrib/gzip) - Handler for adding gzip compress to requests
* [render](https://github.com/martini-contrib/render) - Handler that provides a service for easily rendering JSON and HTML templates.
* [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler for parsing the `Accept-Language` HTTP header.
* [sessions](https://github.com/martini-contrib/sessions) - Handler that provides a Session service.
* [strip](https://github.com/martini-contrib/strip) - URL Prefix stripping.
* [method](https://github.com/martini-contrib/method) - HTTP method overriding via Header or form fields.
* [secure](https://github.com/martini-contrib/secure) - Implements a few quick security wins.
* [encoder](https://github.com/martini-contrib/encoder) - Encoder service for rendering data in several formats and content negotiation.
* [cors](https://github.com/martini-contrib/cors) - Handler that enables CORS support.
* [oauth2](https://github.com/martini-contrib/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アプリです:

~~~ go
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`関数が役に立ちます:

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### Live code reload?

[gin](https://github.com/codegangsta/gin) と [fresh](https://github.com/pilu/fresh) 両方がMartiniアプリケーションを自動リロードできます。

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

## About

Inspired by [express](https://github.com/visionmedia/express) and [sinatra](https://github.com/sinatra/sinatra)

Martini is obsessively designed by none other than the [Code Gangsta](http://codegangsta.io/)


================================================
FILE: translations/README_ko_kr.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

마티니(Martini)는 강력하고 손쉬운 웹애플리케이션 / 웹서비스개발을 위한 Golang 패키지입니다.

## 시작하기

Go 인스톨 및 [GOPATH](http://golang.org/doc/code.html#GOPATH) 환경변수 설정 이후에, `.go` 파일 하나를 만들어 보죠..흠... 일단 `server.go`라고 부르겠습니다.
~~~go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello, 세계!"
  })
  m.Run()
}
~~~

마티니 패키지를 인스톨 합니다. (**go 1.1** 혹은 그 이상 버젼 필요):
~~~
go get github.com/go-martini/martini
~~~

이제 서버를 돌려 봅시다:
~~~
go run server.go
~~~

마티니 웹서버가 `localhost:3000`에서 돌아가고 있는 것을 확인하실 수 있을 겁니다.

## 도움이 필요하다면?

[메일링 리스트](https://groups.google.com/forum/#!forum/martini-go)에 가입해 주세요

[데모 비디오](http://martini.codegangsta.io/#demo)도 있어요.

혹은 Stackoverflow에 [마티니 태크](http://stackoverflow.com/questions/tagged/martini)를 이용해서 물어봐 주세요

GoDoc [문서(documentation)](http://godoc.org/github.com/go-martini/martini)

문제는 전부다 영어로 되어 있다는 건데요 -_-;;;
나는 한글 아니면 보기 싫다! 하는 분들은 아래 링크를 참조하세요
- [golang-korea](https://code.google.com/p/golang-korea/)
- 혹은 ([RexK](http://github.com/RexK))의 이메일로 연락주세요.

## 주요기능
* 사용하기 엄청 쉽습니다.
* 비간섭(Non-intrusive) 디자인
* 다른 Golang 패키지들과 잘 어울립니다.
* 끝내주는 경로 매칭과 라우팅.
* 모듈형 디자인 - 기능추가가 쉽고, 코드 꺼내오기도 쉬움.
* 유용한 핸들러와 미들웨어가 많음.
* 훌륭한 패키지화(out of the box) 기능들
* **[http.HandlerFunc](http://godoc.org/net/http#HandlerFunc) 인터페이스와 호환율 100%**

## 미들웨어(Middleware)
미들웨어들과 추가기능들은 [martini-contrib](https://github.com/martini-contrib)에서 확인해 주세요.

## 목차
* [Classic Martini](#classic-martini)
  * [핸들러](#핸들러handlers)
  * [라우팅](#라우팅routing)
  * [서비스](#서비스services)
  * [정적파일 서빙](#정적파일-서빙serving-static-files)
* [미들웨어 핸들러](#미들웨어-핸들러middleware-handlers)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
마티니를 쉽고 빠르게 이용하시려면, [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic)를 이용해 보세요. 보통 웹애플리케이션에서 사용하는 설정들이 이미 포함되어 있습니다.
~~~ go
  m := martini.Classic()
  // ... 미들웨어와 라우팅 설정은 이곳에 오면 작성하면 됩니다.
  m.Run()
~~~

아래는 [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic)에 자동으로 제공되는 기본 기능들 입니다.

  * Request/Response 로그 기능 - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * 패닉 리커버리 (Panic Recovery) - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * 정적 파일 서빙 - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * 라우팅(Routing) - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### 핸들러(Handlers)

핸들러(Handlers)는 마티니의 핵심입니다. 핸들러는 기본적으로 실행 가능한 모든 형태의 함수들입니다.
~~~ go
m.Get("/", func() {
  println("hello 세계")
})
~~~

#### 반환 값 (Return Values)
핸들러가 반환을 하는 함수라면, 마티니는 반환 값을 [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter)에 스트링으로 입력 할 것입니다.
~~~ go
m.Get("/", func() string {
  return "hello 세계" // HTTP 200 : "hello 세계"
})
~~~

원하신다면, 선택적으로 상태코드도 함께 반환 할 수 있습니다.
~~~ go
m.Get("/", func() (int, string) {
  return 418, "난 주전자야!" // HTTP 418 : "난 주전자야!"
})
~~~

#### 서비스 주입(Service Injection)
핸들러들은 리플렉션을 통해 호출됩니다. 마티니는 *의존성 주입*을 이용해서 핸들러의 인수들을 주입합니다. **이것이 마티니를 `http.HandlerFunc` 인터페이스와 100% 호환할 수 있게 해줍니다.**

핸들러의 인수를 입력했다면, 마티니가 서비스 목록들을 살펴본 후 타입확인(type assertion)을 통해 의존성문제 해결을 시도 할 것입니다.
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res와 req는 마티니에 의해 주입되었다.
  res.WriteHeader(200) // HTTP 200
})
~~~

아래 서비스들은 [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):에 포함되어 있습니다.
  * [*log.Logger](http://godoc.org/log#Logger) - 마티니의 글로벌(전역) 로그.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http 요청 컨텍스트.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - 루트 매칭으로 찾은 인자를 `map[string]string`으로 변형.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - 루트 도우미 서비스.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response writer 인터페이스.
  * [*http.Request](http://godoc.org/net/http/#Request) - http 리퀘스트.

### 라우팅(Routing)
마티니에서 루트는 HTTP 메소드와 URL매칭 패턴의 페어입니다.
각 루트는 하나 혹은 그 이상의 핸들러 메소드를 가질 수 있습니다.
~~~ go
m.Get("/", func() {
  // 보여줘 봐
})

m.Patch("/", func() {
  // 업데이트 좀 해
})

m.Post("/", func() {
  // 만들어봐
})

m.Put("/", func() {
  // 변경해봐
})

m.Delete("/", func() {
  // 없애버려!
})

m.Options("/", func() {
  // http 옵션 메소드
})

m.NotFound(func() {
  // 404 해결하기
})
~~~

루트들은 정의된 순서대로 매칭된다. 들어온 요구에 처음으로 매칭된 루트가 호출된다.

루트 패턴은 [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) service로 액세스 가능한 인자들을 포함하기도 한다:
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]			// :name을 Params인자에서 추출
})
~~~

루트는 별표식(\*)으로 매칭 될 수도 있습니다:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

정규식도 사용가능합니다:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
정규식에 관하여 더 자세히 알고 싶다면 [Go documentation](http://golang.org/pkg/regexp/syntax/)을 참조해 주세요.

루트 핸들러는 스택을 쌓아 올릴 수 있습니다. 특히 유저 인증작업이나, 허가작업에 유용히 쓰일 수 있죠.
~~~ go
m.Get("/secret", authorize, func() {
  // 이 함수는 authorize 함수가 resopnse에 결과를 쓰지 않는이상 실행 될 거에요.
})
~~~

```RootGroup```은 루트들을 한 곳에 모아 정리하는데 유용합니다.
~~~ go
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)
})
~~~

핸들러에 미들웨어를 집어넣을 수 있는것과 같이, 그룹에도 미들웨어를 집어넣는 것이 가능합니다.
~~~ go
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)
~~~

### 서비스(Services)
서비스는 핸들러의 인수목록에 주입 될 수 있는 오브젝트들을 말합니다. 서비스는 *글로벌* 혹은 *리퀘스트* 레벨단위로 주입이 가능합니다.

#### 글로벌 맵핑(Global Mapping)
마타니 인스턴스는 서비스 맵핑을 쉽게 하기 위해서 inject.Injector 인터페이스를 반형합니다:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // 서비스가 모든 핸들러에서 *MyDatabase로서 사용될 수 있습니다.
// ...
m.Run()
~~~

#### 리퀘스트 레벨 맵핑(Request-Level Mapping)
리퀘스트 레벨 맵핑은 핸들러안에서 [martini.Context](http://godoc.org/github.com/go-martini/martini#Context)를 사용하면 됩니다:
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // *MyCustomLogger로서 맵핑 됨
}
~~~

#### 인터페이스로 값들 맵핑(Mapping values to Interfaces)
서비스의 강력한 기능중 하나는 서비스를 인터페이스로 맵핑이 가능하다는 것입니다. 예를들어, [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter)를 재정의(override)해서 부가 기능들을 수행하게 하고 싶으시다면, 아래와 같이 핸들러를 작성 하시면 됩니다.

~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // ResponseWriter를 NewResponseWriter로 치환(override)
}
~~~

### 정적파일 서빙(Serving Static Files)
[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) 인스턴스는 "public" 폴더안에 있는 파일들을 정적파일로써 자동으로 서빙합니다. 더 많은 폴더들은 정적파일 폴더에 포함시키시려면 [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) 핸들러를 이용하시면 됩니다.

~~~ go
m.Use(martini.Static("assets")) // "assets" 폴더에서도 정적파일 서빙.
~~~

## 미들웨어 핸들러(Middleware Handlers)
미들웨어 핸들러는 http request와 라우팅 사이에서 작동합니다. 미들웨어 핸들러는 근본적으로 다른 핸들러들과는 다릅니다. 사용방법은 아래와 같습니다:
~~~ go
m.Use(func() {
  // 미들웨어 임무 수행!
})
~~~

`Handlers`를 이용하여 미들웨어 스택들의 완전 컨트롤이 가능합니다. 다만, 이렇게 설정하시면 이전에 `Handlers`를 이용하여 설정한 핸들러들은 사라집니다:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

미들웨어 핸들러는 로깅(logging), 허가(authorization), 인가(authentication), 세션, 압축(gzipping), 에러 페이지 등 등, http request의 전후로 실행되어야 할 일들을 처리하기 아주 좋습니다:
~~~ go
// API 키 확인작업
m.Use(func(res http.ResponseWriter, req *http.Request) {
  if req.Header.Get("X-API-KEY") != "비밀암호!!!" {
    res.WriteHeader(http.StatusUnauthorized)	// HTTP 401
  }
})
~~~

### Next()
[Context.Next()](http://godoc.org/github.com/go-martini/martini#Context)는  선택적 함수입니다. 이 함수는 http request가 다 작동 될때까지 기다립니다.따라서 http request 이후에 실행 되어야 할 업무들을 수행하기 좋은 함수입니다.
~~~ go
// log before and after a request
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("request전입니다.")

  c.Next()

  log.Println("request후 입니다.")
})
~~~

## Martini Env
마티니 핸들러들은 `martini.Env` 글로벌 변수를 사용하여 개발환경에서는 프로덕션 환경과는 다르게 작동하기도 합니다. 따라서, 프로덕션 서버로 마티니 서버를 배포하시게 된다면 꼭 환경변수 `MARTINI_ENV=production`를 세팅해주시기 바랍니다.

## FAQ

### 미들웨어들을 어디서 찾아야 하나요?

깃헙에서 [martini-contrib](https://github.com/martini-contrib) 프로젝트들을 찾아보세요. 만약에 못 찾으시겠으면, martini-contrib 팀원들에게 연락해서 하나 만들어 달라고 해보세요.
* [auth](https://github.com/martini-contrib/auth) - 인증작업을 도와주는 핸들러.
* [binding](https://github.com/martini-contrib/binding) - request를 맵핑하고 검사하는 핸들러.
* [gzip](https://github.com/martini-contrib/gzip) - gzip 핸들러.
* [render](https://github.com/martini-contrib/render) - HTML 템플레이트들과 JSON를 사용하기 편하게 해주는 핸들러.
* [acceptlang](https://github.com/martini-contrib/acceptlang) - `Accept-Language` HTTP 해더를 파싱 할 때 유용한 핸들러.
* [sessions](https://github.com/martini-contrib/sessions) - 세션 서비스를 제공하는 핸들러.
* [strip](https://github.com/martini-contrib/strip) - URL 프리틱스를 없애주는 핸들러.
* [method](https://github.com/martini-contrib/method) - 해더나 폼필드를 이용한 HTTP 메소드 치환.
* [secure](https://github.com/martini-contrib/secure) - 몇몇 보안설정을 위한 핸들러.
* [encoder](https://github.com/martini-contrib/encoder) - 데이터 렌더링과 컨텐트 타입을위한 인코딩 서비스.
* [cors](https://github.com/martini-contrib/cors) - CORS 서포트를 위한 핸들러.
* [oauth2](https://github.com/martini-contrib/oauth2) - OAuth2.0 로그인 핸들러. 페이스북, 구글, 깃헙 지원.

### 현재 작동중인 서버에 마티니를 적용하려면?

마티니 인스턴스는 `http.Handler` 인터페이스를 차용합니다. 따라서 Go 서버 서브트리로 쉽게 사용될 수 있습니다. 아래 코드는 구글 앱 엔진에서 작동하는 마티니 앱입니다:

~~~ go
package hello

import (
  "net/http"
  "github.com/go-martini/martini"
)

func init() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello 세계!"
  })
  http.Handle("/", m)
}
~~~

### 포트와 호스트는 어떻게 바꾸나요?

마티니의 `Run` 함수는 PORT와 HOST 환경변수를 이용하는데, 설정이 안되어 있다면 localhost:3000으로 설정 되어 집니다.
좀더 유연하게 설정을 하고 싶다면, `martini.RunOnAddr`를 활용해 주세요.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### 라이브 코드 리로드?

[gin](https://github.com/codegangsta/gin) 과 [fresh](https://github.com/pilu/fresh) 가 마티니 앱의 라이브 리로드를 도와줍니다.

## 공헌하기(Contributing)

마티니는 간단하고 가벼운 패키지로 남을 것입니다. 따라서 보통 대부분의 공헌들은 [martini-contrib](https://github.com/martini-contrib) 그룹의 저장소로 가게 됩니다. 만약 마티니 코어에 기여하고 싶으시다면 주저없이 Pull Request를 해주세요.

## About

[express](https://github.com/visionmedia/express) 와 [sinatra](https://github.com/sinatra/sinatra)의 영향을 받았습니다.

마티니는 [Code Gangsta](http://codegangsta.io/)가 디자인 했습니다.


================================================
FILE: translations/README_pl_PL.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

Martini to solidny framework umożliwiający sprawne tworzenie modularnych aplikacji internetowych i usług sieciowych w języku Go.

## Pierwsze kroki

Po zakończonej instalacji Go i ustawieniu zmiennej [GOPATH](http://golang.org/doc/code.html#GOPATH), utwórz swój pierwszy plik `.go`. Nazwijmy go `server.go`.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello world!"
  })
  m.Run()
}
~~~

Następnie zainstaluj pakiet Martini (środowisko **go** w wersji **1.1** lub nowszej jest wymagane):
~~~
go get github.com/go-martini/martini
~~~

Uruchom serwer:
~~~
go run server.go
~~~

W tym momencie webserwer Martini jest uruchomiony na `localhost:3000`.

## Uzyskiwanie pomocy

Dołącz do [grup dyskusyjnych](https://groups.google.com/forum/#!forum/martini-go)

Obejrzyj przygotowane [demo](http://martini.codegangsta.io/#demo)

Zadawaj pytania na Stackoverflow dodając [tag martini](http://stackoverflow.com/questions/tagged/martini)

GoDoc [dokumentacja](http://godoc.org/github.com/go-martini/martini)


## Cechy frameworka
* Bardzo prosty w użyciu.
* Posiada niewymagającą ingerencji budowę.
* Łatwo integruje się z innymi pakietami w języku Go.
* Sprawnie dopasowuje ścieżki i routing.
* Modularny projekt - łatwo dodać funkcję i łatwo usunąć.
* Bogate zasoby handlerów i middleware'ów do wykorzystania.
* Spora część funkcji działa 'z paczki'.
* **W pełni kompatybilny z interfejsem [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc).**
* Umożliwia serwowanie domyślnych stron (np. przy serwowaniu aplikacji napisanych w AngularJS w trybie HTML5).

## Więcej middleware'ów
W celu uzyskania więcej informacji o middleware'ach i ich możliwościach, przejrzyj repozytoria należące do organizacji [martini-contrib](https://github.com/martini-contrib).

## Spis treści
* [Domyślna konfiguracja (Martini Classic)](#domyślna-konfiguracja-martini-classic))
  * [Handlery](#handlery)
  * [Routing](#routing)
  * [Usługi](#usługi)
  * [Serwowanie plików statycznych](#serwowanie-plików-statycznych)
* [Handlery middleware'ów](#handlery-middlewareów)
  * [Next()](#next)
* [Zmienne środowiskowe Martini](#zmienne-środowiskowe-martini)
* [FAQ](#faq)

## Domyślna konfiguracja (Martini Classic)
Martini pozwala bardzo szybko uruchomić webserver korzystając przy tym z [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic). Standardowo Classic dostarcza domyślne ustawienia, które z powodzeniem pozwolą nam uruchomić wiele aplikacji internetowych:
~~~ go
  m := martini.Classic()
  // ... miejsce na middleware'y i routing
  m.Run()
~~~

Poniżej wymieniono kilka funkcji [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) dostarczanych automatycznie:
  * Logowanie żądań/odpowiedzi - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Serwowanie plików statycznych - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Routing - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Handlery
Handlery to serce i dusza Martini. Handlerem można nazwać każdą funkcję postaci:
~~~ go
m.Get("/", func() {
  println("hello world")
})
~~~

#### Wartości zwracane
Jeśli handler zwróci wartość, Martini przekaże ją do bieżącego [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) jako łańcuch znaków:
~~~ go
m.Get("/", func() string {
  return "hello world" // HTTP 200 : "hello world"
})
~~~

Opcjonalnie można zwrócić także status HTTP:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "i'm a teapot" // HTTP 418 : "i'm a teapot"
})
~~~

#### Wstrzykiwanie usług
Handlery są wywoływane przez refleksję. Martini korzysta z *wstrzykiwania zależności* w celu rozwiązania tych, które występują na liście argumentów handlera. **To sprawia, że Martini jest w pełni zgodny z interfejsem `http.HandlerFunc`.**

Jeśli dodasz argument do handlera, Martini przeszuka swoja listę usług i spróbuje dopasować zależność na podstawie asercji typów:
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res i req są wstrzykiwane przez Martini
  res.WriteHeader(200) // HTTP 200
})
~~~

Następujące usługi są dostarczane razem z [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):
  * [*log.Logger](http://godoc.org/log#Logger) - globalny logger dla Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - kontekst żądania HTTP.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` przechowująca nazwane parametry, znalezione podczas dopasowywania _routes_.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - usługa wspierająca _route'y_.
  * [martini.Route](http://godoc.org/github.com/go-martini/martini#Route) - bieżacy aktywny _route_.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - interfejs zapisu odpowiedzi HTTP.
  * [*http.Request](http://godoc.org/net/http/#Request) - żądanie HTTP.

### Routing
W Martini, jako _route_ należy rozumieć metodę HTTP skojarzoną ze wzorcem dopasowującym adres URL.
Każdy wzorzec może być skojarzony z jedną lub więcej metod handlera:
~~~ go
m.Get("/", func() {
  // wyświetl coś
})

m.Patch("/", func() {
  // zaaktualizuj coś
})

m.Post("/", func() {
  // utwórz coś
})

m.Put("/", func() {
  // zamień coś
})

m.Delete("/", func() {
  // zniszcz coś
})

m.Options("/", func() {
  // opcje HTTP
})

m.NotFound(func() {
  // obsłuż 404
})
~~~

_Route'y_ są dopasowywane w kolejności ich definiowania. Pierwszy dopasowany _route_ zostanie wywołany. 

Wzorce ścieżek _route'ów_ mogą zawierać nazwane paremetry, dostępne poprzez usługę  [martini.Params](http://godoc.org/github.com/go-martini/martini#Params):
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

_Route'y_ mogą zostać dopasowane z wartościami globalnymi:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

Również wyrażenia regularne mogą zostać użyte:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
Więcej informacji o budowie wyrażeń regularnych znajdziesz w [dokumentacji Go](http://golang.org/pkg/regexp/syntax/).

Handlery można organizować w stosy wywołań, co przydaje się przy mechanizmach takich jak uwierzytelnianie i autoryzacja:
~~~ go
m.Get("/secret", authorize, func() {
  // funkcja będzie wywoływana dopóty, dopóki authorize nie zwróci odpowiedzi
})
~~~

Grupy _route'ów_ mogą zostać dodane przy pomocy metody Group.
~~~ go
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)
})
~~~

W taki sam sposób jak przekazujesz middleware'y do handlerów, to możesz przekazywać middleware'y do grup.
~~~ go
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)
~~~

### Usługi
Usługi są obiektami możliwymi do wstrzyknięcia poprzez listę argumentów danego handlera i mogą być mapowane na poziomie *globalnym* lub *żądania*.

#### Mapowanie globalne
Instancja Martini implementuje interfejs inject.Injector interface, więc mapowanie jest bardzo proste:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // usługa będzie dostępna dla wszystkich handlerów jako *MyDatabase
// ...
m.Run()
~~~

#### Mapowanie na poziomie żądania
Mapowanie na poziomie żądania może być wykonane w handlerze poprzez [martini.Context](http://godoc.org/github.com/go-martini/martini#Context):
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // zmapowany jako *MyCustomLogger
}
~~~

#### Mapowanie wartości na interfejsy
Jedną z mocnych stron usług jest możliwość zmapowania konkretnej usługi na interfejs. Dla przykładu, jeśli chcesz nadpisać [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) obiektem, który go opakowuje i wykonuje dodatkowe operacje, to możesz napisać następujący handler:
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // nadpisz oryginalny ResponseWriter naszym ResponseWriterem
}
~~~

### Serwowanie plików statycznych
Instancja [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) automatycznie serwuje statyczne pliki z katalogu "public" znajdującym się bezpośrednio w głównym katalogu serwera. Możliwe jest serwowanie dodatkowych katalogów poprzez dodanie handlerów [martini.Static](http://godoc.org/github.com/go-martini/martini#Static).
~~~ go
m.Use(martini.Static("assets")) // serwuj zasoby z katalogu "assets"
~~~

#### Serwowanie domyślnej strony
Możesz zdefiniować adres URL lokalnego pliku, który będzie serwowany gdy żądany adres URL nie zostanie znaleziony. Dodatkowo możesz zdefiniować prefiks wykluczający, który spowoduje, że niektórze adresy URL zostaną zignorowane. Jest to przydatna opcja dla serwerów, które jednocześnie serwują statyczne pliki i mają zdefiniowane handlery (np. REST API). Warto także rozważyć zdefiniowanie statycznych handlerów jako części łańcucha NotFound.

W poniższym przykładzie aplikacja serwuje plik `/index.html`, gdy tylko adres URL nie zostanie dopasowany do istniejącego lokalnego pliku i nie zaczyna się prefiksem `/api/v`:
~~~ go
static := martini.Static("assets", martini.StaticOptions{Fallback: "/index.html", Exclude: "/api/v"})
m.NotFound(static, http.NotFound)
~~~

## Handlery middleware'ów
Handlery middleware'ów są uruchamiane po otrzymaniu żądania HTTP a przed przekazaniem go do routera. W zasadzie nie ma różnicy między nimi a handlerami Martini. Handler middleware'a można dodać do stosu wywołań w następujący sposób:
~~~ go
m.Use(func() {
  // wykonaj operacje zdefiniowane przez middleware
})
~~~

Pełną kontrolę na stosem middleware'owym zapewnia funkcja `Handlers`. Poniższy przykład prezentuje, jak można zamienić poprzednio skonfigurowane handlery:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

Handlery middleware'ów sprawdzają się doskonale dla mechanizmów takich jak logowanie, autoryzacja, uwierzytelnianie, obsługa sesji, kompresja odpowiedzi, strony błędów i innych, których operacje muszą zostać wykonane przed i po obsłudze żądania HTTP:
~~~ go
// 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://godoc.org/github.com/go-martini/martini#Context) jest opcjonalną funkcją, którą handlery middleware'ów wywołują, żeby przekazać tymczasowo obsługę żadania do kolejnych handlerów, a później do niej wrócić. Mechanizm sprawdza się doskonale w przypadku wykonywania operacji po obsłudze żądania HTTP:
~~~ go
// zaloguj przed i po żądaniu
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("before a request")

  c.Next()

  log.Println("after a request")
})
~~~

## Zmienne środowiskowe Martini

Niektóre handlery Martini wykorzystują globalną zmienną `martini.Env` by dostarczać specjalne funkcje dla środowisk deweloperskich i produkcyjnych. Zaleca się ustawienie zmiennej `MARTINI_ENV=production` w środowisku produkcyjnym.

## FAQ

### Gdzie mam szukać middleware'u X?

Proponujemy zacząć poszukiwania od projektów należących do [martini-contrib](https://github.com/martini-contrib). Jeśli dany middleware się tam nie znajduje, skontaktuj się z członkiem zespołu martini-contrib i poproś go o dodanie nowego repozytorium do organizacji.

* [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler umożliwiający parsowanie nagłówka HTTP `Accept-Language`.
* [accessflags](https://github.com/martini-contrib/accessflags) - Handler dołączający obsługę kontroli dostępu.
* [auth](https://github.com/martini-contrib/auth) - Handlery uwierzytelniające.
* [binding](https://github.com/martini-contrib/binding) - Handler mapujący/walidujący żądanie na strukturę.
* [cors](https://github.com/martini-contrib/cors) - Handler dostarcza wsparcie dla CORS.
* [csrf](https://github.com/martini-contrib/csrf) - Ochrona CSRF dla aplikacji.
* [encoder](https://github.com/martini-contrib/encoder) - Usługa enkodująca treść odpowiedzi w różnych formatach, wspiera negocjacje formatu.
* [gzip](https://github.com/martini-contrib/gzip) - Handler dla kompresji GZIP żądań.
* [gorelic](https://github.com/martini-contrib/gorelic) - NewRelic middleware.
* [logstasher](https://github.com/martini-contrib/logstasher) - Middleware zwracający odpowiedź formacie kompatybilnym z logstash JSONem.
* [method](https://github.com/martini-contrib/method) - Nadpisywanie metod HTTP poprzez nagłówek.
* [oauth2](https://github.com/martini-contrib/oauth2) - Handler dostarczający logowanie OAuth 2.0 dla aplikacji Martini. Logowanie Google Sign-in, Facebook Connect i Github wspierane.
* [permissions2](https://github.com/xyproto/permissions2) - Handler śledzący użytkowników, ich logowania i uprawnienia.
* [render](https://github.com/martini-contrib/render) - Handler dostarczający usługę łatwo renderującą odpowiedź do formatu JSON i szablonów HTML.
* [secure](https://github.com/martini-contrib/secure) - Implementuje kilka szybkich "quick-wins" związanych z bezpieczeństwem.
* [sessions](https://github.com/martini-contrib/sessions) - Handler dostarcza usługę sesji.
* [sessionauth](https://github.com/martini-contrib/sessionauth) - Handler, który umożliwia w prosty sposób nałożenie reguły wymagania logowania dla konkretnych adresów oraz obsługę zalogowanych użytkowników w sesji. 
* [strict](https://github.com/martini-contrib/strict) - Strict Mode 
* [strip](https://github.com/martini-contrib/strip) - Pomijanie prefiksu URL.
* [staticbin](https://github.com/martini-contrib/staticbin) - Handler umożliwia serwowanie statycznych plików z zasobów binarnych.
* [throttle](https://github.com/martini-contrib/throttle) - Middleware kontrolujący przepustowość handlerów.
* [vauth](https://github.com/rafecolton/vauth) - Handlery wspierające vendorowe uwierzytelnianie (obecnie GitHub i TravisCI).
* [web](https://github.com/martini-contrib/web) - Kontekst znany z web.go.

### Jak mogę zintegrować Martini z istniejącymi serwerami?

Instacja Martini implementuje `http.Handler`, więc może być łatwo wykorzystana do serwowania całych drzew zasobów na istniejących serwerach Go. Przykład przedstawia działającą aplikację Martini dla Google App Engine:

~~~ go
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)
}
~~~

### Jak mogę zmienić host/port?

Funkcja `Run` sprawdza, czy są zdefiniowane zmienne środowiskowe HOST i PORT, i jeśli są to ich używa. W przeciwnym wypadku Martini uruchomi się z domyślnymi ustawieniami localhost:3000.
W celu uzyskania większej kontroli nad hostem i portem, skorzystaj z funkcji `martini.RunOnAddr`.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### Automatyczne przeładowywanie kodu aplikacji (Live code reload)

[gin](https://github.com/codegangsta/gin) i [fresh](https://github.com/pilu/fresh) wspierają przeładowywanie kodu aplikacji.

## Rozwijanie
Martini w założeniu ma pozostać czysty i uporządkowany. Większość kontrybucji powinna trafić jako repozytorium organizacji [martini-contrib](https://github.com/martini-contrib). Jeśli masz kontrybucję do core'a projektu Martini, zgłoś Pull Requesta.

## O projekcie

Inspirowany [expressem](https://github.com/visionmedia/express) i [sinatrą](https://github.com/sinatra/sinatra)

Martini został obsesyjnie zaprojektowany przez nikogo innego jak przez [Code Gangsta](http://codegangsta.io/)


================================================
FILE: translations/README_pt_br.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

**NOTA:** O martini framework não é mais mantido.

Martini é um poderoso pacote para escrever aplicações/serviços modulares em Golang..


## Vamos começar

Após a instalação do Go e de configurar o [GOPATH](http://golang.org/doc/code.html#GOPATH), crie seu primeiro arquivo `.go`. Vamos chamá-lo de `server.go`.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello world!"
  })
  m.Run()
}
~~~

Então instale o pacote do Martini (É necessário **go 1.1** ou superior):
~~~
go get github.com/go-martini/martini
~~~

Então rode o servidor:
~~~
go run server.go
~~~

Agora você tem um webserver Martini rodando na porta `localhost:3000`.

## Obtenha ajuda

Assine a [Lista de email](https://groups.google.com/forum/#!forum/martini-go)

Veja o [Vídeo demonstrativo](http://martini.codegangsta.io/#demo)

Use a tag [martini](http://stackoverflow.com/questions/tagged/martini) para perguntas no Stackoverflow



## Caracteríticas
* Extrema simplicidade de uso.
* Design não intrusivo.
* Boa integração com outros pacotes Golang.
* Router impressionante.
* Design modular - Fácil para adicionar e remover funcionalidades.
* Muito bom no uso handlers/middlewares.
* Grandes caracteríticas inovadoras.
* **Completa compatibilidade com a interface [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc).**

## Mais Middleware
Para mais middleware e funcionalidades, veja os repositórios em [martini-contrib](https://github.com/martini-contrib).

## Tabela de Conteudos
* [Classic Martini](#classic-martini)
  * [Handlers](#handlers)
  * [Routing](#routing)
  * [Services](#services)
  * [Serving Static Files](#serving-static-files)
* [Middleware Handlers](#middleware-handlers)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
Para iniciar rapidamente, [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) provê algumas ferramentas razoáveis para maioria das aplicações web:
~~~ go
  m := martini.Classic()
  // ... middleware e rota aqui
  m.Run()
~~~

Algumas das funcionalidade que o [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) oferece automaticamente são:
  * Request/Response Logging - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Servidor de arquivos státicos - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Rotas - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Handlers
Handlers são o coração e a alma do Martini. Um handler é basicamente qualquer função que pode ser chamada:
~~~ go
m.Get("/", func() {
  println("hello world")
})
~~~

#### Retorno de Valores
Se um handler retornar alguma coisa, Martini irá escrever o valor retornado como uma string ao [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter):
~~~ go
m.Get("/", func() string {
  return "hello world" // HTTP 200 : "hello world"
})
~~~

Você também pode retornar o código de status:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "Eu sou um bule" // HTTP 418 : "Eu sou um bule"
})
~~~

#### Injeção de Serviços
Handlers são chamados via reflexão. Martini utiliza *Injeção de Dependencia* para resolver as dependencias nas listas de argumentos dos Handlers . **Isso faz Martini ser completamente compatível com a interface `http.HandlerFunc` do golang.**

Se você adicionar um argumento ao seu Handler, Martini ira procurar na sua lista de serviços e tentar resolver sua dependencia pelo seu tipo:
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res e req são injetados pelo Martini
  res.WriteHeader(200) // HTTP 200
})
~~~

Os seguintes serviços são incluídos com [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):
  * [*log.Logger](http://godoc.org/log#Logger) - Log Global para Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request context.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` de nomes dos parâmetros buscados pela rota.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Serviço de auxílio as rotas.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response escreve a interface.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request.

### Rotas
No Martini, uma rota é um método HTTP emparelhado com um padrão de URL de correspondência.
Cada rota pode ter um ou mais métodos handler:
~~~ go
m.Get("/", func() {
  // mostra alguma coisa
})

m.Patch("/", func() {
  // altera alguma coisa
})

m.Post("/", func() {
  // cria alguma coisa
})

m.Put("/", func() {
  // sobrescreve alguma coisa
})

m.Delete("/", func() {
  // destrói alguma coisa
})

m.Options("/", func() {
  // opções do HTTP
})

m.NotFound(func() {
  // manipula 404
})
~~~

As rotas são combinadas na ordem em que são definidas. A primeira rota que corresponde a solicitação é chamada.

O padrão de rotas pode incluir parâmetros que podem ser acessados via [martini.Params](http://godoc.org/github.com/go-martini/martini#Params):
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

As rotas podem ser combinados com expressões regulares e globs:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

Expressões regulares podem ser bem usadas:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
Dê uma olhada na [documentação](http://golang.org/pkg/regexp/syntax/) para mais informações sobre expressões regulares.


Handlers de rota podem ser empilhados em cima uns dos outros, o que é útil para coisas como autenticação e autorização:
~~~ go
m.Get("/secret", authorize, func() {
  // Será executado quando authorize não escrever uma resposta
})
~~~

Grupos de rota podem ser adicionados usando o método Group.
~~~ go
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)
})
~~~

Assim como você pode passar middlewares para um manipulador você pode passar middlewares para grupos.
~~~ go
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)
~~~

### Serviços
Serviços são objetos que estão disponíveis para ser injetado em uma lista de argumentos de Handler. Você pode mapear um serviço num nível *Global* ou *Request*.

#### Mapeamento Global
Um exemplo onde o Martini implementa a interface inject.Injector, então o mapeamento de um serviço é fácil:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // o serviço estará disponível para todos os handlers *MyDatabase.
// ...
m.Run()
~~~

#### Mapeamento por requisição
Mapeamento do nível de request pode ser feito via handler através [martini.Context](http://godoc.org/github.com/go-martini/martini#Context):
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // mapeamento é *MyCustomLogger
}
~~~

#### Valores de Mapeamento para Interfaces
Uma das partes mais poderosas sobre os serviços é a capacidade para mapear um serviço de uma interface. Por exemplo, se você quiser substituir o [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) com um objeto que envolveu-o e realizou operações extras, você pode escrever o seguinte handler:
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // substituir ResponseWriter com nosso ResponseWriter invólucro
}
~~~

### Servindo Arquivos Estáticos
Uma instância de [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) serve automaticamente arquivos estáticos do diretório "public" na raiz do seu servidor.
Você pode servir de mais diretórios, adicionando mais [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) handlers.
~~~ go
m.Use(martini.Static("assets")) // servindo os arquivos do diretório "assets"
~~~

## Middleware Handlers
Middleware Handlers ficam entre a solicitação HTTP e o roteador. Em essência, eles não são diferentes de qualquer outro Handler no Martini. Você pode adicionar um handler de middleware para a pilha assim:
~~~ go
m.Use(func() {
  // faz algo com middleware
})
~~~

Você pode ter o controle total sobre a pilha de middleware com a função `Handlers`. Isso irá substituir quaisquer manipuladores que foram previamente definidos:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

Middleware Handlers trabalham muito bem com princípios com logging, autorização, autenticação, sessão, gzipping, páginas de erros e uma série de outras operações que devem acontecer antes ou depois de uma solicitação HTTP:
~~~ go
// Valida uma chave de API
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://godoc.org/github.com/go-martini/martini#Context) é uma função opcional que Middleware Handlers podem chamar para aguardar a execução de outros Handlers. Isso funciona muito bem para operações que devem acontecer após uma requisição:
~~~ go
// log antes e depois do request
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("antes do request")

  c.Next()

  log.Println("depois do request")
})
~~~

## Martini Env

Martini handlers fazem uso do `martini.Env`, uma variável global para fornecer funcionalidade especial para ambientes de desenvolvimento e ambientes de produção. É recomendado que a variável `MARTINI_ENV=production` seja definida quando a implementação estiver em um ambiente de produção.

## FAQ

### Onde posso encontrar o middleware X?

Inicie sua busca nos projetos [martini-contrib](https://github.com/martini-contrib). Se ele não estiver lá não hesite em contactar um membro da equipe martini-contrib sobre como adicionar um novo repo para a organização.

* [auth](https://github.com/martini-contrib/auth) - Handlers para autenticação.
* [binding](https://github.com/martini-contrib/binding) - Handler para mapeamento/validação de um request a estrutura.
* [gzip](https://github.com/martini-contrib/gzip) - Handler para adicionar compreção gzip para o requests
* [render](https://github.com/martini-contrib/render) - Handler que providencia uma rederização simples para JSON e templates HTML.
* [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler para parsing do `Accept-Language` no header HTTP.
* [sessions](https://github.com/martini-contrib/sessions) - Handler que prove o serviço de sessão.
* [strip](https://github.com/martini-contrib/strip) - URL Prefix stripping.
* [method](https://github.com/martini-contrib/method) - HTTP método de substituição via cabeçalho ou campos do formulário.
* [secure](https://github.com/martini-contrib/secure) - Implementa rapidamente itens de segurança.
* [encoder](https://github.com/martini-contrib/encoder) - Serviço Encoder para renderização de dados em vários formatos e negociação de conteúdo.
* [cors](https://github.com/martini-contrib/cors) - Handler que habilita suporte a CORS.
* [oauth2](https://github.com/martini-contrib/oauth2) - Handler que prove sistema de login OAuth 2.0 para aplicações Martini. Google Sign-in, Facebook Connect e Github login são suportados.

### Como faço para integrar com os servidores existentes?

Uma instância do Martini implementa `http.Handler`, de modo que pode ser facilmente utilizado para servir sub-rotas e diretórios
em servidores Go existentes. Por exemplo, este é um aplicativo Martini trabalhando para Google App Engine:

~~~ go
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)
}
~~~

### Como faço para alterar a porta/host?

A função `Run` do Martini olha para as variáveis PORT e HOST para utilizá-las. Caso contrário o Martini assume como padrão localhost:3000.
Para ter mais flexibilidade sobre a porta e host use a função `martini.RunOnAddr`.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### Servidor com autoreload?

[gin](https://github.com/codegangsta/gin) e [fresh](https://github.com/pilu/fresh) são aplicativos para autoreload do Martini.

## Contribuindo
Martini é feito para ser mantido pequeno e limpo. A maioria das contribuições devem ser feitas no repositório [martini-contrib](https://github.com/martini-contrib). Se quiser contribuir com o core do Martini fique livre para fazer um Pull Request.

## Sobre

Inspirado por [express](https://github.com/visionmedia/express) e [sinatra](https://github.com/sinatra/sinatra)

Martini is obsessively designed by none other than the [Code Gangsta](http://codegangsta.io/)


================================================
FILE: translations/README_ru_RU.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

Martini - мощный пакет для быстрой разработки веб приложений и сервисов на Golang.

## Начало работы

После установки Golang и настройки вашего [GOPATH](http://golang.org/doc/code.html#GOPATH), создайте ваш первый `.go` файл. Назовем его `server.go`.

~~~ 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
~~~

И вы получите запущенный Martini сервер на `localhost:3000`.

## Помощь

Присоединяйтесь к [рассылке](https://groups.google.com/forum/#!forum/martini-go)

Задавайте вопросы на Stackoverflow используя [тэг martini](http://stackoverflow.com/questions/tagged/martini)

GoDoc [документация](http://godoc.org/github.com/go-martini/martini)


## Возможности
* Очень прост в использовании.
* Ненавязчивый дизайн.
* Хорошо сочетается с другими пакетами.
* Потрясающий роутинг и маршрутизация.
* Модульный дизайн - легко добавлять и исключать функциональность.
* Большое количество хороших обработчиков/middlewares, готовых к использованию.
* Отличный набор 'из коробки'.
* **Полностью совместим с интерфейсом [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc).**

## Больше Middleware
Смотрите репозитории организации [martini-contrib](https://github.com/martini-contrib), для большей информации о функциональности и middleware.

## Содержание
* [Classic Martini](#classic-martini)
  * [Обработчики](#%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B8)
  * [Роутинг](#%D0%A0%D0%BE%D1%83%D1%82%D0%B8%D0%BD%D0%B3)
  * [Сервисы](#%D0%A1%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8B)
  * [Отдача статических файлов](#%D0%9E%D1%82%D0%B4%D0%B0%D1%87%D0%B0-%D1%81%D1%82%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85-%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2)
* [Middleware обработчики](#middleware-%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B8)
  * [Next()](#next)
* [Окружение](#%D0%9E%D0%BA%D1%80%D1%83%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5)
* [FAQ](#faq)

## Classic Martini
Для быстрого старта [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) предлагает несколько предустановок, это используется для большинства веб приложений:
~~~ go
  m := martini.Classic()
  // ... middleware и роутинг здесь
  m.Run()
~~~

Ниже представлена уже подключенная [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) функциональность:  

  * Request/Response логгирование - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Отдача статики - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Роутинг - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Обработчики
Обработчики - это сердце и душа Martini. Обработчик - любая функция, которая может быть вызвана:
~~~ go
m.Get("/", func() {
  println("hello world")
})
~~~

#### Возвращаемые значения
Если обработчик возвращает что-либо, Martini запишет это как результат в текущий [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter), в виде строки:
~~~ go
m.Get("/", func() string {
  return "hello world" // HTTP 200 : "hello world"
})
~~~

Так же вы можете возвращать код статуса, опционально:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "i'm a teapot" // HTTP 418 : "i'm a teapot"
})
~~~

#### Внедрение сервисов
Обработчики вызываются посредством рефлексии. Martini использует **Внедрение зависимости** для разрешения зависимостей в списке аргумента обработчика. **Это делает Martini полностью совместимым с интерфейсом `http.HandlerFunc`.**

Если вы добавите аргументы в ваш обработчик, Martini будет пытаться найти этот список сервисов за счет проверки типов(type assertion):
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res и req будут внедрены  Martini
  res.WriteHeader(200) // HTTP 200
})
~~~

Следующие сервисы включены в [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):

  * [*log.Logger](http://godoc.org/log#Logger) - Глобальный логгер для Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request контекст.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` именованных аргументов из роутера.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Хэлпер роутеров.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response writer интерфейс.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request.

### Роутинг
В Martini, роут - это объединенные паттерн и HTTP метод.
Каждый роут может принимать один или несколько обработчиков:
~~~ go
m.Get("/", func() {
  // показать что-то
})

m.Patch("/", func() {
  // обновить что-то
})

m.Post("/", func() {
  // создать что-то
})

m.Put("/", func() {
  // изменить что-то
})

m.Delete("/", func() {
  // удалить что-то
})

m.Options("/", func() {
  // http опции
})

m.NotFound(func() {
  // обработчик 404
})
~~~

Роуты могут сопоставляться с http запросами только в порядке объявления. Вызывается первый роут, который соответствует запросу.

Паттерны роутов могут включать именованные параметры, доступные через [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) сервис:
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

Роуты можно объявлять как glob'ы:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

Так же могут использоваться регулярные выражения:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
Синтаксис регулярных выражений смотрите [Go documentation](http://golang.org/pkg/regexp/syntax/).

Обработчики роутов так же могут быть выстроены в стек, друг перед другом. Это очень удобно для таких задач как авторизация и аутентификация:
~~~ go
m.Get("/secret", authorize, func() {
  // будет вызываться, в случае если authorize ничего не записал в ответ
})
~~~

Роуты так же могут быть объединены в группы, посредством метода Group:
~~~ go
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)
})
~~~

Так же как вы можете добавить middleware для обычного обработчика, вы можете добавить middleware и для группы.
~~~ go
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, поэтому замаппить сервис легко:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // сервис будет доступен для всех обработчиков как *MyDatabase
// ...
m.Run()
~~~

#### Маппинг уровня запроса
Маппинг на уровне запроса можно сделать при помощи [martini.Context](http://godoc.org/github.com/go-martini/martini#Context):
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // как *MyCustomLogger
}
~~~

#### Маппинг на определенный интерфейс
Одна из мощных частей, того что касается сервисов - маппинг сервиса на определенный интерфейс. Например, если вы хотите переопределить [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) объектом, который оборачивает и добавляет новые операции, вы можете написать следующее:
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // переопределить ResponseWriter нашей оберткой
}
~~~

### Отдача статических файлов
Экземпляр [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) автоматически отдает статические файлы из директории "public" в корне, рядом с вашим файлом `server.go`.
Вы можете добавить еще директорий, добавляя [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) обработчики.  
~~~ go
m.Use(martini.Static("assets")) // отдача файлов из "assets" директории
~~~

## Middleware Обработчики
Middleware обработчики находятся между входящим http запросом и роутом. По сути, они ничем не отличаются от любого другого обработчика Martini. Вы можете добавить middleware обработчик в стек следующим образом:
~~~ go
m.Use(func() {
  // делать какую то middleware работу
})
~~~

Для полного контроля над стеком middleware существует метод `Handlers`. В этом примере будут заменены все обработчики, которые были до этого:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

Middleware обработчики очень хорошо работают для таких вещей как логгирование, авторизация, аутентификация, сессии, сжатие, страницы ошибок и любые другие операции, которые должны быть выполнены до или после http запроса:
~~~ go
// валидация api ключа
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://godoc.org/github.com/go-martini/martini#Context) опциональная функция, которая может быть вызвана в Middleware обработчике, для выхода из контекста, и возврата в него, после вызова всего стека обработчиков. Это можно использовать для операций, которые должны быть выполнены после http запроса:
~~~ go
// логгирование до и после http запроса
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("до запроса")

  c.Next()

  log.Println("после запроса")
})
~~~

## Окружение
Некоторые Martini обработчики используют глобальную переменную `martini.Env` для того, чтоб предоставить специальную функциональность для девелопмент и продакшн окружения. Рекомендуется устанавливать `MARTINI_ENV=production`, когда вы деплоите приложение на продакшн.

## FAQ

### Где найти готовые middleware?

Начните поиск с [martini-contrib](https://github.com/martini-contrib) проектов. Если нет ничего подходящего, без колебаний пишите члену команды martini-contrib о добавлении нового репозитория в организацию.

* [auth](https://github.com/martini-contrib/auth) - Обработчики для аутентификации.
* [binding](https://github.com/martini-contrib/binding) - Обработчик для маппинга/валидации сырого запроса в определенную структуру(struct).
* [gzip](https://github.com/martini-contrib/gzip) - Обработчик, добавляющий gzip сжатие для запросов.
* [render](https://github.com/martini-contrib/render) - Обработчик, которые предоставляет сервис для легкого рендеринга JSON и HTML шаблонов.
* [acceptlang](https://github.com/martini-contrib/acceptlang) - Обработчик для парсинга `Accept-Language` HTTP заголовка.
* [sessions](https://github.com/martini-contrib/sessions) - Сервис сессий.
* [strip](https://github.com/martini-contrib/strip) - Удаление префиксов из URL.
* [method](https://github.com/martini-contrib/method) - Подмена HTTP метода через заголовок.
* [secure](https://github.com/martini-contrib/secure) - Набор для безопасности.
* [encoder](https://github.com/martini-contrib/encoder) - Сервис для представления данных в нескольких форматах и взаимодействия с контентом.
* [cors](https://github.com/martini-contrib/cors) - Поддержка CORS.
* [oauth2](https://github.com/martini-contrib/oauth2) - Обработчик, предоставляющий OAuth 2.0 логин для Martini приложений. Вход через Google, Facebook и через Github поддерживаются.

### Как интегрироваться с существуюшими серверами?

Экземпляр Martini реализует интерфейс `http.Handler`, потому - это очень просто использовать вместе с существующим Go проектом. Например, это работает для платформы Google App Engine:
~~~ go
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)
}
~~~

### Как изменить порт и/или хост?
Функция `Run` смотрит переменные окружиения PORT и HOST, и использует их.
В противном случае Martini по умолчанию будет использовать `localhost:3000`.
Для большей гибкости используйте вместо этого функцию `martini.RunOnAddr`.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### Живая перезагрузка кода?

[gin](https://github.com/codegangsta/gin) и [fresh](https://github.com/pilu/fresh) могут работать вместе с Martini.

## Вклад в общее дело

Подразумевается что Martini чистый и маленький. Большинство улучшений должны быть в организации [martini-contrib](https://github.com/martini-contrib). Но если вы хотите улучшить ядро Martini, отправляйте пулл реквесты.

## О проекте

Вдохновлен [express](https://github.com/visionmedia/express) и [sinatra](https://github.com/sinatra/sinatra)

Martini создан [Code Gangsta](http://codegangsta.io/)


================================================
FILE: translations/README_tr_TR.md
================================================
# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master "wercker status")](https://app.wercker.com/project/bykey/9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https://godoc.org/github.com/go-martini/martini?status.png)](http://godoc.org/github.com/go-martini/martini)

Martini Go dilinde hızlı ve modüler web uygulamaları ve servisleri için güçlü bir pakettir.


## Başlangıç

Go kurulumu ve [GOPATH](http://golang.org/doc/code.html#GOPATH) ayarını yaptıktan sonra, ilk `.go` uzantılı dosyamızı oluşturuyoruz. Bu oluşturduğumuz dosyayı `server.go` olarak adlandıracağız.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hello world!"
  })
  m.Run()
}
~~~

Martini paketini kurduktan sonra (**go 1.1** ve daha üst go sürümü gerekmektedir.):

~~~
go get github.com/go-martini/martini
~~~

Daha sonra server'ımızı çalıştırıyoruz:

~~~
go run server.go
~~~

Şimdi elimizde çalışan bir adet Martini webserver `localhost:3000`  adresinde bulunmaktadır.


## Yardım Almak İçin 

[Mail Listesi](https://groups.google.com/forum/#!forum/martini-go)

[Örnek Video](http://martini.codegangsta.io/#demo)

Stackoverflow üzerinde [martini etiketine](http://stackoverflow.com/questions/tagged/martini) sahip sorular

[GO Diline ait Dökümantasyonlar](http://godoc.org/github.com/go-martini/martini)


## Özellikler 
* Oldukça basit bir kullanıma sahip.
* Kısıtlama yok.
* Golang paketleri ile rahat bir şekilde kullanılıyor.
* Müthiş bir şekilde path eşleştirme ve yönlendirme.
* Modüler dizayn - Kolay eklenen fonksiyonellik.
* handlers/middlewares kullanımı çok iyi.
* Büyük 'kutu dışarı' özellik seti.
* **[http.HandlerFunc](http://godoc.org/net/http#HandlerFunc) arayüzü ile tam uyumludur.**
* Varsayılan belgelendirme işlemleri (örnek olarak, AngularJS uygulamalarının HTML5 modunda servis edilmesi).

## Daha Fazla Middleware(Ara Katman)

Daha fazla ara katman ve fonksiyonellik için, şu repoları inceleyin [martini-contrib](https://github.com/martini-contrib).

## Tablo İçerikleri
* [Classic Martini](#classic-martini)
  * [İşleyiciler / Handlers](#handlers)
  * [Yönlendirmeler / Routing](#routing)
  * [Servisler](#services)
  * [Statik Dosyaların Sunumu](#serving-static-files)
* [Katman İşleyiciler / Middleware Handlers](#middleware-handlers)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) hızlıca projeyi çalıştırır ve çoğu web uygulaması için iyi çalışan bazı makul varsayılanlar sağlar:

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

[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) aşağıdaki bazı fonsiyonelleri  otomatik olarak çeker:

  * İstek/Yanıt Kayıtları (Request/Response Logging) - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Hataların Düzeltilmesi (Panic Recovery) - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Statik Dosyaların Sunumu (Static File serving) - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Yönlendirmeler (Routing) - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### İşleyiciler (Handlers)
İşleyiciler Martini'nin ruhu ve kalbidir. Bir işleyici temel olarak her türlü fonksiyonu çağırabilir:

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

#### Geriye Dönen Değerler

Eğer bir işleyici geriye bir şey dönderiyorsa, Martini string olarak sonucu [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) ile yazacaktır:

~~~ go
m.Get("/", func() string {
  return "hello world" // HTTP 200 : "hello world"
})
~~~

Ayrıca isteğe bağlı bir durum kodu dönderebilir:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "i'm a teapot" // HTTP 418 : "i'm a teapot"
})
~~~

#### Service Injection
İşlemciler yansıma yoluyla çağrılır. Martini *Dependency Injection* kullanarak arguman listesindeki bağımlıkları giderir.**Bu sayede Martini go programlama dilinin `http.HandlerFunc` arayüzü ile tamamen uyumlu hale getirilir.**

Eğer işleyiciye bir arguman eklersek, Martini "type assertion" ile servis listesinde arayacak ve bağımlılıkları çözmek için girişimde bulunacaktır:

~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
  res.WriteHeader(200) // HTTP 200
})
~~~

Aşağıdaki servislerin içerikleri

[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):
  * [*log.Logger](http://godoc.org/log#Logger) - Martini için Global loglayıcı.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request içereği.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` ile yol eşleme tarafından params olarak isimlendirilen yapılar bulundu.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Yönledirilme için yardımcı olan yapıdır.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http yanıtlarını yazacak olan yapıdır.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request(http isteği yapar).

### Yönlendirme - Routing
Martini'de bir yol HTTP metodu URL-matching pattern'i ile eşleştirilir.
Her bir yol bir veya daha fazla işleyici metod alabilir:
~~~ go
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
})
~~~

Yollar sırayla tanımlandıkları şekilde eşleştirilir.Request ile eşleşen ilk rota çağrılır.

Yol patternleri [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) servisi tarafından adlandırılan parametreleri içerebilir:
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hello " + params["name"]
})
~~~

Yollar globaller ile eşleşebilir:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hello " + params["_1"]
})
~~~

Düzenli ifadeler kullanılabilir:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hello %s", params["name"])
})
~~~
Düzenli ifadeler hakkında daha fazla bilgiyi [Go dökümanlarından](http://golang.org/pkg/regexp/syntax/) elde edebilirsiniz.

Yol işleyicileri birbirlerinin üstüne istiflenebilir. Bu durum doğrulama ve yetkilendirme(authentication and authorization) işlemleri için iyi bir yöntemdir: 
~~~ go
m.Get("/secret", authorize, func() {
  // this will execute as long as authorize doesn't write a response
})
~~~

Yol grupları Grup metodlar kullanılarak eklenebilir.
~~~ go
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)
})
~~~

Tıpkı ara katmanların işleyiciler için bazı ara katman işlemlerini atlayabileceği gibi gruplar içinde atlayabilir.
~~~ go
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)
~~~

### Servisler

Servisler işleyicilerin arguman listesine enjekte edilecek kullanılabilir nesnelerdir. İstenildiği taktirde bir servis *Global* ve *Request* seviyesinde eşlenebilir.

#### Global Eşleme - Global Mapping

Bir martini örneği(instance) projeye enjekte edilir. 
A Martini instance implements the inject.Enjekte arayüzü, çok kolay bir şekilde servis eşlemesi yapar:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // the service will be available to all handlers as *MyDatabase
// ...
m.Run()
~~~

#### Request-Level Mapping
Request düzeyinde eşleme yapmak üzere işleyici [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) ile oluşturulabilir:
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // mapped as *MyCustomLogger
}
~~~

#### Arayüz Eşleme Değerleri
Servisler hakkındaki en güçlü şeylerden birisi bir arabirim ile bir servis eşleşmektedir. Örneğin, istenirse [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) yapısı paketlenmiş ve ekstra işlemleri gerçekleştirilen bir nesne ile  override edilebilir. Şu işleyici yazılabilir:

~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // override ResponseWriter with our wrapper ResponseWriter
}
~~~

### Statik Dosyaların Sunumu

[martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) örneği otomatik olarak statik dosyaları serverda root içinde yer alan "public" dizininden servis edilir.

Eğer istenirse daha fazla [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) işleyicisi eklenerek daha fazla dizin servis edilebilir.
~~~ go
m.Use(martini.Static("assets")) // serve from the "assets" directory as well
~~~

#### Standart Dökümanların Sunulması - Serving a Default Document

Eğer istenilen URL bulunamaz ise özel bir URL dönderilebilir. Ayrıca bir dışlama(exclusion) ön eki ile bazı URL'ler göz ardı edilir. Bu durum statik dosyaların ve ilave işleyiciler için kullanışlıdır(Örneğin, REST API). Bunu yaparken, bu işlem ile NotFound zincirinin bir parçası olan statik işleyiciyi tanımlamak kolaydır.

Herhangi bir URL isteği bir local dosya ile eşleşmediği ve `/api/v` ile başlamadığı zaman aşağıdaki örnek `/index.html` dosyasını sonuç olarak geriye döndürecektir.
~~~ go
static := martini.Static("assets", martini.StaticOptions{Fallback: "/index.html", Exclude: "/api/v"})
m.NotFound(static, http.NotFound)
~~~

## Ara Katman İşleyicileri
Ara katmana ait işleyiciler http isteği ve yönlendirici arasında bulunmaktadır. Özünde onlar diğer Martini işleyicilerinden farklı değildirler. İstenildiği taktirde bir yığına ara katman işleyicisi şu şekilde eklenebilir:
~~~ go
m.Use(func() {
  // do some middleware stuff
})
~~~

`Handlers` fonksiyonu ile ara katman yığını üzerinde tüm kont
Download .txt
gitextract_1zcxk7ip/

├── .gitignore
├── Godeps/
│   └── Godeps.json
├── LICENSE
├── README.md
├── env.go
├── env_test.go
├── go_version.go
├── logger.go
├── logger_test.go
├── martini.go
├── martini_test.go
├── recovery.go
├── recovery_test.go
├── response_writer.go
├── response_writer_test.go
├── return_handler.go
├── router.go
├── router_test.go
├── static.go
├── static_test.go
├── translations/
│   ├── README_de_DE.md
│   ├── README_es_ES.md
│   ├── README_fr_FR.md
│   ├── README_ja_JP.md
│   ├── README_ko_kr.md
│   ├── README_pl_PL.md
│   ├── README_pt_br.md
│   ├── README_ru_RU.md
│   ├── README_tr_TR.md
│   ├── README_zh_cn.md
│   └── README_zh_tw.md
└── wercker.yml
Download .txt
SYMBOL INDEX (159 symbols across 16 files)

FILE: env.go
  constant Dev (line 9) | Dev  string = "development"
  constant Prod (line 10) | Prod string = "production"
  constant Test (line 11) | Test string = "test"
  function setENV (line 18) | func setENV(e string) {
  function init (line 24) | func init() {

FILE: env_test.go
  function Test_SetENV (line 7) | func Test_SetENV(t *testing.T) {
  function Test_Root (line 24) | func Test_Root(t *testing.T) {

FILE: go_version.go
  function MartiniDoesNotSupportGo1Point0 (line 5) | func MartiniDoesNotSupportGo1Point0() {

FILE: logger.go
  function Logger (line 10) | func Logger() Handler {

FILE: logger_test.go
  function Test_Logger (line 11) | func Test_Logger(t *testing.T) {

FILE: martini.go
  type Martini (line 30) | type Martini struct
    method Handlers (line 47) | func (m *Martini) Handlers(handlers ...Handler) {
    method Action (line 55) | func (m *Martini) Action(handler Handler) {
    method Logger (line 61) | func (m *Martini) Logger(logger *log.Logger) {
    method Use (line 67) | func (m *Martini) Use(handler Handler) {
    method ServeHTTP (line 74) | func (m *Martini) ServeHTTP(res http.ResponseWriter, req *http.Request) {
    method RunOnAddr (line 79) | func (m *Martini) RunOnAddr(addr string) {
    method Run (line 90) | func (m *Martini) Run() {
    method createContext (line 101) | func (m *Martini) createContext(res http.ResponseWriter, req *http.Req...
  function New (line 38) | func New() *Martini {
  type ClassicMartini (line 111) | type ClassicMartini struct
  function Classic (line 118) | func Classic() *ClassicMartini {
  type Handler (line 131) | type Handler interface
  function validateHandler (line 133) | func validateHandler(handler Handler) {
  type Context (line 140) | type Context interface
  type context (line 150) | type context struct
    method handler (line 158) | func (c *context) handler() Handler {
    method Next (line 168) | func (c *context) Next() {
    method Written (line 173) | func (c *context) Written() bool {
    method run (line 177) | func (c *context) run() {

FILE: martini_test.go
  function expect (line 11) | func expect(t *testing.T, a interface{}, b interface{}) {
  function refute (line 17) | func refute(t *testing.T, a interface{}, b interface{}) {
  function Test_New (line 23) | func Test_New(t *testing.T) {
  function Test_Martini_RunOnAddr (line 30) | func Test_Martini_RunOnAddr(t *testing.T) {
  function Test_Martini_Run (line 35) | func Test_Martini_Run(t *testing.T) {
  function Test_Martini_ServeHTTP (line 39) | func Test_Martini_ServeHTTP(t *testing.T) {
  function Test_Martini_Handlers (line 65) | func Test_Martini_Handlers(t *testing.T) {
  function Test_Martini_EarlyWrite (line 95) | func Test_Martini_EarlyWrite(t *testing.T) {
  function Test_Martini_Written (line 118) | func Test_Martini_Written(t *testing.T) {
  function Test_Martini_Basic_NoRace (line 133) | func Test_Martini_Basic_NoRace(t *testing.T) {

FILE: recovery.go
  constant panicHtml (line 15) | panicHtml = `<html>
  function stack (line 53) | func stack(skip int) []byte {
  function source (line 80) | func source(lines [][]byte, n int) []byte {
  function function (line 89) | func function(pc uintptr) []byte {
  function Recovery (line 115) | func Recovery() Handler {

FILE: recovery_test.go
  function Test_Recovery (line 11) | func Test_Recovery(t *testing.T) {
  function Test_Recovery_ResponseWriter (line 33) | func Test_Recovery_ResponseWriter(t *testing.T) {

FILE: response_writer.go
  type ResponseWriter (line 13) | type ResponseWriter interface
  type BeforeFunc (line 29) | type BeforeFunc
  function NewResponseWriter (line 32) | func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
  type responseWriter (line 40) | type responseWriter struct
    method WriteHeader (line 47) | func (rw *responseWriter) WriteHeader(s int) {
    method Write (line 53) | func (rw *responseWriter) Write(b []byte) (int, error) {
    method Status (line 63) | func (rw *responseWriter) Status() int {
    method Size (line 67) | func (rw *responseWriter) Size() int {
    method Written (line 71) | func (rw *responseWriter) Written() bool {
    method Before (line 75) | func (rw *responseWriter) Before(before BeforeFunc) {
    method Hijack (line 79) | func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
    method callBefore (line 87) | func (rw *responseWriter) callBefore() {
    method Flush (line 93) | func (rw *responseWriter) Flush() {
  type closeNotifyResponseWriter (line 100) | type closeNotifyResponseWriter struct
    method CloseNotify (line 105) | func (rw *closeNotifyResponseWriter) CloseNotify() <-chan bool {

FILE: response_writer_test.go
  type closeNotifyingRecorder (line 13) | type closeNotifyingRecorder struct
    method close (line 25) | func (c *closeNotifyingRecorder) close() {
    method CloseNotify (line 29) | func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
  function newCloseNotifyingRecorder (line 18) | func newCloseNotifyingRecorder() *closeNotifyingRecorder {
  type hijackableResponse (line 33) | type hijackableResponse struct
    method Header (line 41) | func (h *hijackableResponse) Header() http.Header           { return n...
    method Write (line 42) | func (h *hijackableResponse) Write(buf []byte) (int, error) { return 0...
    method WriteHeader (line 43) | func (h *hijackableResponse) WriteHeader(code int)          {}
    method Flush (line 44) | func (h *hijackableResponse) Flush()                        {}
    method Hijack (line 45) | func (h *hijackableResponse) Hijack() (net.Conn, *bufio.ReadWriter, er...
  function newHijackableResponse (line 37) | func newHijackableResponse() *hijackableResponse {
  function Test_ResponseWriter_WritingString (line 50) | func Test_ResponseWriter_WritingString(t *testing.T) {
  function Test_ResponseWriter_WritingStrings (line 63) | func Test_ResponseWriter_WritingStrings(t *testing.T) {
  function Test_ResponseWriter_WritingHeader (line 76) | func Test_ResponseWriter_WritingHeader(t *testing.T) {
  function Test_ResponseWriter_Before (line 88) | func Test_ResponseWriter_Before(t *testing.T) {
  function Test_ResponseWriter_Hijack (line 109) | func Test_ResponseWriter_Hijack(t *testing.T) {
  function Test_ResponseWrite_Hijack_NotOK (line 121) | func Test_ResponseWrite_Hijack_NotOK(t *testing.T) {
  function Test_ResponseWriter_CloseNotify (line 131) | func Test_ResponseWriter_CloseNotify(t *testing.T) {
  function Test_ResponseWriter_Flusher (line 145) | func Test_ResponseWriter_Flusher(t *testing.T) {
  function Test_ResponseWriter_FlusherHandler (line 154) | func Test_ResponseWriter_FlusherHandler(t *testing.T) {

FILE: return_handler.go
  type ReturnHandler (line 13) | type ReturnHandler
  function defaultReturnHandler (line 15) | func defaultReturnHandler() ReturnHandler {
  function isByteSlice (line 37) | func isByteSlice(val reflect.Value) bool {
  function canDeref (line 41) | func canDeref(val reflect.Value) bool {

FILE: router.go
  type Params (line 13) | type Params
  type Router (line 16) | type Router interface
  type router (line 47) | type router struct
    method Group (line 72) | func (r *router) Group(pattern string, fn func(Router), h ...Handler) {
    method Get (line 78) | func (r *router) Get(pattern string, h ...Handler) Route {
    method Patch (line 82) | func (r *router) Patch(pattern string, h ...Handler) Route {
    method Post (line 86) | func (r *router) Post(pattern string, h ...Handler) Route {
    method Put (line 90) | func (r *router) Put(pattern string, h ...Handler) Route {
    method Delete (line 94) | func (r *router) Delete(pattern string, h ...Handler) Route {
    method Options (line 98) | func (r *router) Options(pattern string, h ...Handler) Route {
    method Head (line 102) | func (r *router) Head(pattern string, h ...Handler) Route {
    method Any (line 106) | func (r *router) Any(pattern string, h ...Handler) Route {
    method AddRoute (line 110) | func (r *router) AddRoute(method, pattern string, h ...Handler) Route {
    method Handle (line 114) | func (r *router) Handle(res http.ResponseWriter, req *http.Request, co...
    method NotFound (line 142) | func (r *router) NotFound(handler ...Handler) {
    method addRoute (line 146) | func (r *router) addRoute(method string, pattern string, handlers []Ha...
    method appendRoute (line 166) | func (r *router) appendRoute(rt *route) {
    method getRoutes (line 172) | func (r *router) getRoutes() []*route {
    method findRoute (line 178) | func (r *router) findRoute(name string) *route {
    method URLFor (line 338) | func (r *router) URLFor(name string, params ...interface{}) string {
    method All (line 362) | func (r *router) All() []Route {
    method MethodsFor (line 383) | func (r *router) MethodsFor(path string) []string {
  type group (line 54) | type group struct
  function NewRouter (line 68) | func NewRouter() Router {
  type Route (line 189) | type Route interface
  type route (line 202) | type route struct
    method MatchMethod (line 242) | func (r route) MatchMethod(method string) RouteMatch {
    method Match (line 255) | func (r route) Match(method string, path string) (RouteMatch, map[stri...
    method Validate (line 275) | func (r *route) Validate() {
    method Handle (line 281) | func (r *route) Handle(c Context, res http.ResponseWriter) {
    method URLWith (line 291) | func (r *route) URLWith(args []string) string {
    method Name (line 311) | func (r *route) Name(name string) {
    method GetName (line 315) | func (r *route) GetName() string {
    method Pattern (line 319) | func (r *route) Pattern() string {
    method Method (line 323) | func (r *route) Method() string {
  function newRoute (line 213) | func newRoute(method string, pattern string, handlers []Handler) *route {
  type RouteMatch (line 228) | type RouteMatch
    method BetterThan (line 238) | func (r RouteMatch) BetterThan(o RouteMatch) bool {
  constant NoMatch (line 231) | NoMatch RouteMatch = iota
  constant StarMatch (line 232) | StarMatch
  constant OverloadMatch (line 233) | OverloadMatch
  constant ExactMatch (line 234) | ExactMatch
  type Routes (line 328) | type Routes interface
  function hasMethod (line 373) | func hasMethod(methods []string, method string) bool {
  type routeContext (line 394) | type routeContext struct
    method Next (line 400) | func (r *routeContext) Next() {
    method run (line 405) | func (r *routeContext) run() {

FILE: router_test.go
  function Test_Routing (line 10) | func Test_Routing(t *testing.T) {
  function Test_RouterHandlerStatusCode (line 139) | func Test_RouterHandlerStatusCode(t *testing.T) {
  function Test_RouterHandlerStacking (line 198) | func Test_RouterHandlerStacking(t *testing.T) {
  function Test_RouteMatching (line 252) | func Test_RouteMatching(t *testing.T) {
  function Test_MethodsFor (line 262) | func Test_MethodsFor(t *testing.T) {
  function Test_NotFound (line 293) | func Test_NotFound(t *testing.T) {
  function Test_NotFoundAsHandler (line 309) | func Test_NotFoundAsHandler(t *testing.T) {
  function Test_NotFoundStacking (line 349) | func Test_NotFoundStacking(t *testing.T) {
  function Test_Any (line 384) | func Test_Any(t *testing.T) {
  function Test_URLFor (line 407) | func Test_URLFor(t *testing.T) {
  function Test_AllRoutes (line 437) | func Test_AllRoutes(t *testing.T) {
  function Test_ActiveRoute (line 455) | func Test_ActiveRoute(t *testing.T) {

FILE: static.go
  type StaticOptions (line 13) | type StaticOptions struct
  function prepareStaticOptions (line 30) | func prepareStaticOptions(options []StaticOptions) StaticOptions {
  function Static (line 53) | func Static(directory string, staticOpt ...StaticOptions) Handler {

FILE: static_test.go
  function Test_Static (line 18) | func Test_Static(t *testing.T) {
  function Test_Static_Local_Path (line 40) | func Test_Static_Local_Path(t *testing.T) {
  function Test_Static_Head (line 67) | func Test_Static_Head(t *testing.T) {
  function Test_Static_As_Post (line 89) | func Test_Static_As_Post(t *testing.T) {
  function Test_Static_BadDir (line 107) | func Test_Static_BadDir(t *testing.T) {
  function Test_Static_Options_Logging (line 121) | func Test_Static_Options_Logging(t *testing.T) {
  function Test_Static_Options_ServeIndex (line 154) | func Test_Static_Options_ServeIndex(t *testing.T) {
  function Test_Static_Options_Prefix (line 175) | func Test_Static_Options_Prefix(t *testing.T) {
  function Test_Static_Options_Expires (line 197) | func Test_Static_Options_Expires(t *testing.T) {
  function Test_Static_Options_Fallback (line 218) | func Test_Static_Options_Fallback(t *testing.T) {
  function Test_Static_Redirect (line 240) | func Test_Static_Redirect(t *testing.T) {
Condensed preview — 32 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (235K chars).
[
  {
    "path": ".gitignore",
    "chars": 866,
    "preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
  },
  {
    "path": "Godeps/Godeps.json",
    "chars": 240,
    "preview": "{\n\t\"ImportPath\": \"github.com/go-martini/martini\",\n\t\"GoVersion\": \"go1.4.2\",\n\t\"Deps\": [\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/c"
  },
  {
    "path": "LICENSE",
    "chars": 1079,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Jeremy Saenz\n\nPermission is hereby granted, free of charge, to any person obta"
  },
  {
    "path": "README.md",
    "chars": 15892,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "env.go",
    "chars": 463,
    "preview": "package martini\n\nimport (\n\t\"os\"\n)\n\n// Envs\nconst (\n\tDev  string = \"development\"\n\tProd string = \"production\"\n\tTest string"
  },
  {
    "path": "env_test.go",
    "chars": 404,
    "preview": "package martini\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_SetENV(t *testing.T) {\n\ttests := []struct {\n\t\tin  string\n\t\tout string\n"
  },
  {
    "path": "go_version.go",
    "chars": 116,
    "preview": "// +build !go1.1\n\npackage martini\n\nfunc MartiniDoesNotSupportGo1Point0() {\n\t\"Martini requires Go 1.1 or greater.\"\n}\n"
  },
  {
    "path": "logger.go",
    "chars": 671,
    "preview": "package martini\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n)\n\n// Logger returns a middleware handler that logs the request as "
  },
  {
    "path": "logger_test.go",
    "chars": 593,
    "preview": "package martini\n\nimport (\n\t\"bytes\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n)\n\nfunc Test_Logger(t *testing.T) "
  },
  {
    "path": "martini.go",
    "chars": 5285,
    "preview": "// Package martini is a powerful package for quickly writing modular web applications/services in Golang.\n//\n// For a fu"
  },
  {
    "path": "martini_test.go",
    "chars": 2958,
    "preview": "package martini\n\nimport (\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"reflect\"\n\t\"testing\"\n)\n\n/* Test Helpers */\nfunc expect(t *te"
  },
  {
    "path": "recovery.go",
    "chars": 3518,
    "preview": "package martini\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"net/http\"\n\t\"runtime\"\n\n\t\"github.com/codegangsta/inject\"\n)"
  },
  {
    "path": "recovery_test.go",
    "chars": 1233,
    "preview": "package martini\n\nimport (\n\t\"bytes\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n)\n\nfunc Test_Recovery(t *testing.T"
  },
  {
    "path": "response_writer.go",
    "chars": 2778,
    "preview": "package martini\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// ResponseWriter is a wrapper around http.ResponseWrite"
  },
  {
    "path": "response_writer_test.go",
    "chars": 4245,
    "preview": "package martini\n\nimport (\n\t\"bufio\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\t\"time\"\n)\n\ntype closeNotifyi"
  },
  {
    "path": "return_handler.go",
    "chars": 1224,
    "preview": "package martini\n\nimport (\n\t\"github.com/codegangsta/inject\"\n\t\"net/http\"\n\t\"reflect\"\n)\n\n// ReturnHandler is a service that "
  },
  {
    "path": "router.go",
    "chars": 10351,
    "preview": "package martini\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"sync\"\n)\n\n// Params is a map of name/value"
  },
  {
    "path": "router_test.go",
    "chars": 13394,
    "preview": "package martini\n\nimport (\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc Test_Routing(t *testing.T) {\n\tr"
  },
  {
    "path": "static.go",
    "chars": 3299,
    "preview": "package martini\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// StaticOptions is a str"
  },
  {
    "path": "static_test.go",
    "chars": 6221,
    "preview": "package martini\n\nimport (\n\t\"bytes\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path\"\n\t\"testing\"\n\n\t\"gith"
  },
  {
    "path": "translations/README_de_DE.md",
    "chars": 16142,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_es_ES.md",
    "chars": 15073,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_fr_FR.md",
    "chars": 14641,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_ja_JP.md",
    "chars": 10913,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_ko_kr.md",
    "chars": 10697,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_pl_PL.md",
    "chars": 16520,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_pt_br.md",
    "chars": 13629,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_ru_RU.md",
    "chars": 13604,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_tr_TR.md",
    "chars": 15121,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "translations/README_zh_cn.md",
    "chars": 10156,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/174bef7e3c999e103cacfe2770102266 \"wercker status\")](https:/"
  },
  {
    "path": "translations/README_zh_tw.md",
    "chars": 10475,
    "preview": "# Martini  [![wercker status](https://app.wercker.com/status/9b7dbc6e2654b604cd694d191c3d5487/s/master \"wercker status\")"
  },
  {
    "path": "wercker.yml",
    "chars": 25,
    "preview": "box: wercker/golang@1.1.1"
  }
]

About this extraction

This page contains the full source code of the go-martini/martini GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 32 files (216.6 KB), approximately 65.2k tokens, and a symbol index with 159 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!