You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
5.8KB

  1. /* ----------------------------------------------------------------------
  2. * ______ ___ __
  3. * / ____/___ / | ____ __ ___ __/ /_ ___ ________
  4. * / / __/ __ \/ /| | / __ \/ / / / | /| / / __ \/ _ \/ ___/ _ \
  5. * / /_/ / /_/ / ___ |/ / / / /_/ /| |/ |/ / / / / __/ / / __/
  6. * \____/\____/_/ |_/_/ /_/\__. / |__/|__/_/ /_/\___/_/ \___/
  7. * /____/
  8. *
  9. * (C) Copyright 2015 GoAnywhere (http://goanywhere.io).
  10. * ----------------------------------------------------------------------
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. * ----------------------------------------------------------------------*/
  23. package rex
  24. import (
  25. "fmt"
  26. "net/http"
  27. "path/filepath"
  28. "reflect"
  29. "runtime"
  30. "time"
  31. "github.com/goanywhere/rex/internal"
  32. "github.com/gorilla/mux"
  33. )
  34. type Router struct {
  35. mod *internal.Module
  36. mux *mux.Router
  37. ready bool
  38. subrouters []*Router
  39. }
  40. func New() *Router {
  41. return &Router{
  42. mod: new(internal.Module),
  43. mux: mux.NewRouter(),
  44. }
  45. }
  46. // build constructs all router/subrouters along with their middleware modules chain.
  47. func (self *Router) build() {
  48. if !self.ready {
  49. self.ready = true
  50. // * activate router's middleware modules.
  51. self.mod.Use(self.mux)
  52. // * activate subrouters's middleware modules.
  53. for index := 0; index < len(self.subrouters); index++ {
  54. sr := self.subrouters[index]
  55. sr.mod.Use(sr.mux)
  56. }
  57. }
  58. }
  59. // register adds the http.Handler/http.HandleFunc into Gorilla mux.
  60. func (self *Router) register(method string, pattern string, handler interface{}) {
  61. // finds the full function name (with package) as its mappings.
  62. var name = runtime.FuncForPC(reflect.ValueOf(handler).Pointer()).Name()
  63. switch H := handler.(type) {
  64. case http.Handler:
  65. self.mux.Handle(pattern, H).Methods(method).Name(name)
  66. case func(http.ResponseWriter, *http.Request):
  67. self.mux.HandleFunc(pattern, H).Methods(method).Name(name)
  68. default:
  69. Fatalf("Unsupported handler (%s) passed in.", name)
  70. }
  71. }
  72. // Get is a shortcut for mux.HandleFunc(pattern, handler).Methods("GET"),
  73. // it also fetch the full function name of the handler (with package) to name the route.
  74. func (self *Router) Get(pattern string, handler interface{}) {
  75. self.register("GET", pattern, handler)
  76. }
  77. // Head is a shortcut for mux.HandleFunc(pattern, handler).Methods("HEAD")
  78. // it also fetch the full function name of the handler (with package) to name the route.
  79. func (self *Router) Head(pattern string, handler interface{}) {
  80. self.register("HEAD", pattern, handler)
  81. }
  82. // Options is a shortcut for mux.HandleFunc(pattern, handler).Methods("OPTIONS")
  83. // it also fetch the full function name of the handler (with package) to name the route.
  84. // NOTE method OPTIONS is **NOT** cachable, beware of what you are going to do.
  85. func (self *Router) Options(pattern string, handler interface{}) {
  86. self.register("OPTIONS", pattern, handler)
  87. }
  88. // Post is a shortcut for mux.HandleFunc(pattern, handler).Methods("POST")
  89. // it also fetch the full function name of the handler (with package) to name the route.
  90. func (self *Router) Post(pattern string, handler interface{}) {
  91. self.register("POST", pattern, handler)
  92. }
  93. // Put is a shortcut for mux.HandleFunc(pattern, handler).Methods("PUT")
  94. // it also fetch the full function name of the handler (with package) to name the route.
  95. func (self *Router) Put(pattern string, handler interface{}) {
  96. self.register("PUT", pattern, handler)
  97. }
  98. // Delete is a shortcut for mux.HandleFunc(pattern, handler).Methods("DELETE")
  99. // it also fetch the full function name of the handler (with package) to name the route.
  100. func (self *Router) Delete(pattern string, handler interface{}) {
  101. self.register("Delete", pattern, handler)
  102. }
  103. // Group creates a new application group under the given path prefix.
  104. func (self *Router) Group(prefix string) *Router {
  105. var mod = new(internal.Module)
  106. self.mux.PathPrefix(prefix).Handler(mod)
  107. var mux = self.mux.PathPrefix(prefix).Subrouter()
  108. router := &Router{mod: mod, mux: mux}
  109. self.subrouters = append(self.subrouters, router)
  110. return router
  111. }
  112. // FileRouter registers a handler to serve HTTP requests
  113. // with the contents of the file system rooted at root.
  114. func (self *Router) FileServer(prefix, dir string) {
  115. if abs, err := filepath.Abs(dir); err == nil {
  116. fs := http.StripPrefix(prefix, http.FileServer(http.Dir(abs)))
  117. self.mux.PathPrefix(prefix).Handler(fs)
  118. } else {
  119. Fatalf("Failed to setup file server: %v", err)
  120. }
  121. }
  122. // Name returns route name for the given request, if any.
  123. func (self *Router) Name(r *http.Request) (name string) {
  124. var match mux.RouteMatch
  125. if self.mux.Match(r, &match) {
  126. name = match.Route.GetName()
  127. }
  128. return name
  129. }
  130. func (self *Router) Use(module interface{}) {
  131. self.mod.Use(module)
  132. }
  133. // ServeHTTP dispatches the request to the handler whose
  134. // pattern most closely matches the request URL.
  135. func (self *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  136. self.build()
  137. self.mod.ServeHTTP(w, r)
  138. }
  139. // Run starts the application server to serve incoming requests at the given address.
  140. func (self *Router) Run() {
  141. runtime.GOMAXPROCS(options.maxprocs)
  142. go func() {
  143. time.Sleep(500 * time.Millisecond)
  144. Infof("Application server is listening at %d", options.port)
  145. }()
  146. if err := http.ListenAndServe(fmt.Sprintf(":%d", options.port), self); err != nil {
  147. Fatalf("Failed to start the server: %v", err)
  148. }
  149. }