tan.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package tango
  2. import (
  3. "net/http"
  4. "os"
  5. )
  6. const (
  7. Dev = iota
  8. Prod
  9. )
  10. var (
  11. Env = Dev
  12. modes = []string{
  13. "Dev",
  14. "Product",
  15. }
  16. )
  17. func Version() string {
  18. return "0.2.8.0326"
  19. }
  20. type Tango struct {
  21. Router
  22. Mode int
  23. handlers []Handler
  24. logger Logger
  25. ErrHandler Handler
  26. }
  27. var (
  28. ClassicHandlers = []Handler{
  29. Logging(),
  30. Recovery(true),
  31. Compresses([]string{".js", ".css", ".html", ".htm"}),
  32. Static(StaticOptions{Prefix: "public"}),
  33. Return(),
  34. Responses(),
  35. Requests(),
  36. Param(),
  37. Contexts(),
  38. }
  39. )
  40. func (t *Tango) Logger() Logger {
  41. return t.logger
  42. }
  43. func (t *Tango) Get(url string, c interface{}) {
  44. t.Route([]string{"GET", "HEAD"}, url, c)
  45. }
  46. func (t *Tango) Post(url string, c interface{}) {
  47. t.Route([]string{"POST"}, url, c)
  48. }
  49. func (t *Tango) Head(url string, c interface{}) {
  50. t.Route([]string{"HEAD"}, url, c)
  51. }
  52. func (t *Tango) Options(url string, c interface{}) {
  53. t.Route([]string{"OPTIONS"}, url, c)
  54. }
  55. func (t *Tango) Trace(url string, c interface{}) {
  56. t.Route([]string{"TRACE"}, url, c)
  57. }
  58. func (t *Tango) Patch(url string, c interface{}) {
  59. t.Route([]string{"PATCH"}, url, c)
  60. }
  61. func (t *Tango) Delete(url string, c interface{}) {
  62. t.Route([]string{"DELETE"}, url, c)
  63. }
  64. func (t *Tango) Put(url string, c interface{}) {
  65. t.Route([]string{"PUT"}, url, c)
  66. }
  67. func (t *Tango) Any(url string, c interface{}) {
  68. t.Route(SupportMethods, url, c)
  69. }
  70. func (t *Tango) Use(handlers ...Handler) {
  71. t.handlers = append(t.handlers, handlers...)
  72. }
  73. func (t *Tango) Run(addrs ...string) {
  74. var addr string
  75. if len(addrs) == 0 {
  76. addr = ":8000"
  77. } else {
  78. addr = addrs[0]
  79. }
  80. t.logger.Info("listening on", addr, modes[t.Mode])
  81. err := http.ListenAndServe(addr, t)
  82. if err != nil {
  83. t.logger.Error(err)
  84. }
  85. }
  86. func (t *Tango) RunTLS(certFile, keyFile string, addrs ...string) {
  87. var addr string
  88. if len(addrs) == 0 {
  89. addr = ":8000"
  90. } else {
  91. addr = addrs[0]
  92. }
  93. t.logger.Info("listening on https", addr, modes[t.Mode])
  94. err := http.ListenAndServeTLS(addr, certFile, keyFile, t)
  95. if err != nil {
  96. t.logger.Error(err)
  97. }
  98. }
  99. type HandlerFunc func(ctx *Context)
  100. func (h HandlerFunc) Handle(ctx *Context) {
  101. h(ctx)
  102. }
  103. func WrapBefore(handler http.Handler) HandlerFunc {
  104. return func(ctx *Context) {
  105. handler.ServeHTTP(ctx.ResponseWriter, ctx.Req())
  106. ctx.Next()
  107. }
  108. }
  109. func WrapAfter(handler http.Handler) HandlerFunc {
  110. return func(ctx *Context) {
  111. ctx.Next()
  112. handler.ServeHTTP(ctx.ResponseWriter, ctx.Req())
  113. }
  114. }
  115. func (t *Tango) UseHandler(handler http.Handler) {
  116. t.Use(WrapBefore(handler))
  117. }
  118. func (t *Tango) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  119. ctx := NewContext(
  120. t,
  121. req,
  122. NewResponseWriter(w),
  123. t.logger,
  124. )
  125. ctx.Invoke()
  126. // if there is no logging or error handle, so the last written check.
  127. if !ctx.Written() {
  128. p := req.URL.Path
  129. if len(req.URL.RawQuery) > 0 {
  130. p = p + "?" + req.URL.RawQuery
  131. }
  132. if ctx.Route() != nil {
  133. if ctx.Result == nil {
  134. ctx.Write([]byte(""))
  135. t.logger.Info(req.Method, ctx.Status(), p)
  136. return
  137. }
  138. panic("result should be handler before")
  139. }
  140. if ctx.Result == nil {
  141. ctx.Result = NotFound()
  142. }
  143. ctx.HandleError()
  144. t.logger.Error(req.Method, ctx.Status(), p)
  145. }
  146. }
  147. func NewWithLog(logger Logger, handlers ...Handler) *Tango {
  148. tango := &Tango{
  149. Router: NewRouter(),
  150. Mode: Env,
  151. logger: logger,
  152. handlers: make([]Handler, 0),
  153. ErrHandler: Errors(),
  154. }
  155. tango.Use(handlers...)
  156. return tango
  157. }
  158. func New(handlers ...Handler) *Tango {
  159. return NewWithLog(NewLogger(os.Stdout), handlers...)
  160. }
  161. func Classic(l ...Logger) *Tango {
  162. var logger Logger
  163. if len(l) == 0 {
  164. logger = NewLogger(os.Stdout)
  165. } else {
  166. logger = l[0]
  167. }
  168. return NewWithLog(
  169. logger,
  170. ClassicHandlers...,
  171. )
  172. }