context.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package wisp
  2. import (
  3. "context"
  4. "encoding/json"
  5. "encoding/xml"
  6. "errors"
  7. "io"
  8. "net/http"
  9. "net/url"
  10. "strconv"
  11. "strings"
  12. "github.com/julienschmidt/httprouter"
  13. )
  14. type Context struct {
  15. response http.ResponseWriter
  16. request *http.Request
  17. params httprouter.Params
  18. ctx context.Context
  19. }
  20. // Basic getters
  21. func (c *Context) Response() http.ResponseWriter {
  22. return c.response
  23. }
  24. func (c *Context) Request() *http.Request {
  25. return c.request
  26. }
  27. func (c *Context) Params() httprouter.Params {
  28. return c.params
  29. }
  30. func (c *Context) Context() context.Context {
  31. return c.ctx
  32. }
  33. // URL Param retrieval (from path)
  34. func (c *Context) Param(name string) string {
  35. return c.params.ByName(name)
  36. }
  37. // Query param retrieval
  38. func (c *Context) Query(name string) string {
  39. return c.request.URL.Query().Get(name)
  40. }
  41. func (c *Context) QueryDefault(name, defaultValue string) string {
  42. if v := c.Query(name); v != "" {
  43. return v
  44. }
  45. return defaultValue
  46. }
  47. // Form param retrieval (POST, PUT with form data)
  48. func (c *Context) FormValue(name string) string {
  49. return c.request.FormValue(name)
  50. }
  51. func (c *Context) FormValueDefault(name, defaultValue string) string {
  52. if v := c.FormValue(name); v != "" {
  53. return v
  54. }
  55. return defaultValue
  56. }
  57. // Body binding helpers
  58. func (c *Context) BindJSON(dest interface{}) error {
  59. defer c.request.Body.Close()
  60. dec := json.NewDecoder(c.request.Body)
  61. dec.DisallowUnknownFields()
  62. return dec.Decode(dest)
  63. }
  64. func (c *Context) BindXML(dest interface{}) error {
  65. defer c.request.Body.Close()
  66. dec := xml.NewDecoder(c.request.Body)
  67. return dec.Decode(dest)
  68. }
  69. func (c *Context) BindForm() (url.Values, error) {
  70. defer c.request.Body.Close()
  71. contentType := c.request.Header.Get("Content-Type")
  72. if !strings.Contains(contentType, "application/x-www-form-urlencoded") {
  73. return nil, errors.New("content-type is not application/x-www-form-urlencoded")
  74. }
  75. return url.ParseQuery(c.request.PostForm.Encode())
  76. }
  77. func (c *Context) BindMultipartForm(maxMemory int64) error {
  78. return c.request.ParseMultipartForm(maxMemory)
  79. }
  80. // Cookie helpers
  81. func (c *Context) Cookie(name string) (*http.Cookie, error) {
  82. return c.request.Cookie(name)
  83. }
  84. func (c *Context) SetCookie(cookie *http.Cookie) {
  85. http.SetCookie(c.response, cookie)
  86. }
  87. // Response helpers
  88. func (c *Context) Write(data []byte) (int, error) {
  89. return c.response.Write(data)
  90. }
  91. func (c *Context) String(status int, s string) error {
  92. _, err := io.WriteString(c.response, s)
  93. return err
  94. }
  95. func (c *Context) JSON(status int, data any) error {
  96. c.response.Header().Set("Content-Type", "application/json")
  97. c.response.WriteHeader(status)
  98. return json.NewEncoder(c.response).Encode(data)
  99. }
  100. func (c *Context) XML(status int, data any) error {
  101. c.response.Header().Set("Content-Type", "application/xml")
  102. c.response.WriteHeader(status)
  103. return xml.NewEncoder(c.response).Encode(data)
  104. }
  105. func (c *Context) Redirect(status int, urlStr string) {
  106. http.Redirect(c.response, c.request, urlStr, status)
  107. }
  108. func (c *Context) Status(code int) {
  109. c.response.WriteHeader(code)
  110. }
  111. // Helpers for common status responses
  112. func (c *Context) NoContent() {
  113. c.Status(http.StatusNoContent)
  114. }
  115. func (c *Context) NotFound() {
  116. c.Status(http.StatusNotFound)
  117. }
  118. func (c *Context) BadRequest(e error) error {
  119. c.response.WriteHeader(http.StatusBadRequest)
  120. _, err := c.response.Write([]byte(e.Error()))
  121. return err
  122. }
  123. func (c *Context) InternalServerError(e error) error {
  124. c.response.WriteHeader(http.StatusInternalServerError)
  125. _, err := c.response.Write([]byte(e.Error()))
  126. return err
  127. }
  128. // Context cancellation / deadline
  129. func (c *Context) Done() <-chan struct{} {
  130. return c.ctx.Done()
  131. }
  132. func (c *Context) Err() error {
  133. return c.ctx.Err()
  134. }
  135. // Request parsing helpers for common data types
  136. func (c *Context) ParamInt(name string) (int, error) {
  137. v := c.Param(name)
  138. return strconv.Atoi(v)
  139. }
  140. func (c *Context) ParamIntDefault(name string, defaultValue int) int {
  141. v := c.Param(name)
  142. if v == "" {
  143. return defaultValue
  144. }
  145. i, err := strconv.Atoi(v)
  146. if err != nil {
  147. return defaultValue
  148. }
  149. return i
  150. }
  151. func (c *Context) QueryInt(name string) (int, error) {
  152. v := c.Query(name)
  153. return strconv.Atoi(v)
  154. }
  155. func (c *Context) QueryIntDefault(name string, defaultValue int) int {
  156. v := c.Query(name)
  157. if v == "" {
  158. return defaultValue
  159. }
  160. i, err := strconv.Atoi(v)
  161. if err != nil {
  162. return defaultValue
  163. }
  164. return i
  165. }
  166. func (c *Context) FormInt(name string) (int, error) {
  167. v := c.FormValue(name)
  168. return strconv.Atoi(v)
  169. }
  170. func (c *Context) FormIntDefault(name string, defaultValue int) int {
  171. v := c.FormValue(name)
  172. if v == "" {
  173. return defaultValue
  174. }
  175. i, err := strconv.Atoi(v)
  176. if err != nil {
  177. return defaultValue
  178. }
  179. return i
  180. }
  181. // Context management helpers
  182. func (c *Context) SetValue(key, val any) {
  183. c.ctx = context.WithValue(c.ctx, key, val)
  184. }
  185. func (c *Context) Value(key any) any {
  186. return c.ctx.Value(key)
  187. }