gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

context.go (37984B)


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