Capstan is a Golang web framework that shares some similarities with others in its segment.
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.

311 lines
8.4KB

  1. package capstan
  2. import (
  3. "net/http"
  4. "git.destrealm.org/go/capstan/render"
  5. "git.destrealm.org/go/capstan/session"
  6. "github.com/gorilla/websocket"
  7. )
  8. type Controller interface {
  9. middleware() Middleware
  10. name() string
  11. mandatoryNoSlash() bool
  12. mandatorySlash() bool
  13. optionalSlash() bool
  14. slashIsDefault() bool
  15. noInterpolation() bool
  16. path() string
  17. prefix() string
  18. index() string
  19. webSocketPath() string
  20. upgrader() *websocket.Upgrader
  21. renderer() render.Renderer
  22. endpoints() map[string]RouteFlag
  23. options() BaseController
  24. }
  25. type ConnectHandler interface {
  26. Connect(Context) error
  27. }
  28. type DeleteHandler interface {
  29. Delete(Context) error
  30. }
  31. type GetHandler interface {
  32. Get(Context) error
  33. }
  34. type HeadHandler interface {
  35. Head(Context) error
  36. }
  37. type OptionsHandler interface {
  38. Options(Context) error
  39. }
  40. type PostHandler interface {
  41. Post(Context) error
  42. }
  43. type PutHandler interface {
  44. Put(Context) error
  45. }
  46. type PatchHandler interface {
  47. Patch(Context) error
  48. }
  49. type TraceHandler interface {
  50. Trace(Context) error
  51. }
  52. // Binder controllers are those that wish to implement or handle binding
  53. // themselves. Consequently, a *Router is passed as the Bind() function's sole
  54. // argument such that the controller may use it to interface directly with the
  55. // router instance or may call Router.Mux() to use the muxer directly. If an
  56. // implementation uses the latter, the underlying configured go-chi instance is
  57. // exposed for external management.
  58. type Binder interface {
  59. Bind(*Router)
  60. }
  61. type IndexHandler interface {
  62. Index(Context) error
  63. }
  64. // MiddlewareHandler, when implemented, allows controllers to return middleware
  65. // that utilizes attached fields and methods as internal context. This is useful
  66. // if your middleware requires access to a database or other dependencies
  67. // (including injected dependencies).
  68. type MiddlewareHandler interface {
  69. Middleware() []func(http.Handler) http.Handler
  70. }
  71. type WebSocketHandler interface {
  72. WebSocket(Context) error
  73. }
  74. // MapperHandler returns a map of a route (map key) and the endpoint + method
  75. // (RouteMap) it should be bound to. MapperHandlers are controllers that define
  76. // their own route-to-endpoint handling routines.
  77. type MapperHandler interface {
  78. Mapper() map[string]RouteMap
  79. }
  80. type BaseController struct {
  81. route *Route
  82. // Middleware defined for this controller.
  83. Middleware Middleware
  84. // Name to assign to this controller. Leave empty to automatically deduce
  85. // the name from the implementing struct.
  86. Name string
  87. // Path against which this controller will bind its routes. This may have
  88. // special meaning for index and other methods (e.g. custom).
  89. Path string
  90. // Paths to additionally assign to this controller and its methods. Not
  91. // currently used.
  92. Paths map[string][]string
  93. // Prefix to prepend to the controller's symbolic name. This may be useful
  94. // for namespacing controller references for reversing the URL in templates.
  95. Prefix string
  96. // OptionalSlash indicates the trailing slash is optional. It is usually
  97. // advised to set this via the Path component.
  98. OptionalSlash bool
  99. // Endpoints is a list of custom endpoints attached to this controller.
  100. Endpoints map[string]RouteFlag
  101. // MandatoryNoSlash indicates the trailing slash must not be present. It is
  102. // usually advised to set this via the Path component.
  103. MandatoryNoSlash bool
  104. // MandatorySlash indicates the trailing slash is required. It is usually
  105. // advised to set this via the Path component.
  106. MandatorySlash bool
  107. // SlashIsDefault indicates the presence or absence of the trailing slash is
  108. // the default state. This flag only holds meaning when OptionalSlash is set
  109. // to true. It is usually advised to set this via the Path component by
  110. // including a slash followed by a question mark ("/?") to indicate that the
  111. // slash is optional and the default redirection target.
  112. SlashIsDefault bool
  113. // NoInterpolation disables path interpolation and mandates the flags
  114. // (above) to configure the route slash states. This is useful for routes
  115. // where the special characters used to communicate slash behavior are
  116. // required as part of the route and should be accepted as literals.
  117. NoInterpolation bool
  118. // WebSocketPath, if set, will attach the WebSocket() method to the
  119. // specified path underneath the path defined for this controller.
  120. // Recommended.
  121. //
  122. // Leave this blank if your controller is intended strictly for websocket
  123. // handling.
  124. WebSocketPath string
  125. // Upgrader is the configured websocket upgrader via gorilla/websocket. This
  126. // provides both the configuration details for websocket connections in
  127. // addition to bound methods for upgrading the connection. If this is nil
  128. // and the controller implements the WebSocketHandler interface, the default
  129. // upgrader will be used instead.
  130. Upgrader *websocket.Upgrader
  131. // Renderer reference for this controller. This may be unique to each
  132. // controller or may be set globally via a helper.
  133. Renderer render.Renderer
  134. // BeforeResponse bindings specifically used for this controller.
  135. BeforeResponse []func(Context, *Route) error
  136. // AfterResponse bindings specifically used for this controller.
  137. AfterResponse []func(Context, error) error
  138. // Index path override. This may contain a path component, a single slash
  139. // indicating the path terminates with this index, a slash followed by a
  140. // question mark which indicates the slash is optional, or a slash followed
  141. // by an exclamation point indicating the route must not terminate with a
  142. // slash.
  143. Index string
  144. // Method path overrides.
  145. // Get overrides the default path for GET requests, appending the path
  146. // component specified here.
  147. Get string
  148. // Post overrides the default path for POST requests, appending the path
  149. // component specified here.
  150. Post string
  151. // Put overrides the default path for PUT requests, appending the path
  152. // component specified here.
  153. Put string
  154. // Patch overrides the default path for PATCH requests, appending the path
  155. // component specified here.
  156. Patch string
  157. // Delete overrides the default path for DELETE requests, appending the path
  158. // component specified here.
  159. Delete string
  160. // Head overrides the default path for HEAD requests, appending the path
  161. // component specified here.
  162. Head string
  163. }
  164. func (bc BaseController) middleware() Middleware {
  165. return bc.Middleware
  166. }
  167. func (bc BaseController) name() string {
  168. return bc.Name
  169. }
  170. func (bc BaseController) mandatoryNoSlash() bool {
  171. return bc.MandatoryNoSlash
  172. }
  173. func (bc BaseController) mandatorySlash() bool {
  174. return bc.MandatorySlash
  175. }
  176. func (bc BaseController) optionalSlash() bool {
  177. return bc.OptionalSlash
  178. }
  179. func (bc BaseController) slashIsDefault() bool {
  180. return bc.SlashIsDefault
  181. }
  182. func (bc BaseController) noInterpolation() bool {
  183. return bc.NoInterpolation
  184. }
  185. func (bc BaseController) path() string {
  186. return bc.Path
  187. }
  188. func (bc BaseController) prefix() string {
  189. return bc.Prefix
  190. }
  191. func (bc BaseController) renderer() render.Renderer {
  192. return bc.Renderer
  193. }
  194. func (bc BaseController) beforeResponseHandlers() []func(Context, *Route) error {
  195. return bc.BeforeResponse
  196. }
  197. func (bc BaseController) afterResponseHandlers() []func(Context, error) error {
  198. return bc.AfterResponse
  199. }
  200. func (bc BaseController) webSocketPath() string {
  201. return bc.WebSocketPath
  202. }
  203. func (bc BaseController) upgrader() *websocket.Upgrader {
  204. return bc.Upgrader
  205. }
  206. func (bc BaseController) index() string {
  207. return bc.Index
  208. }
  209. func (bc BaseController) endpoints() map[string]RouteFlag {
  210. return bc.Endpoints
  211. }
  212. func (bc BaseController) options() BaseController {
  213. return bc
  214. }
  215. type Context interface {
  216. Float(string) (float64, error)
  217. FloatDefault(string, float64) float64
  218. Int(string) (int64, error)
  219. IntDefault(string, int64) int64
  220. Param(string) string
  221. ParamDefault(string, string) string
  222. Params(string) []string
  223. String(string) (string, error)
  224. StringDefault(string, string) string
  225. In(interface{}) error
  226. JSON(interface{}) error
  227. ParamTypes() map[string]string
  228. Render(string, interface{}) error
  229. Renderer() (render.ContextRenderer, error)
  230. SetRenderer(render.Renderer)
  231. Headers() http.Header
  232. Request() *http.Request
  233. Response() http.ResponseWriter
  234. RequestContext(key string, value interface{})
  235. Route() *Route
  236. SetCookie(*http.Cookie)
  237. WebSocket() *websocket.Conn
  238. SetWebSocket(*websocket.Conn)
  239. Session() session.Session
  240. URLFor(string) *URLBuilder
  241. Write([]byte) (int, error)
  242. WriteHeader(int)
  243. WriteJSON(interface{}) error
  244. ContentType(ContentType)
  245. HasError() error
  246. Panic(string)
  247. Error() string
  248. SetError(error)
  249. Code() int
  250. SetCode(int)
  251. }