context.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. package http
  2. import (
  3. "context"
  4. "encoding/json"
  5. "net"
  6. "net/http"
  7. "os"
  8. "path"
  9. "strings"
  10. )
  11. var (
  12. defaultBinder = &DefaultBinder{}
  13. )
  14. var (
  15. realIPHeaders = []string{
  16. "Cf-Connecting-Ip",
  17. "True-Client-IP",
  18. "X-Forwarded-For",
  19. "X-Real-Ip",
  20. }
  21. )
  22. type Context struct {
  23. ctx context.Context
  24. req *http.Request
  25. res http.ResponseWriter
  26. params map[string]string
  27. user *Userinfo
  28. statusCode int
  29. }
  30. func (ctx *Context) reset(req *http.Request, res http.ResponseWriter, ps map[string]string) {
  31. ctx.statusCode = http.StatusOK
  32. ctx.user = nil
  33. ctx.req, ctx.res, ctx.params = req, res, ps
  34. }
  35. func (ctx *Context) User() *Userinfo {
  36. return ctx.user
  37. }
  38. func (ctx *Context) SetUser(ui *Userinfo) {
  39. ctx.user = ui
  40. }
  41. func (ctx *Context) RealIp() string {
  42. var (
  43. s string
  44. pos int
  45. ipaddr string
  46. )
  47. for _, h := range realIPHeaders {
  48. if ipaddr = ctx.Request().Header.Get(h); ipaddr != "" {
  49. goto __end
  50. }
  51. }
  52. ipaddr, _, _ = net.SplitHostPort(ctx.Request().RemoteAddr)
  53. __end:
  54. for {
  55. if pos = strings.IndexByte(ipaddr, ','); pos > -1 {
  56. s = strings.TrimSpace(ipaddr[:pos])
  57. if netAddr := net.ParseIP(s); netAddr != nil && !netAddr.IsPrivate() {
  58. return s
  59. }
  60. ipaddr = ipaddr[pos+1:]
  61. } else {
  62. break
  63. }
  64. }
  65. return strings.TrimSpace(ipaddr)
  66. }
  67. func (ctx *Context) Request() *http.Request {
  68. return ctx.req
  69. }
  70. func (ctx *Context) Response() http.ResponseWriter {
  71. return ctx.res
  72. }
  73. func (ctx *Context) Context() context.Context {
  74. if ctx.Request().Context() != nil {
  75. return ctx.Request().Context()
  76. }
  77. return ctx.ctx
  78. }
  79. func (ctx *Context) Bind(v any) (err error) {
  80. return defaultBinder.Bind(v, ctx.Request())
  81. }
  82. func (ctx *Context) Query(k string) string {
  83. qs := ctx.Request().URL.Query()
  84. if qs == nil {
  85. return ""
  86. }
  87. return qs.Get(k)
  88. }
  89. func (ctx *Context) Form(k string) string {
  90. return ctx.Request().FormValue(k)
  91. }
  92. func (ctx *Context) Param(k string) string {
  93. var (
  94. ok bool
  95. s string
  96. )
  97. if s, ok = ctx.params[k]; ok {
  98. return s
  99. }
  100. s = ctx.Query(k)
  101. if s == "" {
  102. s = ctx.Form(k)
  103. }
  104. return s
  105. }
  106. func (ctx *Context) json(res responsePayload) (err error) {
  107. ctx.Response().Header().Set("Content-Type", "application/json")
  108. encoder := json.NewEncoder(ctx.Response())
  109. if strings.HasPrefix(ctx.Request().Header.Get("User-Agent"), "curl") {
  110. encoder.SetIndent("", "\t")
  111. }
  112. return encoder.Encode(res)
  113. }
  114. func (ctx *Context) Success(v any) (err error) {
  115. return ctx.json(responsePayload{Data: v})
  116. }
  117. func (ctx *Context) Status(code int) {
  118. ctx.statusCode = code
  119. }
  120. func (ctx *Context) Error(code int, reason string) (err error) {
  121. return ctx.json(responsePayload{Code: code, Reason: reason})
  122. }
  123. func (ctx *Context) Redirect(url string, code int) {
  124. if code != http.StatusFound && code != http.StatusMovedPermanently {
  125. code = http.StatusFound
  126. }
  127. http.Redirect(ctx.Response(), ctx.Request(), url, code)
  128. }
  129. func (ctx *Context) SetCookie(cookie *http.Cookie) {
  130. http.SetCookie(ctx.Response(), cookie)
  131. }
  132. func (ctx *Context) GetCookie(name string) (*http.Cookie, error) {
  133. return ctx.Request().Cookie(name)
  134. }
  135. func (ctx *Context) DeleteCookie(name string) {
  136. cookie, err := ctx.GetCookie(name)
  137. if err == nil {
  138. cookie.MaxAge = -1
  139. ctx.SetCookie(cookie)
  140. }
  141. }
  142. func (ctx *Context) SetCookieValue(name, value, domain string) {
  143. if domain == "" {
  144. domain = ctx.Request().URL.Hostname()
  145. }
  146. if name == "" || value == "" {
  147. return
  148. }
  149. ctx.SetCookie(&http.Cookie{
  150. Name: name,
  151. Value: value,
  152. Path: "/",
  153. Domain: domain,
  154. })
  155. }
  156. func (ctx *Context) GetCookieValue(name string) string {
  157. if name == "" {
  158. return ""
  159. }
  160. cookie, err := ctx.GetCookie(name)
  161. if err == nil {
  162. return cookie.Value
  163. }
  164. return ""
  165. }
  166. func (ctx *Context) SendFile(filename string) (err error) {
  167. var (
  168. fi os.FileInfo
  169. fp *os.File
  170. )
  171. if fi, err = os.Stat(filename); err == nil {
  172. if fp, err = os.Open(filename); err == nil {
  173. http.ServeContent(ctx.Response(), ctx.Request(), path.Base(filename), fi.ModTime(), fp)
  174. err = fp.Close()
  175. }
  176. }
  177. return
  178. }