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 tag para perguntas no Stackoverflow
- Extrema simplicidade no uso.
- Não intrusivo ao desenho da app.
- Funciona bem com outros pacotes Golang.
- Impressionante caminho de correspondência e rotas.
- 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 e rodar facilmente, martini.Classic() prove algumas ferramentas rasoá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 ira escrever o resultado atual http.ResponseWriter que é uma string:
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ço e tentar resolver sua dependencia via tipo de afirmação:
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 Go documentation 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 request 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 pode ser chamado ao bloco até depois que outros Handlers tenham sido executados. Isso funciona muito bem para todas as operações que devem acontecer depois de um request HTTP:
// 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 vs 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 implementando 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 http.ListenAndServe
.
m := martini.Classic()
// ...
log.Fatal(http.ListenAndServe(":8080", m))
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