Skip to content

Latest commit

 

History

History
483 lines (366 loc) · 16.7 KB

README_pt_br.md

File metadata and controls

483 lines (366 loc) · 16.7 KB

Negroni

GoDoc Build Status codebeat codecov

Notice: Esta é uma biblioteca conhecida anteriormente como github.com/codegangsta/negroni -- Github irá redirecionar automaticamente os pedidos para este repositório, mas recomendas atualizar suas referências por clareza.

Negroni é uma abordagem idiomática para middleware web em Go. É pequeno, não intrusivo, e incentiva uso da biblioteca net/http.

Se gosta da idéia do Martini, mas acha que contém muita mágica, então Negroni é ideal.

Idiomas traduzidos:

Começando

Depois de instalar Go e definir seu GOPATH, criar seu primeiro arquivo .go. Iremos chamá-lo server.go.

package main

import (
  "fmt"
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.Classic() // Includes some default middlewares
  n.UseHandler(mux)

  http.ListenAndServe(":3000", n)
}

Depois instale o pacote Negroni (go 1.1 ou superior)

go get github.com/urfave/negroni

Depois execute seu servidor:

go run server.go

Agora terá um servidor web Go net/http rodando em localhost:3000.

Empacotamento

Se você está no Debian, negroni também está disponível como um pacote que você podee instalar via apt install golang-github-urfave-negroni-dev (no momento queisto for escrito, ele estava em repositórios do sid).

Negroni é um Framework?

Negroni não é a framework. É uma biblioteca que é desenhada para trabalhar diretamente com net/http.

Roteamento?

Negroni é TSPR(Traga seu próprio Roteamento). A comunidade Go já tem um grande número de roteadores http disponíveis, Negroni tenta rodar bem com todos eles pelo suporte total net/http/ Por exemplo, a integração com Gorilla Mux se parece com isso:

router := mux.NewRouter()
router.HandleFunc("/", HomeHandler)

n := negroni.New(Middleware1, Middleware2)
// Or use a middleware with the Use() function
n.Use(Middleware3)
// router goes last
n.UseHandler(router)

n.Run(":3000")

negroni.Classic()

negroni.Classic() fornece alguns middlewares padrão que são úteis para maioria das aplicações:

  • negroni.Recovery - Panic Recovery Middleware.
  • negroni.Logging - Request/Response Logging Middleware.
  • negroni.Static - Static File serving under the "public" directory.

Isso torna muito fácil começar com alguns recursos úteis do Negroni.

Handlers

Negroni fornece um middleware de fluxo bidirecional. Isso é feito através da interface negroni.Handler:

type Handler interface {
  ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
}

Se um middleware não tenha escrito o ResponseWriter, ele deve chamar a próxima http.HandlerFunc na cadeia para produzir o próximo handler middleware. Isso pode ser usado muito bem:

func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  // do some stuff before
  next(rw, r)
  // do some stuff after
}

E pode mapear isso para a cadeia de handler com a função Use:

n := negroni.New()
n.Use(negroni.HandlerFunc(MyMiddleware))

Você também pode mapear http.Handler antigos:

n := negroni.New()

mux := http.NewServeMux()
// map your routes

n.UseHandler(mux)

http.ListenAndServe(":3000", n)

With()

Negroni tem uma conveniente função chamada With. With pega uma ou mais instâncias Handler e retorna um novo Negroni com a combinação dos handlers de receivers e os novos handlers.

// middleware we want to reuse
common := negroni.New()
common.Use(MyMiddleware1)
common.Use(MyMiddleware2)

// `specific` is a new negroni with the handlers from `common` combined with the
// the handlers passed in
specific := common.With(
	SpecificMiddleware1,
	SpecificMiddleware2
)

Run()

Negroni tem uma função de conveniência chamada Run. Run pega um endereço de string idêntico para http.ListenAndServe.

package main

import (
  "github.com/urfave/negroni"
)

