NOTA: O martini framework não é mais mantido.
Martini é um poderoso pacote para escrever aplicações/serviços modulares em Golang..
Após a instalação do Go e de configurar o GOPATH, crie seu primeiro arquivo .go
. Vamos chamá-lo de server.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
.
Assine a Lista de email
Veja o Vídeo demonstrativo
Use a tag martini para perguntas no Stackoverflow
- 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.
Para mais middleware e funcionalidades, veja os repositórios em martini-contrib.
Para iniciar rapidamente, martini.Classic() provê algumas ferramentas razoáveis para maioria das aplicações web:
m := martini.Classic()
// ... middleware e rota aqui
m.Run()
Algumas das funcionalidade que o martini.Classic() oferece automaticamente são:
- Request/Response Logging - martini.Logger
- Panic Recovery - martini.Recovery
- Servidor de arquivos státicos - martini.Static
- Rotas - martini.Router
Handlers são o coração e a alma do Martini. Um handler é basicamente qualquer função que pode ser chamada:
m.Get("/", func() {
println("hello world")
})
Se um handler retornar alguma coisa, Martini irá escrever o valor retornado como uma string ao http.ResponseWriter:
m.Get("/", func() string {
return "hello world" // HTTP 200 : "hello world"
})
Você também pode retornar o código de status:
m.Get("/", func() (int, string) {
return 418, "Eu sou um bule" // HTTP 418 : "Eu sou um bule"
})
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:
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():
- *log.Logger - Log Global para Martini.
- martini.Context - http request context.
- martini.Params -
map[string]string
de nomes dos parâmetros buscados pela rota. - martini.Routes - Serviço de auxílio as rotas.
- http.ResponseWriter - http Response escreve a interface.
- *http.Request - http Request.
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:
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:
m.Get("/hello/:name", func(params martini.Params) string {
return "Hello " + params["name"]
})
As rotas podem ser combinados com expressões regulares e globs:
m.Get("/hello/**", func(params martini.Params) string {
return "Hello " + params["_1"]
})
Expressões regulares podem ser bem usadas:
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 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:
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.
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.
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 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.
Um exemplo onde o Martini implementa a interface inject.Injector, então o mapeamento de um serviço é fácil:
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // o serviço estará disponível para todos os handlers *MyDatabase.
// ...
m.Run()
Mapeamento do nível de request pode ser feito via handler através martini.Context:
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
logger := &MyCustomLogger{req}
c.Map(logger) // mapeamento é *MyCustomLogger
}
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 com um objeto que envolveu-o e realizou operações extras, você pode escrever o seguinte handler:
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
rw := NewSpecialResponseWriter(res)
c.MapTo(rw, (*http.ResponseWriter)(nil)) // substituir ResponseWriter com nosso ResponseWriter invólucro
}
Uma instância de 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 handlers.
m.Use(martini.Static("assets")) // servindo os arquivos do diretório "assets"
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:
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:
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:
// 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)
}
})
Context.Next() é 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:
// 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 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.
Inicie sua busca nos projetos 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 - Handlers para autenticação.
- binding - Handler para mapeamento/validação de um request a estrutura.
- gzip - Handler para adicionar compreção gzip para o requests
- render - Handler que providencia uma rederização simples para JSON e templates HTML.
- acceptlang - Handler para parsing do
Accept-Language
no header HTTP. - sessions - Handler que prove o serviço de sessão.
- strip - URL Prefix stripping.
- method - HTTP método de substituição via cabeçalho ou campos do formulário.
- secure - Implementa rapidamente itens de segurança.
- encoder - Serviço Encoder para renderização de dados em vários formatos e negociação de conteúdo.
- cors - Handler que habilita suporte a CORS.
- 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.
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:
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)
}
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
.
m := martini.Classic()
// ...
log.Fatal(m.RunOnAddr(":8080"))
gin e fresh são aplicativos para autoreload do Martini.
Martini é feito para ser mantido pequeno e limpo. A maioria das contribuições devem ser feitas no repositório martini-contrib. Se quiser contribuir com o core do Martini fique livre para fazer um Pull Request.
Inspirado por express e sinatra
Martini is obsessively designed by none other than the Code Gangsta