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.

178 lines
6.1KB

  1. package capstan
  2. import (
  3. "net/http"
  4. "git.destrealm.org/go/capstan/config"
  5. "git.destrealm.org/go/capstan/render"
  6. "git.destrealm.org/go/capstan/utils"
  7. "github.com/go-chi/chi"
  8. )
  9. // NewScanner pseudo-alias for utils.NewScanner. Used by CLI to abstract away OS
  10. // differences when scanning end-of-line ("\n" vs "\r\n").
  11. var NewScanner = utils.NewScanner
  12. // NoColor flag. If set to anything but the empty string, this will enable
  13. // NO_COLOR processing.
  14. var NoColor string
  15. // ShutdownHook types are registered to be called whenever the application is
  16. // terminated normally.
  17. type ShutdownHook func() error
  18. // Pseudo-alias types.
  19. // Config is the top-level pseudo-alias for Capstan's configuration struct.
  20. // Provided for import convenience.
  21. type Config = config.Config
  22. // ApplicationConfig is the top-level pseudo-alias for Capstan's application
  23. // configuration. Warning: This entity may be deprecated in a future version
  24. // since CLI application support has been dropped (that's up to the caller).
  25. type ApplicationConfig = config.ApplicationConfig
  26. // EnvironmentConfig is the top-level pseudo-alias for Capstan's environment
  27. // configuration.
  28. //
  29. // The environment configurations allows one to configure a Capstan container
  30. // when running in multiapp mode, allowing individualized versions, names, or
  31. // descriptions per application while presenting different information for the
  32. // containing environment.
  33. type EnvironmentConfig = config.EnvironmentConfig
  34. // MultiAppConfig is the top-level pseudo-alias for Capstan's multi-application
  35. // support. This controls multiapp behavior when muli-application mode has been
  36. // enabled by calling Application.AttachApplication.
  37. type MultiAppConfig = config.MultiAppConfig
  38. // ServerConfig is the top-level pseudo-alias for Capstan's server
  39. // configuration. This is a convenience type to reduce imports.
  40. type ServerConfig = config.ServerConfig
  41. // SessionConfig is a top-level pseudo-alas for Capstan's session configuration.
  42. type SessionConfig = config.SessionConfig
  43. // MapValues is a top-level pseudo-alias for Capstan's wrapper type
  44. // render.MapValues wrapping the pongo2 Context.
  45. type MapValues = render.MapValues
  46. // ContentType determines the content type for a request. This is used primarily
  47. // by the Capstan Context entity to determine how the response should be
  48. // generated.
  49. type ContentType string
  50. const (
  51. TextPlain ContentType = "text/plain"
  52. TextHTML ContentType = "text/html"
  53. ApplicationJSON ContentType = "application/json; charset=utf8"
  54. )
  55. // Endpoint defines functions that serve as Capstan endpoints. These are usually
  56. // members of a struct and there's currently no provision for creating "bare"
  57. // endpoints.
  58. type Endpoint func(Context) error
  59. // Middleware is a pseudo-alias for go-chi's awkwardly-named "Middlewares."
  60. type Middleware chi.Middlewares
  61. // MiddlewareFunc defines the type used by middleware declarations. This is
  62. // provided mostly for convenience as middleware will generally define the
  63. // returned handler function directly rather than assigning it to a type.
  64. type MiddlewareFunc func(http.Handler) http.Handler
  65. // RouteMap is currently unused. It will be includes as part of the Mapper()
  66. // handler for controllers that define their own route map.
  67. type RouteMap struct {
  68. Method string
  69. Endpoint Endpoint
  70. }
  71. type RouteFlag struct {
  72. Method string
  73. Endpoint string
  74. }
  75. type RouterOptions struct {
  76. ContentType string
  77. }
  78. // Route properties defining things like trailing slash behavior and the routes
  79. // base path components.
  80. type routeProps struct {
  81. // Fully interpreted route for use with go-chi.
  82. route string
  83. // Route components prior to the introduction of parameters. Non-parameter
  84. // components following parameterized ones will not be included.
  85. baseRoute string
  86. // Map of route parameters to their declared types.
  87. params map[string]string
  88. // Route is terminated with an optional slash.
  89. optionalSlash bool
  90. // Route must not be terminated with any slash.
  91. mandatoryNoSlash bool
  92. // Route must be terminated with a slash.
  93. mandatorySlash bool
  94. // Slash redirection defaults to redirecting toward routes terminated with a
  95. // slash.
  96. slashIsDefault bool
  97. }
  98. // Merges the contents of `props` into the current property, using `props` as
  99. // the base. This is usually used by Index() routes where `props` is the master
  100. // property.
  101. //
  102. // p.baseRoute is ignored here largely because we're not interested in the
  103. // subroute's base as it's getting merged into the parent.
  104. func (p *routeProps) mergeBase(props *routeProps) {
  105. if p.route == "" {
  106. p.route = props.baseRoute
  107. return
  108. }
  109. base := props.baseRoute
  110. if base[len(base)-1:] != "/" {
  111. base += "/"
  112. }
  113. if p.route == "/" {
  114. p.route = base
  115. return
  116. }
  117. if p.route[0] == '/' {
  118. p.route = base + p.route[1:]
  119. } else {
  120. p.route += base
  121. }
  122. return
  123. }
  124. // HTTP errors and their associated descriptions. Used by the built-in HTTP
  125. // error response handler template.
  126. var httpErrorDesc = map[int]string{
  127. 400: "The server could not process your request. It may be malformed or incomplete.",
  128. 401: "You do not have access to this resource. Authentication may be required.",
  129. 403: "You do not have permission to access this resource.",
  130. 404: "The requested resource does not exist on this server.",
  131. 405: "The requested method is inappropriate for this endpoint.",
  132. 406: "The requested resource cannot be provided for the current Accept headers.",
  133. 408: "Your request was not completed in a timely manner, and the server has closed the connection.",
  134. 409: "Your request could not be fulfilled because it conflicts with other resources on the server.",
  135. 410: "The requested resource has been permanently removed.",
  136. 411: "The request body did not match the expected length.",
  137. 413: "Your request body exceeded the limits imposed by this server and has been ignored.",
  138. 414: "The request URI exceeded the limits for this server.",
  139. 500: "An error has occurred while processing your request.",
  140. 501: "The request method has not been implemented for this endpoint.",
  141. 503: "We cannot process your request at this time. The server may be down for maintenance or overloaded. Please try again shortly.",
  142. 505: "You have requested an HTTP version that is not supported by this server.",
  143. }