negroni.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package negroni
  2. import (
  3. "log"
  4. "net/http"
  5. "os"
  6. )
  7. const (
  8. // DefaultAddress is used if no other is specified.
  9. DefaultAddress = ":8080"
  10. )
  11. // Handler handler is an interface that objects can implement to be registered to serve as middleware
  12. // in the Negroni middleware stack.
  13. // ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc
  14. // passed in.
  15. //
  16. // If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked.
  17. type Handler interface {
  18. ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
  19. }
  20. // HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.
  21. // If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.
  22. type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
  23. func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  24. h(rw, r, next)
  25. }
  26. type middleware struct {
  27. handler Handler
  28. next *middleware
  29. }
  30. func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
  31. m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
  32. }
  33. // Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni
  34. // middleware. The next http.HandlerFunc is automatically called after the Handler
  35. // is executed.
  36. func Wrap(handler http.Handler) Handler {
  37. return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  38. handler.ServeHTTP(rw, r)
  39. next(rw, r)
  40. })
  41. }
  42. // WrapFunc converts a http.HandlerFunc into a negroni.Handler so it can be used as a Negroni
  43. // middleware. The next http.HandlerFunc is automatically called after the Handler
  44. // is executed.
  45. func WrapFunc(handlerFunc http.HandlerFunc) Handler {
  46. return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  47. handlerFunc(rw, r)
  48. next(rw, r)
  49. })
  50. }
  51. // Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler.
  52. // Negroni middleware is evaluated in the order that they are added to the stack using
  53. // the Use and UseHandler methods.
  54. type Negroni struct {
  55. middleware middleware
  56. handlers []Handler
  57. }
  58. // New returns a new Negroni instance with no middleware preconfigured.
  59. func New(handlers ...Handler) *Negroni {
  60. return &Negroni{
  61. handlers: handlers,
  62. middleware: build(handlers),
  63. }
  64. }
  65. // With returns a new Negroni instance that is a combination of the negroni
  66. // receiver's handlers and the provided handlers.
  67. func (n *Negroni) With(handlers ...Handler) *Negroni {
  68. return New(
  69. append(n.handlers, handlers...)...,
  70. )
  71. }
  72. // Classic returns a new Negroni instance with the default middleware already
  73. // in the stack.
  74. //
  75. // Recovery - Panic Recovery Middleware
  76. // Logger - Request/Response Logging
  77. // Static - Static File Serving
  78. func Classic() *Negroni {
  79. return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public")))
  80. }
  81. func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
  82. n.middleware.ServeHTTP(NewResponseWriter(rw), r)
  83. }
  84. // Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
  85. func (n *Negroni) Use(handler Handler) {
  86. if handler == nil {
  87. panic("handler cannot be nil")
  88. }
  89. n.handlers = append(n.handlers, handler)
  90. n.middleware = build(n.handlers)
  91. }
  92. // UseFunc adds a Negroni-style handler function onto the middleware stack.
  93. func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {
  94. n.Use(HandlerFunc(handlerFunc))
  95. }
  96. // UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
  97. func (n *Negroni) UseHandler(handler http.Handler) {
  98. n.Use(Wrap(handler))
  99. }
  100. // UseHandlerFunc adds a http.HandlerFunc-style handler function onto the middleware stack.
  101. func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) {
  102. n.UseHandler(http.HandlerFunc(handlerFunc))
  103. }
  104. // Run is a convenience function that runs the negroni stack as an HTTP
  105. // server. The addr string, if provided, takes the same format as http.ListenAndServe.
  106. // If no address is provided but the PORT environment variable is set, the PORT value is used.
  107. // If neither is provided, the address' value will equal the DefaultAddress constant.
  108. func (n *Negroni) Run(addr ...string) {
  109. l := log.New(os.Stdout, "[negroni] ", 0)
  110. finalAddr := detectAddress(addr...)
  111. l.Printf("listening on %s", finalAddr)
  112. l.Fatal(http.ListenAndServe(finalAddr, n))
  113. }
  114. func detectAddress(addr ...string) string {
  115. if len(addr) > 0 {
  116. return addr[0]
  117. }
  118. if port := os.Getenv("PORT"); port != "" {
  119. return ":" + port
  120. }
  121. return DefaultAddress
  122. }
  123. // Returns a list of all the handlers in the current Negroni middleware chain.
  124. func (n *Negroni) Handlers() []Handler {
  125. return n.handlers
  126. }
  127. func build(handlers []Handler) middleware {
  128. var next middleware
  129. if len(handlers) == 0 {
  130. return voidMiddleware()
  131. } else if len(handlers) > 1 {
  132. next = build(handlers[1:])
  133. } else {
  134. next = voidMiddleware()
  135. }
  136. return middleware{handlers[0], &next}
  137. }
  138. func voidMiddleware() middleware {
  139. return middleware{
  140. HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}),
  141. &middleware{},
  142. }
  143. }