martini.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // Package martini is a powerful package for quickly writing modular web applications/services in Golang.
  2. //
  3. // For a full guide visit http://github.com/go-martini/martini
  4. //
  5. // package main
  6. //
  7. // import "github.com/go-martini/martini"
  8. //
  9. // func main() {
  10. // m := martini.Classic()
  11. //
  12. // m.Get("/", func() string {
  13. // return "Hello world!"
  14. // })
  15. //
  16. // m.Run()
  17. // }
  18. package martini
  19. import (
  20. "log"
  21. "net/http"
  22. "os"
  23. "reflect"
  24. "github.com/codegangsta/inject"
  25. )
  26. // Martini represents the top level web application. inject.Injector methods can be invoked to map services on a global level.
  27. type Martini struct {
  28. inject.Injector
  29. handlers []Handler
  30. action Handler
  31. logger *log.Logger
  32. }
  33. // New creates a bare bones Martini instance. Use this method if you want to have full control over the middleware that is used.
  34. func New() *Martini {
  35. m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[martini] ", 0)}
  36. m.Map(m.logger)
  37. m.Map(defaultReturnHandler())
  38. return m
  39. }
  40. // Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
  41. // Will panic if any of the handlers is not a callable function
  42. func (m *Martini) Handlers(handlers ...Handler) {
  43. m.handlers = make([]Handler, 0)
  44. for _, handler := range handlers {
  45. m.Use(handler)
  46. }
  47. }
  48. // 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().
  49. func (m *Martini) Action(handler Handler) {
  50. validateHandler(handler)
  51. m.action = handler
  52. }
  53. // Logger sets the logger
  54. func (m *Martini) Logger(logger *log.Logger) {
  55. m.logger = logger
  56. m.Map(m.logger)
  57. }
  58. // 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.
  59. func (m *Martini) Use(handler Handler) {
  60. validateHandler(handler)
  61. m.handlers = append(m.handlers, handler)
  62. }
  63. // ServeHTTP is the HTTP Entry point for a Martini instance. Useful if you want to control your own HTTP server.
  64. func (m *Martini) ServeHTTP(res http.ResponseWriter, req *http.Request) {
  65. m.createContext(res, req).run()
  66. }
  67. // Run the http server on a given host and port.
  68. func (m *Martini) RunOnAddr(addr string) {
  69. // TODO: Should probably be implemented using a new instance of http.Server in place of
  70. // calling http.ListenAndServer directly, so that it could be stored in the martini struct for later use.
  71. // This would also allow to improve testing when a custom host and port are passed.
  72. logger := m.Injector.Get(reflect.TypeOf(m.logger)).Interface().(*log.Logger)
  73. logger.Printf("listening on %s (%s)\n", addr, Env)
  74. logger.Fatalln(http.ListenAndServe(addr, m))
  75. }
  76. // Run the http server. Listening on os.GetEnv("PORT") or 3000 by default.
  77. func (m *Martini) Run() {
  78. port := os.Getenv("PORT")
  79. if len(port) == 0 {
  80. port = "3000"
  81. }
  82. host := os.Getenv("HOST")
  83. m.RunOnAddr(host + ":" + port)
  84. }
  85. func (m *Martini) createContext(res http.ResponseWriter, req *http.Request) *context {
  86. c := &context{inject.New(), m.handlers, m.action, NewResponseWriter(res), 0}
  87. c.SetParent(m)
  88. c.MapTo(c, (*Context)(nil))
  89. c.MapTo(c.rw, (*http.ResponseWriter)(nil))
  90. c.Map(req)
  91. return c
  92. }
  93. // ClassicMartini represents a Martini with some reasonable defaults. Embeds the router functions for convenience.
  94. type ClassicMartini struct {
  95. *Martini
  96. Router
  97. }
  98. // Classic creates a classic Martini with some basic default middleware - martini.Logger, martini.Recovery and martini.Static.
  99. // Classic also maps martini.Routes as a service.
  100. func Classic() *ClassicMartini {
  101. r := NewRouter()
  102. m := New()
  103. m.Use(Logger())
  104. m.Use(Recovery())
  105. m.Use(Static("public"))
  106. m.MapTo(r, (*Routes)(nil))
  107. m.Action(r.Handle)
  108. return &ClassicMartini{m, r}
  109. }
  110. // Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
  111. // Martini will panic if an argument could not be fullfilled via dependency injection.
  112. type Handler interface{}
  113. func validateHandler(handler Handler) {
  114. if reflect.TypeOf(handler).Kind() != reflect.Func {
  115. panic("martini handler must be a callable func")
  116. }
  117. }
  118. // Context represents a request context. Services can be mapped on the request level from this interface.
  119. type Context interface {
  120. inject.Injector
  121. // Next is an optional function that Middleware Handlers can call to yield the until after
  122. // the other Handlers have been executed. This works really well for any operations that must
  123. // happen after an http request
  124. Next()
  125. // Written returns whether or not the response for this context has been written.
  126. Written() bool
  127. }
  128. type context struct {
  129. inject.Injector
  130. handlers []Handler
  131. action Handler
  132. rw ResponseWriter
  133. index int
  134. }
  135. func (c *context) handler() Handler {
  136. if c.index < len(c.handlers) {
  137. return c.handlers[c.index]
  138. }
  139. if c.index == len(c.handlers) {
  140. return c.action
  141. }
  142. panic("invalid index for context handler")
  143. }
  144. func (c *context) Next() {
  145. c.index += 1
  146. c.run()
  147. }
  148. func (c *context) Written() bool {
  149. return c.rw.Written()
  150. }
  151. func (c *context) run() {
  152. for c.index <= len(c.handlers) {
  153. _, err := c.Invoke(c.handler())
  154. if err != nil {
  155. panic(err)
  156. }
  157. c.index += 1
  158. if c.Written() {
  159. return
  160. }
  161. }
  162. }