github.com/ngocphuongnb/tetua@v0.0.7-alpha/packages/fiberserver/context.go (about) 1 package fiberserver 2 3 import ( 4 "bufio" 5 "context" 6 "fmt" 7 "mime/multipart" 8 "runtime" 9 "strconv" 10 11 "github.com/gofiber/fiber/v2" 12 fiberUtils "github.com/gofiber/utils" 13 "github.com/ngocphuongnb/tetua/app/config" 14 "github.com/ngocphuongnb/tetua/app/entities" 15 "github.com/ngocphuongnb/tetua/app/logger" 16 "github.com/ngocphuongnb/tetua/app/server" 17 "github.com/ngocphuongnb/tetua/app/utils" 18 "github.com/valyala/fasthttp" 19 ) 20 21 type Context struct { 22 *fiber.Ctx 23 MetaData *entities.Meta 24 } 25 26 type Response struct { 27 *fasthttp.Response 28 } 29 30 func (c *Context) RequestID() string { 31 return fmt.Sprintf("%v", c.Locals("request_id")) 32 } 33 34 func (c *Context) Hostname() string { 35 return c.Ctx.Hostname() 36 } 37 38 func (c *Context) BaseUrl() string { 39 return c.Ctx.Protocol() + "://" + c.Ctx.Hostname() 40 } 41 42 func (c *Context) RouteName() string { 43 return c.Ctx.Route().Name 44 } 45 46 func (c *Context) Context() context.Context { 47 return context.WithValue(context.Background(), "request_id", c.RequestID()) 48 } 49 50 func (c *Context) File(name string) (*multipart.FileHeader, error) { 51 return c.Ctx.FormFile(name) 52 } 53 54 func (c *Context) Logger() logger.Logger { 55 return logger.Get().WithContext(logger.Context{"request_id": c.RequestID()}) 56 } 57 58 func (c *Context) Messages(ms ...*entities.Messages) *entities.Messages { 59 if len(ms) > 0 { 60 c.MetaData.Messages = ms[0] 61 return ms[0] 62 } 63 return c.MetaData.Messages 64 } 65 66 func (c *Context) Meta(metas ...*entities.Meta) *entities.Meta { 67 if len(metas) > 0 { 68 c.MetaData = metas[0] 69 c.MetaData.User = c.User() 70 71 if c.MetaData.Messages == nil { 72 c.MetaData.Messages = &entities.Messages{} 73 } 74 return c.MetaData 75 } 76 77 if c.MetaData == nil { 78 appName := config.Setting("app_name") 79 c.MetaData = &entities.Meta{ 80 Title: appName, 81 Description: appName, 82 User: c.User(), 83 Messages: &entities.Messages{}, 84 } 85 } 86 87 return c.MetaData 88 } 89 90 func (c *Context) Render(fn func(meta *entities.Meta, wr *bufio.Writer)) error { 91 if c.Meta().Canonical == "" { 92 c.Meta().Canonical = utils.Url(c.Path()) 93 } 94 95 if c.Meta().Type == "" { 96 c.Meta().Type = "website" 97 } 98 99 c.Response().Header("content-type", "text/html; charset=utf-8") 100 requestID := fiberUtils.ImmutableString(c.RequestID()) 101 c.Ctx.Response().SetBodyStreamWriter(func(w *bufio.Writer) { 102 defer func(requestID string) { 103 if r := recover(); r != nil { 104 err, ok := r.(error) 105 if !ok { 106 err = fmt.Errorf("%v", r) 107 } 108 stack := make([]byte, 4<<10) 109 length := runtime.Stack(stack, true) 110 msg := fmt.Sprintf("%v %s\n", err, stack[:length]) 111 logger.Get().WithContext(logger.Context{"request_id": requestID, "recovered": true}).Error(msg) 112 if _, err := w.WriteString("Something went wrong"); err != nil { 113 fmt.Println(err) 114 } 115 } 116 }(requestID) 117 fn(c.Meta(), w) 118 w.Flush() 119 }) 120 121 return nil 122 } 123 124 func (c *Context) User() *entities.User { 125 if user, ok := c.Locals("user").(*entities.User); ok { 126 return user 127 } 128 129 return nil 130 } 131 132 func (c *Context) Post(posts ...*entities.Post) *entities.Post { 133 if len(posts) > 0 { 134 c.Locals("post", posts[0]) 135 } 136 137 if post, ok := c.Locals("post").(*entities.Post); ok { 138 return post 139 } 140 141 return nil 142 } 143 144 func (c *Context) Json(v interface{}) error { 145 return c.Ctx.JSON(v) 146 } 147 148 func (c *Context) Cookies(key string, defaultValue ...string) string { 149 return c.Ctx.Cookies(key, defaultValue...) 150 } 151 152 func (c *Context) Cookie(v *server.Cookie) { 153 cookie := fiber.Cookie{ 154 Name: v.Name, 155 Value: v.Value, 156 Path: v.Path, 157 Domain: v.Domain, 158 Expires: v.Expires, 159 Secure: v.Secure, 160 HTTPOnly: v.HTTPOnly, 161 SameSite: v.SameSite, 162 } 163 c.Ctx.Cookie(&cookie) 164 } 165 166 func (c *Context) Status(v int) server.Context { 167 c.Ctx.Status(v) 168 return c 169 } 170 func (c *Context) Next() error { 171 return c.Ctx.Next() 172 } 173 174 func (c *Context) Locals(key string, value ...interface{}) (val interface{}) { 175 return c.Ctx.Locals(key, value...) 176 } 177 178 func (c *Context) Param(key string) string { 179 return c.Ctx.Params(key) 180 } 181 182 func (c *Context) ParamInt(key string, values ...int) int { 183 if p, err := strconv.Atoi(c.Ctx.Params(key)); err == nil { 184 return p 185 } 186 187 if len(values) > 0 { 188 return values[0] 189 } 190 191 return 0 192 } 193 194 func (c *Context) WithError(msg string, err error) { 195 c.Messages().AppendError(msg) 196 c.Logger().Error(msg, err) 197 } 198 199 func (c *Context) Query(key string, values ...string) string { 200 if value := c.Ctx.Query(key); value != "" { 201 return value 202 } 203 204 if len(values) > 0 { 205 return values[0] 206 } 207 208 return "" 209 } 210 211 func (c *Context) QueryInt(key string, values ...int) int { 212 if p, err := strconv.Atoi(c.Ctx.Query(key)); err == nil { 213 return p 214 } 215 216 if len(values) > 0 { 217 return values[0] 218 } 219 220 return 0 221 } 222 223 func (c *Context) Response() server.Response { 224 return &Response{c.Ctx.Response()} 225 } 226 227 func (c *Context) Method() string { 228 return c.Ctx.Method() 229 } 230 231 func (c *Context) Send(data []byte) error { 232 return c.Ctx.Send(data) 233 } 234 235 func (c *Context) SendString(data string) error { 236 return c.Ctx.SendString(data) 237 } 238 239 func (c *Context) OriginalURL() string { 240 return c.Ctx.OriginalURL() 241 } 242 243 func (c *Context) Path() string { 244 return c.Ctx.Path() 245 } 246 247 func (c *Context) Redirect(path string) error { 248 return c.Ctx.Redirect(path) 249 } 250 251 func (c *Context) RedirectToRoute(name string, params ...map[string]interface{}) error { 252 if len(params) > 0 { 253 return c.Ctx.RedirectToRoute(name, params[0]) 254 } 255 return c.Ctx.RedirectToRoute(name, fiber.Map{}) 256 } 257 258 func (c *Context) Header(key string, vals ...string) string { 259 260 if len(vals) > 0 { 261 c.Ctx.Set(key, vals[0]) 262 return vals[0] 263 } 264 265 return c.Ctx.Get(key) 266 } 267 268 func (c *Context) BodyParser(v interface{}) error { 269 return c.Ctx.BodyParser(v) 270 } 271 272 func (r *Response) Header(key string, vals ...string) string { 273 if len(vals) > 0 { 274 r.Response.Header.Add(key, vals[0]) 275 return vals[0] 276 } 277 278 return string(r.Response.Header.Peek(key)) 279 }