func main() {
  n := negroni.Classic()
  n.Run(":8080")
}

Se nenhum endereço for fornecido, a variável de ambiente PORT é usada no lugar. Se a variável de ambiente PORT não for definida, o endereço padrão será usado. Veja Run para uma descrição completa.

No geral, você irá quere usar métodos net/http e passar negroni como um Handler, como ele é mais flexível, e.g.:

package main

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

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.Classic() // Includes some default middlewares
  n.UseHandler(mux)

  s := &http.Server{
    Addr:           ":8080",
    Handler:        n,
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
  }
  log.Fatal(s.ListenAndServe())
}

Middleware para Rotas Específicas

Se você tem um grupo de rota com rotas que precisam ser executadas por um middleware específico, pode simplesmente criar uma nova instância de Negroni e usar no seu Manipulador de rota.

router := mux.NewRouter()
adminRoutes := mux.NewRouter()
// add admin routes here

// Create a new negroni for the admin middleware
router.PathPrefix("/admin").Handler(negroni.New(
  Middleware1,
  Middleware2,
  negroni.Wrap(adminRoutes),
))

Se você está usando Gorilla Mux, aqui é um exemplo usando uma subrota:

router := mux.NewRouter()
subRouter := mux.NewRouter().PathPrefix("/subpath").Subrouter().StrictSlash(true)
subRouter.HandleFunc("/", someSubpathHandler) // "/subpath/"
subRouter.HandleFunc("/:id", someSubpathHandler) // "/subpath/:id"

// "/subpath" is necessary to ensure the subRouter and main router linkup
router.PathPrefix("/subpath").Handler(negroni.New(
  Middleware1,
  Middleware2,
  negroni.Wrap(subRouter),
))

With() pode ser usado para eliminar redundância por middlewares compartilhados através de rotas.

router := mux.NewRouter()
apiRoutes := mux.NewRouter()
// add api routes here
webRoutes := mux.NewRouter()
// add web routes here

// create common middleware to be shared across routes
common := negroni.New(
	Middleware1,
	Middleware2,
)

// create a new negroni for the api middleware
// using the common middleware as a base
router.PathPrefix("/api").Handler(common.With(
  APIMiddleware1,
  negroni.Wrap(apiRoutes),
))
// create a new negroni for the web middleware
// using the common middleware as a base
router.PathPrefix("/web").Handler(common.With(
  WebMiddleware1,
  negroni.Wrap(webRoutes),
))

Bundled Middleware

Static

Este middleware servirá arquivos do filesystem. Se os arquivos não existerem, ele substituirá a requisição para o próximo middleware. Se você quer que as requisições para arquivos não existentes retorne um 404 File Not Found para o user você deve olhar em usando http.FileServer como um handler.

Exemplo:

package main

import (
  "fmt"
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  // Example of using a http.FileServer if you want "server-like" rather than "middleware" behavior
  // mux.Handle("/public", http.FileServer(http.Dir("/home/public")))

  n := negroni.New()
  n.Use(negroni.NewStatic(http.Dir("/tmp")))
  n.UseHandler(mux)

  http.ListenAndServe(":3002", n)
}

Serviá arquivos do diretório /tmp primeiro, mas substituirá chamadas para o próximo handler se a requisição não encontrar um arquivo no filesystem.

Recovery

Este middleware pega repostas de panic com um código de resposta 500. Se algum outro middleware escreveu um código resposta ou conteúdo, este middleware falhará corretamente enviando um 500 para o cliente, como o cliente já recebeu o código de resposta HTTP. Adicionalmente um PanicHandlerFunc pode ser anexado para reportar 500 para um serviço de report como um Sentry ou Airbrake.

Exemplo:

package main

import (
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    panic("oh no")
  })

  n := negroni.New()
  n.Use(negroni.NewRecovery())
  n.UseHandler(mux)

  http.ListenAndServe(":3003", n)
}

