github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gin/context.go (about) 1 // Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2 // Use of this source code is governed by a MIT style 3 // license that can be found in the LICENSE file. 4 5 package gin 6 7 import ( 8 "errors" 9 "fmt" 10 "github.com/hellobchain/newcryptosm/http" 11 "io" 12 "io/ioutil" 13 "math" 14 "mime/multipart" 15 "net" 16 "net/url" 17 "os" 18 "strings" 19 "sync" 20 "time" 21 22 "github.com/hellobchain/third_party/gin/binding" 23 "github.com/hellobchain/third_party/gin/render" 24 "github.com/hellobchain/third_party/sse" 25 ) 26 27 // Content-Type MIME of the most common data formats. 28 const ( 29 MIMEJSON = binding.MIMEJSON 30 MIMEHTML = binding.MIMEHTML 31 MIMEXML = binding.MIMEXML 32 MIMEXML2 = binding.MIMEXML2 33 MIMEPlain = binding.MIMEPlain 34 MIMEPOSTForm = binding.MIMEPOSTForm 35 MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm 36 MIMEYAML = binding.MIMEYAML 37 ) 38 39 // BodyBytesKey indicates a default body bytes key. 40 const BodyBytesKey = "_gin-gonic/gin/bodybyteskey" 41 42 const abortIndex int8 = math.MaxInt8 / 2 43 44 // Context is the most important part of gin. It allows us to pass variables between middleware, 45 // manage the flow, validate the JSON of a request and render a JSON response for example. 46 type Context struct { 47 writermem responseWriter 48 Request *http.Request 49 Writer ResponseWriter 50 51 Params Params 52 handlers HandlersChain 53 index int8 54 fullPath string 55 56 engine *Engine 57 params *Params 58 59 // This mutex protect Keys map 60 mu sync.RWMutex 61 62 // Keys is a key/value pair exclusively for the context of each request. 63 Keys map[string]interface{} 64 65 // Errors is a list of errors attached to all the handlers/middlewares who used this context. 66 Errors errorMsgs 67 68 // Accepted defines a list of manually accepted formats for content negotiation. 69 Accepted []string 70 71 // queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query() 72 queryCache url.Values 73 74 // formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH, 75 // or PUT body parameters. 76 formCache url.Values 77 78 // SameSite allows a server to define a cookie attribute making it impossible for 79 // the browser to send this cookie along with cross-site requests. 80 sameSite http.SameSite 81 } 82 83 /************************************/ 84 /********** CONTEXT CREATION ********/ 85 /************************************/ 86 87 func (c *Context) reset() { 88 c.Writer = &c.writermem 89 c.Params = c.Params[0:0] 90 c.handlers = nil 91 c.index = -1 92 93 c.fullPath = "" 94 c.Keys = nil 95 c.Errors = c.Errors[0:0] 96 c.Accepted = nil 97 c.queryCache = nil 98 c.formCache = nil 99 *c.params = (*c.params)[0:0] 100 } 101 102 // Copy returns a copy of the current context that can be safely used outside the request's scope. 103 // This has to be used when the context has to be passed to a goroutine. 104 func (c *Context) Copy() *Context { 105 cp := Context{ 106 writermem: c.writermem, 107 Request: c.Request, 108 Params: c.Params, 109 engine: c.engine, 110 } 111 cp.writermem.ResponseWriter = nil 112 cp.Writer = &cp.writermem 113 cp.index = abortIndex 114 cp.handlers = nil 115 cp.Keys = map[string]interface{}{} 116 for k, v := range c.Keys { 117 cp.Keys[k] = v 118 } 119 paramCopy := make([]Param, len(cp.Params)) 120 copy(paramCopy, cp.Params) 121 cp.Params = paramCopy 122 return &cp 123 } 124 125 // HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()", 126 // this function will return "main.handleGetUsers". 127 func (c *Context) HandlerName() string { 128 return nameOfFunction(c.handlers.Last()) 129 } 130 131 // HandlerNames returns a list of all registered handlers for this context in descending order, 132 // following the semantics of HandlerName() 133 func (c *Context) HandlerNames() []string { 134 hn := make([]string, 0, len(c.handlers)) 135 for _, val := range c.handlers { 136 hn = append(hn, nameOfFunction(val)) 137 } 138 return hn 139 } 140 141 // Handler returns the main handler. 142 func (c *Context) Handler() HandlerFunc { 143 return c.handlers.Last() 144 } 145 146 // FullPath returns a matched route full path. For not found routes 147 // returns an empty string. 148 // router.GET("/user/:id", func(c *gin.Context) { 149 // c.FullPath() == "/user/:id" // true 150 // }) 151 func (c *Context) FullPath() string { 152 return c.fullPath 153 } 154 155 /************************************/ 156 /*********** FLOW CONTROL ***********/ 157 /************************************/ 158 159 // Next should be used only inside middleware. 160 // It executes the pending handlers in the chain inside the calling handler. 161 // See example in GitHub. 162 func (c *Context) Next() { 163 c.index++ 164 for c.index < int8(len(c.handlers)) { 165 c.handlers[c.index](c) 166 c.index++ 167 } 168 } 169 170 // IsAborted returns true if the current context was aborted. 171 func (c *Context) IsAborted() bool { 172 return c.index >= abortIndex 173 } 174 175 // Abort prevents pending handlers from being called. Note that this will not stop the current handler. 176 // Let's say you have an authorization middleware that validates that the current request is authorized. 177 // If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers 178 // for this request are not called. 179 func (c *Context) Abort() { 180 c.index = abortIndex 181 } 182 183 // AbortWithStatus calls `Abort()` and writes the headers with the specified status code. 184 // For example, a failed attempt to authenticate a request could use: context.AbortWithStatus(401). 185 func (c *Context) AbortWithStatus(code int) { 186 c.Status(code) 187 c.Writer.WriteHeaderNow() 188 c.Abort() 189 } 190 191 // AbortWithStatusJSON calls `Abort()` and then `JSON` internally. 192 // This method stops the chain, writes the status code and return a JSON body. 193 // It also sets the Content-Type as "application/json". 194 func (c *Context) AbortWithStatusJSON(code int, jsonObj interface{}) { 195 c.Abort() 196 c.JSON(code, jsonObj) 197 } 198 199 // AbortWithError calls `AbortWithStatus()` and `Error()` internally. 200 // This method stops the chain, writes the status code and pushes the specified error to `c.Errors`. 201 // See Context.Error() for more details. 202 func (c *Context) AbortWithError(code int, err error) *Error { 203 c.AbortWithStatus(code) 204 return c.Error(err) 205 } 206 207 /************************************/ 208 /********* ERROR MANAGEMENT *********/ 209 /************************************/ 210 211 // Error attaches an error to the current context. The error is pushed to a list of errors. 212 // It's a good idea to call Error for each error that occurred during the resolution of a request. 213 // A middleware can be used to collect all the errors and push them to a database together, 214 // print a log, or append it in the HTTP response. 215 // Error will panic if err is nil. 216 func (c *Context) Error(err error) *Error { 217 if err == nil { 218 panic("err is nil") 219 } 220 221 parsedError, ok := err.(*Error) 222 if !ok { 223 parsedError = &Error{ 224 Err: err, 225 Type: ErrorTypePrivate, 226 } 227 } 228 229 c.Errors = append(c.Errors, parsedError) 230 return parsedError 231 } 232 233 /************************************/ 234 /******** METADATA MANAGEMENT********/ 235 /************************************/ 236 237 // Set is used to store a new key/value pair exclusively for this context. 238 // It also lazy initializes c.Keys if it was not used previously. 239 func (c *Context) Set(key string, value interface{}) { 240 c.mu.Lock() 241 if c.Keys == nil { 242 c.Keys = make(map[string]interface{}) 243 } 244 245 c.Keys[key] = value 246 c.mu.Unlock() 247 } 248 249 // Get returns the value for the given key, ie: (value, true). 250 // If the value does not exists it returns (nil, false) 251 func (c *Context) Get(key string) (value interface{}, exists bool) { 252 c.mu.RLock() 253 value, exists = c.Keys[key] 254 c.mu.RUnlock() 255 return 256 } 257 258 // MustGet returns the value for the given key if it exists, otherwise it panics. 259 func (c *Context) MustGet(key string) interface{} { 260 if value, exists := c.Get(key); exists { 261 return value 262 } 263 panic("Key \"" + key + "\" does not exist") 264 } 265 266 // GetString returns the value associated with the key as a string. 267 func (c *Context) GetString(key string) (s string) { 268 if val, ok := c.Get(key); ok && val != nil { 269 s, _ = val.(string) 270 } 271 return 272 } 273 274 // GetBool returns the value associated with the key as a boolean. 275 func (c *Context) GetBool(key string) (b bool) { 276 if val, ok := c.Get(key); ok && val != nil { 277 b, _ = val.(bool) 278 } 279 return 280 } 281 282 // GetInt returns the value associated with the key as an integer. 283 func (c *Context) GetInt(key string) (i int) { 284 if val, ok := c.Get(key); ok && val != nil { 285 i, _ = val.(int) 286 } 287 return 288 } 289 290 // GetInt64 returns the value associated with the key as an integer. 291 func (c *Context) GetInt64(key string) (i64 int64) { 292 if val, ok := c.Get(key); ok && val != nil { 293 i64, _ = val.(int64) 294 } 295 return 296 } 297 298 // GetUint returns the value associated with the key as an unsigned integer. 299 func (c *Context) GetUint(key string) (ui uint) { 300 if val, ok := c.Get(key); ok && val != nil { 301 ui, _ = val.(uint) 302 } 303 return 304 } 305 306 // GetUint64 returns the value associated with the key as an unsigned integer. 307 func (c *Context) GetUint64(key string) (ui64 uint64) { 308 if val, ok := c.Get(key); ok && val != nil { 309 ui64, _ = val.(uint64) 310 } 311 return 312 } 313 314 // GetFloat64 returns the value associated with the key as a float64. 315 func (c *Context) GetFloat64(key string) (f64 float64) { 316 if val, ok := c.Get(key); ok && val != nil { 317 f64, _ = val.(float64) 318 } 319 return 320 } 321 322 // GetTime returns the value associated with the key as time. 323 func (c *Context) GetTime(key string) (t time.Time) { 324 if val, ok := c.Get(key); ok && val != nil { 325 t, _ = val.(time.Time) 326 } 327 return 328 } 329 330 // GetDuration returns the value associated with the key as a duration. 331 func (c *Context) GetDuration(key string) (d time.Duration) { 332 if val, ok := c.Get(key); ok && val != nil { 333 d, _ = val.(time.Duration) 334 } 335 return 336 } 337 338 // GetStringSlice returns the value associated with the key as a slice of strings. 339 func (c *Context) GetStringSlice(key string) (ss []string) { 340 if val, ok := c.Get(key); ok && val != nil { 341 ss, _ = val.([]string) 342 } 343 return 344 } 345 346 // GetStringMap returns the value associated with the key as a map of interfaces. 347 func (c *Context) GetStringMap(key string) (sm map[string]interface{}) { 348 if val, ok := c.Get(key); ok && val != nil { 349 sm, _ = val.(map[string]interface{}) 350 } 351 return 352 } 353 354 // GetStringMapString returns the value associated with the key as a map of strings. 355 func (c *Context) GetStringMapString(key string) (sms map[string]string) { 356 if val, ok := c.Get(key); ok && val != nil { 357 sms, _ = val.(map[string]string) 358 } 359 return 360 } 361 362 // GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. 363 func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string) { 364 if val, ok := c.Get(key); ok && val != nil { 365 smss, _ = val.(map[string][]string) 366 } 367 return 368 } 369 370 /************************************/ 371 /************ INPUT DATA ************/ 372 /************************************/ 373 374 // Param returns the value of the URL param. 375 // It is a shortcut for c.Params.ByName(key) 376 // router.GET("/user/:id", func(c *gin.Context) { 377 // // a GET request to /user/john 378 // id := c.Param("id") // id == "john" 379 // }) 380 func (c *Context) Param(key string) string { 381 return c.Params.ByName(key) 382 } 383 384 // Query returns the keyed url query value if it exists, 385 // otherwise it returns an empty string `("")`. 386 // It is shortcut for `c.Request.URL.Query().Get(key)` 387 // GET /path?id=1234&name=Manu&value= 388 // c.Query("id") == "1234" 389 // c.Query("name") == "Manu" 390 // c.Query("value") == "" 391 // c.Query("wtf") == "" 392 func (c *Context) Query(key string) string { 393 value, _ := c.GetQuery(key) 394 return value 395 } 396 397 // DefaultQuery returns the keyed url query value if it exists, 398 // otherwise it returns the specified defaultValue string. 399 // See: Query() and GetQuery() for further information. 400 // GET /?name=Manu&lastname= 401 // c.DefaultQuery("name", "unknown") == "Manu" 402 // c.DefaultQuery("id", "none") == "none" 403 // c.DefaultQuery("lastname", "none") == "" 404 func (c *Context) DefaultQuery(key, defaultValue string) string { 405 if value, ok := c.GetQuery(key); ok { 406 return value 407 } 408 return defaultValue 409 } 410 411 // GetQuery is like Query(), it returns the keyed url query value 412 // if it exists `(value, true)` (even when the value is an empty string), 413 // otherwise it returns `("", false)`. 414 // It is shortcut for `c.Request.URL.Query().Get(key)` 415 // GET /?name=Manu&lastname= 416 // ("Manu", true) == c.GetQuery("name") 417 // ("", false) == c.GetQuery("id") 418 // ("", true) == c.GetQuery("lastname") 419 func (c *Context) GetQuery(key string) (string, bool) { 420 if values, ok := c.GetQueryArray(key); ok { 421 return values[0], ok 422 } 423 return "", false 424 } 425 426 // QueryArray returns a slice of strings for a given query key. 427 // The length of the slice depends on the number of params with the given key. 428 func (c *Context) QueryArray(key string) []string { 429 values, _ := c.GetQueryArray(key) 430 return values 431 } 432 433 func (c *Context) initQueryCache() { 434 if c.queryCache == nil { 435 if c.Request != nil { 436 c.queryCache = c.Request.URL.Query() 437 } else { 438 c.queryCache = url.Values{} 439 } 440 } 441 } 442 443 // GetQueryArray returns a slice of strings for a given query key, plus 444 // a boolean value whether at least one value exists for the given key. 445 func (c *Context) GetQueryArray(key string) ([]string, bool) { 446 c.initQueryCache() 447 if values, ok := c.queryCache[key]; ok && len(values) > 0 { 448 return values, true 449 } 450 return []string{}, false 451 } 452 453 // QueryMap returns a map for a given query key. 454 func (c *Context) QueryMap(key string) map[string]string { 455 dicts, _ := c.GetQueryMap(key) 456 return dicts 457 } 458 459 // GetQueryMap returns a map for a given query key, plus a boolean value 460 // whether at least one value exists for the given key. 461 func (c *Context) GetQueryMap(key string) (map[string]string, bool) { 462 c.initQueryCache() 463 return c.get(c.queryCache, key) 464 } 465 466 // PostForm returns the specified key from a POST urlencoded form or multipart form 467 // when it exists, otherwise it returns an empty string `("")`. 468 func (c *Context) PostForm(key string) string { 469 value, _ := c.GetPostForm(key) 470 return value 471 } 472 473 // DefaultPostForm returns the specified key from a POST urlencoded form or multipart form 474 // when it exists, otherwise it returns the specified defaultValue string. 475 // See: PostForm() and GetPostForm() for further information. 476 func (c *Context) DefaultPostForm(key, defaultValue string) string { 477 if value, ok := c.GetPostForm(key); ok { 478 return value 479 } 480 return defaultValue 481 } 482 483 // GetPostForm is like PostForm(key). It returns the specified key from a POST urlencoded 484 // form or multipart form when it exists `(value, true)` (even when the value is an empty string), 485 // otherwise it returns ("", false). 486 // For example, during a PATCH request to update the user's email: 487 // email=mail@example.com --> ("mail@example.com", true) := GetPostForm("email") // set email to "mail@example.com" 488 // email= --> ("", true) := GetPostForm("email") // set email to "" 489 // --> ("", false) := GetPostForm("email") // do nothing with email 490 func (c *Context) GetPostForm(key string) (string, bool) { 491 if values, ok := c.GetPostFormArray(key); ok { 492 return values[0], ok 493 } 494 return "", false 495 } 496 497 // PostFormArray returns a slice of strings for a given form key. 498 // The length of the slice depends on the number of params with the given key. 499 func (c *Context) PostFormArray(key string) []string { 500 values, _ := c.GetPostFormArray(key) 501 return values 502 } 503 504 func (c *Context) initFormCache() { 505 if c.formCache == nil { 506 c.formCache = make(url.Values) 507 req := c.Request 508 if err := req.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil { 509 if err != http.ErrNotMultipart { 510 debugPrint("error on parse multipart form array: %v", err) 511 } 512 } 513 c.formCache = req.PostForm 514 } 515 } 516 517 // GetPostFormArray returns a slice of strings for a given form key, plus 518 // a boolean value whether at least one value exists for the given key. 519 func (c *Context) GetPostFormArray(key string) ([]string, bool) { 520 c.initFormCache() 521 if values := c.formCache[key]; len(values) > 0 { 522 return values, true 523 } 524 return []string{}, false 525 } 526 527 // PostFormMap returns a map for a given form key. 528 func (c *Context) PostFormMap(key string) map[string]string { 529 dicts, _ := c.GetPostFormMap(key) 530 return dicts 531 } 532 533 // GetPostFormMap returns a map for a given form key, plus a boolean value 534 // whether at least one value exists for the given key. 535 func (c *Context) GetPostFormMap(key string) (map[string]string, bool) { 536 c.initFormCache() 537 return c.get(c.formCache, key) 538 } 539 540 // get is an internal method and returns a map which satisfy conditions. 541 func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) { 542 dicts := make(map[string]string) 543 exist := false 544 for k, v := range m { 545 if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key { 546 if j := strings.IndexByte(k[i+1:], ']'); j >= 1 { 547 exist = true 548 dicts[k[i+1:][:j]] = v[0] 549 } 550 } 551 } 552 return dicts, exist 553 } 554 555 // FormFile returns the first file for the provided form key. 556 func (c *Context) FormFile(name string) (*multipart.FileHeader, error) { 557 if c.Request.MultipartForm == nil { 558 if err := c.Request.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil { 559 return nil, err 560 } 561 } 562 f, fh, err := c.Request.FormFile(name) 563 if err != nil { 564 return nil, err 565 } 566 f.Close() 567 return fh, err 568 } 569 570 // MultipartForm is the parsed multipart form, including file uploads. 571 func (c *Context) MultipartForm() (*multipart.Form, error) { 572 err := c.Request.ParseMultipartForm(c.engine.MaxMultipartMemory) 573 return c.Request.MultipartForm, err 574 } 575 576 // SaveUploadedFile uploads the form file to specific dst. 577 func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error { 578 src, err := file.Open() 579 if err != nil { 580 return err 581 } 582 defer src.Close() 583 584 out, err := os.Create(dst) 585 if err != nil { 586 return err 587 } 588 defer out.Close() 589 590 _, err = io.Copy(out, src) 591 return err 592 } 593 594 // Bind checks the Content-Type to select a binding engine automatically, 595 // Depending the "Content-Type" header different bindings are used: 596 // "application/json" --> JSON binding 597 // "application/xml" --> XML binding 598 // otherwise --> returns an error. 599 // It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input. 600 // It decodes the json payload into the struct specified as a pointer. 601 // It writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid. 602 func (c *Context) Bind(obj interface{}) error { 603 b := binding.Default(c.Request.Method, c.ContentType()) 604 return c.MustBindWith(obj, b) 605 } 606 607 // BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON). 608 func (c *Context) BindJSON(obj interface{}) error { 609 return c.MustBindWith(obj, binding.JSON) 610 } 611 612 // BindXML is a shortcut for c.MustBindWith(obj, binding.BindXML). 613 func (c *Context) BindXML(obj interface{}) error { 614 return c.MustBindWith(obj, binding.XML) 615 } 616 617 // BindQuery is a shortcut for c.MustBindWith(obj, binding.Query). 618 func (c *Context) BindQuery(obj interface{}) error { 619 return c.MustBindWith(obj, binding.Query) 620 } 621 622 // BindYAML is a shortcut for c.MustBindWith(obj, binding.YAML). 623 func (c *Context) BindYAML(obj interface{}) error { 624 return c.MustBindWith(obj, binding.YAML) 625 } 626 627 // BindHeader is a shortcut for c.MustBindWith(obj, binding.Header). 628 func (c *Context) BindHeader(obj interface{}) error { 629 return c.MustBindWith(obj, binding.Header) 630 } 631 632 // BindUri binds the passed struct pointer using binding.Uri. 633 // It will abort the request with HTTP 400 if any error occurs. 634 func (c *Context) BindUri(obj interface{}) error { 635 if err := c.ShouldBindUri(obj); err != nil { 636 c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck 637 return err 638 } 639 return nil 640 } 641 642 // MustBindWith binds the passed struct pointer using the specified binding engine. 643 // It will abort the request with HTTP 400 if any error occurs. 644 // See the binding package. 645 func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error { 646 if err := c.ShouldBindWith(obj, b); err != nil { 647 c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck 648 return err 649 } 650 return nil 651 } 652 653 // ShouldBind checks the Content-Type to select a binding engine automatically, 654 // Depending the "Content-Type" header different bindings are used: 655 // "application/json" --> JSON binding 656 // "application/xml" --> XML binding 657 // otherwise --> returns an error 658 // It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input. 659 // It decodes the json payload into the struct specified as a pointer. 660 // Like c.Bind() but this method does not set the response status code to 400 and abort if the json is not valid. 661 func (c *Context) ShouldBind(obj interface{}) error { 662 b := binding.Default(c.Request.Method, c.ContentType()) 663 return c.ShouldBindWith(obj, b) 664 } 665 666 // ShouldBindJSON is a shortcut for c.ShouldBindWith(obj, binding.JSON). 667 func (c *Context) ShouldBindJSON(obj interface{}) error { 668 return c.ShouldBindWith(obj, binding.JSON) 669 } 670 671 // ShouldBindXML is a shortcut for c.ShouldBindWith(obj, binding.XML). 672 func (c *Context) ShouldBindXML(obj interface{}) error { 673 return c.ShouldBindWith(obj, binding.XML) 674 } 675 676 // ShouldBindQuery is a shortcut for c.ShouldBindWith(obj, binding.Query). 677 func (c *Context) ShouldBindQuery(obj interface{}) error { 678 return c.ShouldBindWith(obj, binding.Query) 679 } 680 681 // ShouldBindYAML is a shortcut for c.ShouldBindWith(obj, binding.YAML). 682 func (c *Context) ShouldBindYAML(obj interface{}) error { 683 return c.ShouldBindWith(obj, binding.YAML) 684 } 685 686 // ShouldBindHeader is a shortcut for c.ShouldBindWith(obj, binding.Header). 687 func (c *Context) ShouldBindHeader(obj interface{}) error { 688 return c.ShouldBindWith(obj, binding.Header) 689 } 690 691 // ShouldBindUri binds the passed struct pointer using the specified binding engine. 692 func (c *Context) ShouldBindUri(obj interface{}) error { 693 m := make(map[string][]string) 694 for _, v := range c.Params { 695 m[v.Key] = []string{v.Value} 696 } 697 return binding.Uri.BindUri(m, obj) 698 } 699 700 // ShouldBindWith binds the passed struct pointer using the specified binding engine. 701 // See the binding package. 702 func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error { 703 return b.Bind(c.Request, obj) 704 } 705 706 // ShouldBindBodyWith is similar with ShouldBindWith, but it stores the request 707 // body into the context, and reuse when it is called again. 708 // 709 // NOTE: This method reads the body before binding. So you should use 710 // ShouldBindWith for better performance if you need to call only once. 711 func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error) { 712 var body []byte 713 if cb, ok := c.Get(BodyBytesKey); ok { 714 if cbb, ok := cb.([]byte); ok { 715 body = cbb 716 } 717 } 718 if body == nil { 719 body, err = ioutil.ReadAll(c.Request.Body) 720 if err != nil { 721 return err 722 } 723 c.Set(BodyBytesKey, body) 724 } 725 return bb.BindBody(body, obj) 726 } 727 728 // ClientIP implements a best effort algorithm to return the real client IP. 729 // It called c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not. 730 // If it's it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]). 731 // If the headers are nots syntactically valid OR the remote IP does not correspong to a trusted proxy, 732 // the remote IP (coming form Request.RemoteAddr) is returned. 733 func (c *Context) ClientIP() string { 734 if c.engine.AppEngine { 735 if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" { 736 return addr 737 } 738 } 739 740 remoteIP, trusted := c.RemoteIP() 741 if remoteIP == nil { 742 return "" 743 } 744 745 if trusted && c.engine.ForwardedByClientIP && c.engine.RemoteIPHeaders != nil { 746 for _, headerName := range c.engine.RemoteIPHeaders { 747 ip, valid := validateHeader(c.requestHeader(headerName)) 748 if valid { 749 return ip 750 } 751 } 752 } 753 return remoteIP.String() 754 } 755 756 // RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port). 757 // It also checks if the remoteIP is a trusted proxy or not. 758 // In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks 759 // defined in Engine.TrustedProxies 760 func (c *Context) RemoteIP() (net.IP, bool) { 761 ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr)) 762 if err != nil { 763 return nil, false 764 } 765 remoteIP := net.ParseIP(ip) 766 if remoteIP == nil { 767 return nil, false 768 } 769 770 if c.engine.trustedCIDRs != nil { 771 for _, cidr := range c.engine.trustedCIDRs { 772 if cidr.Contains(remoteIP) { 773 return remoteIP, true 774 } 775 } 776 } 777 778 return remoteIP, false 779 } 780 781 func validateHeader(header string) (clientIP string, valid bool) { 782 if header == "" { 783 return "", false 784 } 785 items := strings.Split(header, ",") 786 for i, ipStr := range items { 787 ipStr = strings.TrimSpace(ipStr) 788 ip := net.ParseIP(ipStr) 789 if ip == nil { 790 return "", false 791 } 792 793 // We need to return the first IP in the list, but, 794 // we should not early return since we need to validate that 795 // the rest of the header is syntactically valid 796 if i == 0 { 797 clientIP = ipStr 798 valid = true 799 } 800 } 801 return 802 } 803 804 // ContentType returns the Content-Type header of the request. 805 func (c *Context) ContentType() string { 806 return filterFlags(c.requestHeader("Content-Type")) 807 } 808 809 // IsWebsocket returns true if the request headers indicate that a websocket 810 // handshake is being initiated by the client. 811 func (c *Context) IsWebsocket() bool { 812 if strings.Contains(strings.ToLower(c.requestHeader("Connection")), "upgrade") && 813 strings.EqualFold(c.requestHeader("Upgrade"), "websocket") { 814 return true 815 } 816 return false 817 } 818 819 func (c *Context) requestHeader(key string) string { 820 return c.Request.Header.Get(key) 821 } 822 823 /************************************/ 824 /******** RESPONSE RENDERING ********/ 825 /************************************/ 826 827 // bodyAllowedForStatus is a copy of http.bodyAllowedForStatus non-exported function. 828 func bodyAllowedForStatus(status int) bool { 829 switch { 830 case status >= 100 && status <= 199: 831 return false 832 case status == http.StatusNoContent: 833 return false 834 case status == http.StatusNotModified: 835 return false 836 } 837 return true 838 } 839 840 // Status sets the HTTP response code. 841 func (c *Context) Status(code int) { 842 c.Writer.WriteHeader(code) 843 } 844 845 // Header is a intelligent shortcut for c.Writer.Header().Set(key, value). 846 // It writes a header in the response. 847 // If value == "", this method removes the header `c.Writer.Header().Del(key)` 848 func (c *Context) Header(key, value string) { 849 if value == "" { 850 c.Writer.Header().Del(key) 851 return 852 } 853 c.Writer.Header().Set(key, value) 854 } 855 856 // GetHeader returns value from request headers. 857 func (c *Context) GetHeader(key string) string { 858 return c.requestHeader(key) 859 } 860 861 // GetRawData return stream data. 862 func (c *Context) GetRawData() ([]byte, error) { 863 return ioutil.ReadAll(c.Request.Body) 864 } 865 866 // SetSameSite with cookie 867 func (c *Context) SetSameSite(samesite http.SameSite) { 868 c.sameSite = samesite 869 } 870 871 // SetCookie adds a Set-Cookie header to the ResponseWriter's headers. 872 // The provided cookie must have a valid Name. Invalid cookies may be 873 // silently dropped. 874 func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) { 875 if path == "" { 876 path = "/" 877 } 878 http.SetCookie(c.Writer, &http.Cookie{ 879 Name: name, 880 Value: url.QueryEscape(value), 881 MaxAge: maxAge, 882 Path: path, 883 Domain: domain, 884 SameSite: c.sameSite, 885 Secure: secure, 886 HttpOnly: httpOnly, 887 }) 888 } 889 890 // Cookie returns the named cookie provided in the request or 891 // ErrNoCookie if not found. And return the named cookie is unescaped. 892 // If multiple cookies match the given name, only one cookie will 893 // be returned. 894 func (c *Context) Cookie(name string) (string, error) { 895 cookie, err := c.Request.Cookie(name) 896 if err != nil { 897 return "", err 898 } 899 val, _ := url.QueryUnescape(cookie.Value) 900 return val, nil 901 } 902 903 // Render writes the response headers and calls render.Render to render data. 904 func (c *Context) Render(code int, r render.Render) { 905 c.Status(code) 906 907 if !bodyAllowedForStatus(code) { 908 r.WriteContentType(c.Writer) 909 c.Writer.WriteHeaderNow() 910 return 911 } 912 913 if err := r.Render(c.Writer); err != nil { 914 panic(err) 915 } 916 } 917 918 // HTML renders the HTTP template specified by its file name. 919 // It also updates the HTTP code and sets the Content-Type as "text/html". 920 // See http://golang.org/doc/articles/wiki/ 921 func (c *Context) HTML(code int, name string, obj interface{}) { 922 instance := c.engine.HTMLRender.Instance(name, obj) 923 c.Render(code, instance) 924 } 925 926 // IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body. 927 // It also sets the Content-Type as "application/json". 928 // WARNING: we recommend to use this only for development purposes since printing pretty JSON is 929 // more CPU and bandwidth consuming. Use Context.JSON() instead. 930 func (c *Context) IndentedJSON(code int, obj interface{}) { 931 c.Render(code, render.IndentedJSON{Data: obj}) 932 } 933 934 // SecureJSON serializes the given struct as Secure JSON into the response body. 935 // Default prepends "while(1)," to response body if the given struct is array values. 936 // It also sets the Content-Type as "application/json". 937 func (c *Context) SecureJSON(code int, obj interface{}) { 938 c.Render(code, render.SecureJSON{Prefix: c.engine.secureJSONPrefix, Data: obj}) 939 } 940 941 // JSONP serializes the given struct as JSON into the response body. 942 // It adds padding to response body to request data from a server residing in a different domain than the client. 943 // It also sets the Content-Type as "application/javascript". 944 func (c *Context) JSONP(code int, obj interface{}) { 945 callback := c.DefaultQuery("callback", "") 946 if callback == "" { 947 c.Render(code, render.JSON{Data: obj}) 948 return 949 } 950 c.Render(code, render.JsonpJSON{Callback: callback, Data: obj}) 951 } 952 953 // JSON serializes the given struct as JSON into the response body. 954 // It also sets the Content-Type as "application/json". 955 func (c *Context) JSON(code int, obj interface{}) { 956 c.Render(code, render.JSON{Data: obj}) 957 } 958 959 // AsciiJSON serializes the given struct as JSON into the response body with unicode to ASCII string. 960 // It also sets the Content-Type as "application/json". 961 func (c *Context) AsciiJSON(code int, obj interface{}) { 962 c.Render(code, render.AsciiJSON{Data: obj}) 963 } 964 965 // PureJSON serializes the given struct as JSON into the response body. 966 // PureJSON, unlike JSON, does not replace special html characters with their unicode entities. 967 func (c *Context) PureJSON(code int, obj interface{}) { 968 c.Render(code, render.PureJSON{Data: obj}) 969 } 970 971 // XML serializes the given struct as XML into the response body. 972 // It also sets the Content-Type as "application/xml". 973 func (c *Context) XML(code int, obj interface{}) { 974 c.Render(code, render.XML{Data: obj}) 975 } 976 977 // YAML serializes the given struct as YAML into the response body. 978 func (c *Context) YAML(code int, obj interface{}) { 979 c.Render(code, render.YAML{Data: obj}) 980 } 981 982 // ProtoBuf serializes the given struct as ProtoBuf into the response body. 983 func (c *Context) ProtoBuf(code int, obj interface{}) { 984 c.Render(code, render.ProtoBuf{Data: obj}) 985 } 986 987 // String writes the given string into the response body. 988 func (c *Context) String(code int, format string, values ...interface{}) { 989 c.Render(code, render.String{Format: format, Data: values}) 990 } 991 992 // Redirect returns a HTTP redirect to the specific location. 993 func (c *Context) Redirect(code int, location string) { 994 c.Render(-1, render.Redirect{ 995 Code: code, 996 Location: location, 997 Request: c.Request, 998 }) 999 } 1000 1001 // Data writes some data into the body stream and updates the HTTP code. 1002 func (c *Context) Data(code int, contentType string, data []byte) { 1003 c.Render(code, render.Data{ 1004 ContentType: contentType, 1005 Data: data, 1006 }) 1007 } 1008 1009 // DataFromReader writes the specified reader into the body stream and updates the HTTP code. 1010 func (c *Context) DataFromReader(code int, contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string) { 1011 c.Render(code, render.Reader{ 1012 Headers: extraHeaders, 1013 ContentType: contentType, 1014 ContentLength: contentLength, 1015 Reader: reader, 1016 }) 1017 } 1018 1019 // File writes the specified file into the body stream in an efficient way. 1020 func (c *Context) File(filepath string) { 1021 http.ServeFile(c.Writer, c.Request, filepath) 1022 } 1023 1024 // FileFromFS writes the specified file from http.FileSystem into the body stream in an efficient way. 1025 func (c *Context) FileFromFS(filepath string, fs http.FileSystem) { 1026 defer func(old string) { 1027 c.Request.URL.Path = old 1028 }(c.Request.URL.Path) 1029 1030 c.Request.URL.Path = filepath 1031 1032 http.FileServer(fs).ServeHTTP(c.Writer, c.Request) 1033 } 1034 1035 // FileAttachment writes the specified file into the body stream in an efficient way 1036 // On the client side, the file will typically be downloaded with the given filename 1037 func (c *Context) FileAttachment(filepath, filename string) { 1038 c.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename)) 1039 http.ServeFile(c.Writer, c.Request, filepath) 1040 } 1041 1042 // SSEvent writes a Server-Sent Event into the body stream. 1043 func (c *Context) SSEvent(name string, message interface{}) { 1044 c.Render(-1, sse.Event{ 1045 Event: name, 1046 Data: message, 1047 }) 1048 } 1049 1050 // Stream sends a streaming response and returns a boolean 1051 // indicates "Is client disconnected in middle of stream" 1052 func (c *Context) Stream(step func(w io.Writer) bool) bool { 1053 w := c.Writer 1054 clientGone := w.CloseNotify() 1055 for { 1056 select { 1057 case <-clientGone: 1058 return true 1059 default: 1060 keepOpen := step(w) 1061 w.Flush() 1062 if !keepOpen { 1063 return false 1064 } 1065 } 1066 } 1067 } 1068 1069 /************************************/ 1070 /******** CONTENT NEGOTIATION *******/ 1071 /************************************/ 1072 1073 // Negotiate contains all negotiations data. 1074 type Negotiate struct { 1075 Offered []string 1076 HTMLName string 1077 HTMLData interface{} 1078 JSONData interface{} 1079 XMLData interface{} 1080 YAMLData interface{} 1081 Data interface{} 1082 } 1083 1084 // Negotiate calls different Render according acceptable Accept format. 1085 func (c *Context) Negotiate(code int, config Negotiate) { 1086 switch c.NegotiateFormat(config.Offered...) { 1087 case binding.MIMEJSON: 1088 data := chooseData(config.JSONData, config.Data) 1089 c.JSON(code, data) 1090 1091 case binding.MIMEHTML: 1092 data := chooseData(config.HTMLData, config.Data) 1093 c.HTML(code, config.HTMLName, data) 1094 1095 case binding.MIMEXML: 1096 data := chooseData(config.XMLData, config.Data) 1097 c.XML(code, data) 1098 1099 case binding.MIMEYAML: 1100 data := chooseData(config.YAMLData, config.Data) 1101 c.YAML(code, data) 1102 1103 default: 1104 c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) // nolint: errcheck 1105 } 1106 } 1107 1108 // NegotiateFormat returns an acceptable Accept format. 1109 func (c *Context) NegotiateFormat(offered ...string) string { 1110 assert1(len(offered) > 0, "you must provide at least one offer") 1111 1112 if c.Accepted == nil { 1113 c.Accepted = parseAccept(c.requestHeader("Accept")) 1114 } 1115 if len(c.Accepted) == 0 { 1116 return offered[0] 1117 } 1118 for _, accepted := range c.Accepted { 1119 for _, offer := range offered { 1120 // According to RFC 2616 and RFC 2396, non-ASCII characters are not allowed in headers, 1121 // therefore we can just iterate over the string without casting it into []rune 1122 i := 0 1123 for ; i < len(accepted); i++ { 1124 if accepted[i] == '*' || offer[i] == '*' { 1125 return offer 1126 } 1127 if accepted[i] != offer[i] { 1128 break 1129 } 1130 } 1131 if i == len(accepted) { 1132 return offer 1133 } 1134 } 1135 } 1136 return "" 1137 } 1138 1139 // SetAccepted sets Accept header data. 1140 func (c *Context) SetAccepted(formats ...string) { 1141 c.Accepted = formats 1142 } 1143 1144 /************************************/ 1145 /***** GOLANG.ORG/X/NET/CONTEXT *****/ 1146 /************************************/ 1147 1148 // Deadline always returns that there is no deadline (ok==false), 1149 // maybe you want to use Request.Context().Deadline() instead. 1150 func (c *Context) Deadline() (deadline time.Time, ok bool) { 1151 return 1152 } 1153 1154 // Done always returns nil (chan which will wait forever), 1155 // if you want to abort your work when the connection was closed 1156 // you should use Request.Context().Done() instead. 1157 func (c *Context) Done() <-chan struct{} { 1158 return nil 1159 } 1160 1161 // Err always returns nil, maybe you want to use Request.Context().Err() instead. 1162 func (c *Context) Err() error { 1163 return nil 1164 } 1165 1166 // Value returns the value associated with this context for key, or nil 1167 // if no value is associated with key. Successive calls to Value with 1168 // the same key returns the same result. 1169 func (c *Context) Value(key interface{}) interface{} { 1170 if key == 0 { 1171 return c.Request 1172 } 1173 if keyAsString, ok := key.(string); ok { 1174 val, _ := c.Get(keyAsString) 1175 return val 1176 } 1177 return nil 1178 }