ghttp_request_middleware.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package ghttp
  7. import (
  8. "github.com/gogf/gf/errors/gerror"
  9. "net/http"
  10. "reflect"
  11. "github.com/gogf/gf/util/gutil"
  12. )
  13. // Middleware is the plugin for request workflow management.
  14. type Middleware struct {
  15. served bool // Is the request served, which is used for checking response status 404.
  16. request *Request // The request object pointer.
  17. handlerIndex int // Index number for executing sequence purpose for handler items.
  18. handlerMDIndex int // Index number for executing sequence purpose for bound middleware of handler item.
  19. }
  20. // Next calls the next workflow handler.
  21. // It's an important function controlling the workflow of the server request execution.
  22. func (m *Middleware) Next() {
  23. var item *handlerParsedItem
  24. var loop = true
  25. for loop {
  26. // Check whether the request is exited.
  27. if m.request.IsExited() || m.handlerIndex >= len(m.request.handlers) {
  28. break
  29. }
  30. item = m.request.handlers[m.handlerIndex]
  31. // Filter the HOOK handlers, which are designed to be called in another standalone procedure.
  32. if item.handler.itemType == handlerTypeHook {
  33. m.handlerIndex++
  34. continue
  35. }
  36. // Current router switching.
  37. m.request.Router = item.handler.router
  38. // Router values switching.
  39. m.request.routerMap = item.values
  40. gutil.TryCatch(func() {
  41. // Execute bound middleware array of the item if it's not empty.
  42. if m.handlerMDIndex < len(item.handler.middleware) {
  43. md := item.handler.middleware[m.handlerMDIndex]
  44. m.handlerMDIndex++
  45. niceCallFunc(func() {
  46. md(m.request)
  47. })
  48. loop = false
  49. return
  50. }
  51. m.handlerIndex++
  52. switch item.handler.itemType {
  53. // Service controller.
  54. case handlerTypeController:
  55. m.served = true
  56. if m.request.IsExited() {
  57. break
  58. }
  59. c := reflect.New(item.handler.ctrlInfo.reflect)
  60. niceCallFunc(func() {
  61. c.MethodByName("Init").Call([]reflect.Value{reflect.ValueOf(m.request)})
  62. })
  63. if !m.request.IsExited() {
  64. niceCallFunc(func() {
  65. c.MethodByName(item.handler.ctrlInfo.name).Call(nil)
  66. })
  67. }
  68. if !m.request.IsExited() {
  69. niceCallFunc(func() {
  70. c.MethodByName("Shut").Call(nil)
  71. })
  72. }
  73. // Service object.
  74. case handlerTypeObject:
  75. m.served = true
  76. if m.request.IsExited() {
  77. break
  78. }
  79. if item.handler.initFunc != nil {
  80. niceCallFunc(func() {
  81. item.handler.initFunc(m.request)
  82. })
  83. }
  84. if !m.request.IsExited() {
  85. niceCallFunc(func() {
  86. item.handler.itemFunc(m.request)
  87. })
  88. }
  89. if !m.request.IsExited() && item.handler.shutFunc != nil {
  90. niceCallFunc(func() {
  91. item.handler.shutFunc(m.request)
  92. })
  93. }
  94. // Service handler.
  95. case handlerTypeHandler:
  96. m.served = true
  97. if m.request.IsExited() {
  98. break
  99. }
  100. niceCallFunc(func() {
  101. item.handler.itemFunc(m.request)
  102. })
  103. // Global middleware array.
  104. case handlerTypeMiddleware:
  105. niceCallFunc(func() {
  106. item.handler.itemFunc(m.request)
  107. })
  108. // It does not continue calling next middleware after another middleware done.
  109. // There should be a "Next" function to be called in the middleware in order to manage the workflow.
  110. loop = false
  111. }
  112. }, func(exception error) {
  113. if e, ok := exception.(errorStack); ok {
  114. // It's already an error that has stack info.
  115. m.request.error = e
  116. } else {
  117. // Create a new error with stack info.
  118. // Note that there's a skip pointing the start stacktrace
  119. // of the real error point.
  120. m.request.error = gerror.WrapSkip(1, exception, "")
  121. }
  122. m.request.Response.WriteStatus(http.StatusInternalServerError, exception)
  123. loop = false
  124. })
  125. }
  126. // Check the http status code after all handler and middleware done.
  127. if m.request.IsExited() || m.handlerIndex >= len(m.request.handlers) {
  128. if m.request.Response.Status == 0 {
  129. if m.request.Middleware.served {
  130. m.request.Response.WriteHeader(http.StatusOK)
  131. } else {
  132. m.request.Response.WriteHeader(http.StatusNotFound)
  133. }
  134. }
  135. }
  136. }