Irá retornar um 500 Internal Server Error para cada requisição. Ele também irá registrar stack trace bem como um print na stack tarce para quem fez a requisição if PrintStack estiver setado como true (o padrão).

Exemplo com handler de erro:

package main

import (
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    panic("oh no")
  })

  n := negroni.New()
  recovery := negroni.NewRecovery()
  recovery.PanicHandlerFunc = reportToSentry
  n.Use(recovery)
  n.UseHandler(mux)

  http.ListenAndServe(":3003", n)
}

func reportToSentry(info *negroni.PanicInformation) {
    // write code here to report error to Sentry
}

Logger

Este middleware loga cada entrada de requisição e resposta.

Exemplo:

package main

import (
  "fmt"
  "net/http"

  "github.com/urfave/negroni"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.New()
  n.Use(negroni.NewLogger())
  n.UseHandler(mux)

  http.ListenAndServe(":3004", n)
}

Irá printar um log simular para:

[negroni] 2017-10-04T14:56:25+02:00 | 200 |      378µs | localhost:3004 | GET /

em cada request.

Você também pode definir seu próprio formato de log chamando a função SetFormat. O formato é uma string de template como os campos como mencionados na struct LoggerEntry. Então, como exemplo -

l.SetFormat("[{{.Status}} {{.Duration}}] - {{.Request.UserAgent}}")

Mostrará algo como - [200 18.263µs] - Go-User-Agent/1.1

Middleware de Terceiros

Aqui está uma lista atual de Middleware Compatíveis com Negroni. Sinta se livre para mandar um PR vinculando seu middleware se construiu um:

Middleware Autor Descrição
authz Yang Luo ACL, RBAC, ABAC Authorization middlware based on Casbin
binding Matt Holt Data binding from HTTP requests into structs
cloudwatch Colin Steele AWS cloudwatch metrics middleware
cors Olivier Poitrey Cross Origin Resource Sharing (CORS) support
csp Awake Networks Content Security Policy (CSP) support
delay Jeff Martinez Add delays/latency to endpoints. Useful when testing effects of high latency
New Relic Go Agent Yadvendar Champawat Official New Relic Go Agent (currently in beta)
gorelic Jingwen Owen Ou New Relic agent for Go runtime
Graceful Tyler Bunnell Graceful HTTP Shutdown
gzip phyber GZIP response compression
JWT Middleware Auth0 Middleware checks for a JWT on the Authorization header on incoming requests and decodes it
logrus Dan Buch Logrus-based logger
oauth2 David Bochenski oAuth2 middleware
onthefly Alexander Rødseth Generate TinySVG, HTML and CSS on the fly
permissions2 Alexander Rødseth Cookies, users and permissions
prometheus Rene Zbinden Easily create metrics endpoint for the prometheus instrumentation tool
render Cory Jacobsen Render JSON, XML and HTML templates
RestGate Prasanga Siripala Secure authentication for REST API endpoints
secure Cory Jacobsen Middleware that implements a few quick security wins
sessions David Bochenski Session Management
stats Florent Messa Store information about your web application (response time, etc.)
VanGoH Taylor Wrobel Configurable AWS-Style HMAC authentication middleware
xrequestid Andrea Franz Middleware that assigns a random X-Request-Id header to each request
mgo session Joel James Middleware that handles creating and closing mgo sessions per request
digits Bilal Amarni Middleware that handles Twitter Digits authentication
stats Chirag Gupta Middleware that manages qps and latency stats for your endpoints and asynchronously flushes them to influx db

Exemplos

Alexander Rødseth criou mooseware, uma estrutura para escrever um handler middleware Negroni.

Prasanga Siripala Criou um efetivo estrutura esqueleto para projetos Go/Negroni baseados na web: Go-Skeleton

Servidor com autoreload?

gin e fresh são aplicativos para autoreload do Negroni.

Leitura Essencial para Iniciantes em Go & Negroni

Sobre

Negroni é obsessivamente desenhado por ninguém menos que Code Gangsta