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.

164 lines
5.5KB

  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. // ServerConfig is the top-level pseudo-alias for Capstan's server
  27. // configuration. This is a convenience type to reduce imports.
  28. type ServerConfig = config.ServerConfig
  29. // SessionConfig is a top-level pseudo-alas for Capstan's session configuration.
  30. type SessionConfig = config.SessionConfig
  31. // MapValues is a top-level pseudo-alias for Capstan's wrapper type
  32. // render.MapValues wrapping the pongo2 Context.
  33. type MapValues = render.MapValues
  34. // ContentType determines the content type for a request. This is used primarily
  35. // by the Capstan Context entity to determine how the response should be
  36. // generated.
  37. type ContentType string
  38. const (
  39. TextPlain ContentType = "text/plain"
  40. TextHTML ContentType = "text/html"
  41. ApplicationJSON ContentType = "application/json; charset=utf8"
  42. )
  43. // Endpoint defines functions that serve as Capstan endpoints. These are usually
  44. // members of a struct and there's currently no provision for creating "bare"
  45. // endpoints.
  46. type Endpoint func(Context) error
  47. // Middleware is a pseudo-alias for go-chi's awkwardly-named "Middlewares."
  48. type Middleware chi.Middlewares
  49. // MiddlewareFunc defines the type used by middleware declarations. This is
  50. // provided mostly for convenience as middleware will generally define the
  51. // returned handler function directly rather than assigning it to a type.
  52. type MiddlewareFunc func(http.Handler) http.Handler
  53. // RouteMap is currently unused. It will be includes as part of the Mapper()
  54. // handler for controllers that define their own route map.
  55. type RouteMap struct {
  56. Method string
  57. Endpoint Endpoint
  58. }
  59. type RouteFlag struct {
  60. Method string
  61. Endpoint string
  62. }
  63. type RouterOptions struct {
  64. ContentType string
  65. }
  66. // Route properties defining things like trailing slash behavior and the routes
  67. // base path components.
  68. type routeProps struct {
  69. // Fully interpreted route for use with go-chi.
  70. route string
  71. // Route components prior to the introduction of parameters. Non-parameter
  72. // components following parameterized ones will not be included.
  73. baseRoute string
  74. // Map of route parameters to their declared types.
  75. params map[string]string
  76. // Route is terminated with an optional slash.
  77. optionalSlash bool
  78. // Route must not be terminated with any slash.
  79. mandatoryNoSlash bool
  80. // Route must be terminated with a slash.
  81. mandatorySlash bool
  82. // Slash redirection defaults to redirecting toward routes terminated with a
  83. // slash.
  84. slashIsDefault bool
  85. }
  86. // Merges the contents of `props` into the current property, using `props` as
  87. // the base. This is usually used by Index() routes where `props` is the master
  88. // property.
  89. //
  90. // p.baseRoute is ignored here largely because we're not interested in the
  91. // subroute's base as it's getting merged into the parent.
  92. func (p *routeProps) mergeBase(props *routeProps) {
  93. if p.route == "" {
  94. p.route = props.baseRoute
  95. return
  96. }
  97. base := props.baseRoute
  98. if base[len(base)-1:] != "/" {
  99. base += "/"
  100. }
  101. if p.route == "/" {
  102. p.route = base
  103. return
  104. }
  105. if p.route[0] == '/' {
  106. p.route = base + p.route[1:]
  107. } else {
  108. p.route += base
  109. }
  110. return
  111. }
  112. // HTTP errors and their associated descriptions. Used by the built-in HTTP
  113. // error response handler template.
  114. var httpErrorDesc = map[int]string{
  115. 400: "The server could not process your request. It may be malformed or incomplete.",
  116. 401: "You do not have access to this resource. Authentication may be required.",
  117. 403: "You do not have permission to access this resource.",
  118. 404: "The requested resource does not exist on this server.",
  119. 405: "The requested method is inappropriate for this endpoint.",
  120. 406: "The requested resource cannot be provided for the current Accept headers.",
  121. 408: "Your request was not completed in a timely manner, and the server has closed the connection.",
  122. 409: "Your request could not be fulfilled because it conflicts with other resources on the server.",
  123. 410: "The requested resource has been permanently removed.",
  124. 411: "The request body did not match the expected length.",
  125. 413: "Your request body exceeded the limits imposed by this server and has been ignored.",
  126. 414: "The request URI exceeded the limits for this server.",
  127. 500: "An error has occurred while processing your request.",
  128. 501: "The request method has not been implemented for this endpoint.",
  129. 503: "We cannot process your request at this time. The server may be down for maintenance or overloaded. Please try again shortly.",
  130. 505: "You have requested an HTTP version that is not supported by this server.",
  131. }