github.com/cloudwego/hertz@v0.9.3/pkg/app/context.go (about)

     1  /*
     2   * Copyright 2022 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   *
    16   * The MIT License (MIT)
    17   *
    18   * Copyright (c) 2015-present Aliaksandr Valialkin, VertaMedia, Kirill Danshin, Erik Dubbelboer, FastHTTP Authors
    19   *
    20   * Permission is hereby granted, free of charge, to any person obtaining a copy
    21   * of this software and associated documentation files (the "Software"), to deal
    22   * in the Software without restriction, including without limitation the rights
    23   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    24   * copies of the Software, and to permit persons to whom the Software is
    25   * furnished to do so, subject to the following conditions:
    26   *
    27   * The above copyright notice and this permission notice shall be included in
    28   * all copies or substantial portions of the Software.
    29   *
    30   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    31   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    32   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    33   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    34   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    35   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    36   * THE SOFTWARE.
    37   *
    38   * This file may have been modified by CloudWeGo authors. All CloudWeGo
    39   * Modifications are Copyright 2022 CloudWeGo Authors.
    40   */
    41  
    42  package app
    43  
    44  import (
    45  	"context"
    46  	"fmt"
    47  	"io"
    48  	"mime/multipart"
    49  	"net"
    50  	"net/url"
    51  	"os"
    52  	"reflect"
    53  	"strings"
    54  	"sync"
    55  	"time"
    56  
    57  	"github.com/cloudwego/hertz/internal/bytesconv"
    58  	"github.com/cloudwego/hertz/internal/bytestr"
    59  	"github.com/cloudwego/hertz/pkg/app/server/binding"
    60  	"github.com/cloudwego/hertz/pkg/app/server/render"
    61  	"github.com/cloudwego/hertz/pkg/common/errors"
    62  	"github.com/cloudwego/hertz/pkg/common/tracer/traceinfo"
    63  	"github.com/cloudwego/hertz/pkg/common/utils"
    64  	"github.com/cloudwego/hertz/pkg/network"
    65  	"github.com/cloudwego/hertz/pkg/protocol"
    66  	"github.com/cloudwego/hertz/pkg/protocol/consts"
    67  	rConsts "github.com/cloudwego/hertz/pkg/route/consts"
    68  	"github.com/cloudwego/hertz/pkg/route/param"
    69  )
    70  
    71  var zeroTCPAddr = &net.TCPAddr{
    72  	IP: net.IPv4zero,
    73  }
    74  
    75  type Handler interface {
    76  	ServeHTTP(c context.Context, ctx *RequestContext)
    77  }
    78  
    79  type ClientIP func(ctx *RequestContext) string
    80  
    81  type ClientIPOptions struct {
    82  	RemoteIPHeaders []string
    83  	TrustedCIDRs    []*net.IPNet
    84  }
    85  
    86  var defaultTrustedCIDRs = []*net.IPNet{
    87  	{ // 0.0.0.0/0 (IPv4)
    88  		IP:   net.IP{0x0, 0x0, 0x0, 0x0},
    89  		Mask: net.IPMask{0x0, 0x0, 0x0, 0x0},
    90  	},
    91  	{ // ::/0 (IPv6)
    92  		IP:   net.IP{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
    93  		Mask: net.IPMask{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
    94  	},
    95  }
    96  
    97  var defaultClientIPOptions = ClientIPOptions{
    98  	RemoteIPHeaders: []string{"X-Forwarded-For", "X-Real-IP"},
    99  	TrustedCIDRs:    defaultTrustedCIDRs,
   100  }
   101  
   102  // ClientIPWithOption used to generate custom ClientIP function and set by engine.SetClientIPFunc
   103  func ClientIPWithOption(opts ClientIPOptions) ClientIP {
   104  	return func(ctx *RequestContext) string {
   105  		RemoteIPHeaders := opts.RemoteIPHeaders
   106  		TrustedCIDRs := opts.TrustedCIDRs
   107  
   108  		remoteIPStr, _, err := net.SplitHostPort(strings.TrimSpace(ctx.RemoteAddr().String()))
   109  		if err != nil {
   110  			return ""
   111  		}
   112  
   113  		remoteIP := net.ParseIP(remoteIPStr)
   114  		if remoteIP == nil {
   115  			return ""
   116  		}
   117  
   118  		trusted := isTrustedProxy(TrustedCIDRs, remoteIP)
   119  
   120  		if trusted {
   121  			for _, headerName := range RemoteIPHeaders {
   122  				ip, valid := validateHeader(TrustedCIDRs, ctx.Request.Header.Get(headerName))
   123  				if valid {
   124  					return ip
   125  				}
   126  			}
   127  		}
   128  
   129  		return remoteIPStr
   130  	}
   131  }
   132  
   133  // isTrustedProxy will check whether the IP address is included in the trusted list according to trustedCIDRs
   134  func isTrustedProxy(trustedCIDRs []*net.IPNet, remoteIP net.IP) bool {
   135  	if trustedCIDRs == nil {
   136  		return false
   137  	}
   138  
   139  	for _, cidr := range trustedCIDRs {
   140  		if cidr.Contains(remoteIP) {
   141  			return true
   142  		}
   143  	}
   144  	return false
   145  }
   146  
   147  // validateHeader will parse X-Real-IP and X-Forwarded-For header and return the Initial client IP address or an untrusted IP address
   148  func validateHeader(trustedCIDRs []*net.IPNet, header string) (clientIP string, valid bool) {
   149  	if header == "" {
   150  		return "", false
   151  	}
   152  	items := strings.Split(header, ",")
   153  	for i := len(items) - 1; i >= 0; i-- {
   154  		ipStr := strings.TrimSpace(items[i])
   155  		ip := net.ParseIP(ipStr)
   156  		if ip == nil {
   157  			break
   158  		}
   159  
   160  		// X-Forwarded-For is appended by proxy
   161  		// Check IPs in reverse order and stop when find untrusted proxy
   162  		if (i == 0) || (!isTrustedProxy(trustedCIDRs, ip)) {
   163  			return ipStr, true
   164  		}
   165  	}
   166  	return "", false
   167  }
   168  
   169  var defaultClientIP = ClientIPWithOption(defaultClientIPOptions)
   170  
   171  // SetClientIPFunc sets ClientIP function implementation to get ClientIP.
   172  // Deprecated: Use engine.SetClientIPFunc instead of SetClientIPFunc
   173  func SetClientIPFunc(fn ClientIP) {
   174  	defaultClientIP = fn
   175  }
   176  
   177  type FormValueFunc func(*RequestContext, string) []byte
   178  
   179  var defaultFormValue = func(ctx *RequestContext, key string) []byte {
   180  	v := ctx.QueryArgs().Peek(key)
   181  	if len(v) > 0 {
   182  		return v
   183  	}
   184  	v = ctx.PostArgs().Peek(key)
   185  	if len(v) > 0 {
   186  		return v
   187  	}
   188  	mf, err := ctx.MultipartForm()
   189  	if err == nil && mf.Value != nil {
   190  		vv := mf.Value[key]
   191  		if len(vv) > 0 {
   192  			return []byte(vv[0])
   193  		}
   194  	}
   195  	return nil
   196  }
   197  
   198  type RequestContext struct {
   199  	conn     network.Conn
   200  	Request  protocol.Request
   201  	Response protocol.Response
   202  
   203  	// Errors is a list of errors attached to all the handlers/middlewares who used this context.
   204  	Errors errors.ErrorChain
   205  
   206  	Params     param.Params
   207  	handlers   HandlersChain
   208  	fullPath   string
   209  	index      int8
   210  	HTMLRender render.HTMLRender
   211  
   212  	// This mutex protect Keys map.
   213  	mu sync.RWMutex
   214  
   215  	// Keys is a key/value pair exclusively for the context of each request.
   216  	Keys map[string]interface{}
   217  
   218  	hijackHandler HijackHandler
   219  
   220  	finishedMu sync.Mutex
   221  
   222  	// finished means the request end.
   223  	finished chan struct{}
   224  
   225  	// traceInfo defines the trace information.
   226  	traceInfo traceinfo.TraceInfo
   227  
   228  	// enableTrace defines whether enable trace.
   229  	enableTrace bool
   230  
   231  	// clientIPFunc get client ip by use custom function.
   232  	clientIPFunc ClientIP
   233  
   234  	// clientIPFunc get form value by use custom function.
   235  	formValueFunc FormValueFunc
   236  
   237  	binder    binding.Binder
   238  	validator binding.StructValidator
   239  	exiled    bool
   240  }
   241  
   242  // Exile marks this RequestContext as not to be recycled.
   243  // Experimental features: Use with caution, it may have a slight impact on performance.
   244  func (ctx *RequestContext) Exile() {
   245  	ctx.exiled = true
   246  }
   247  
   248  func (ctx *RequestContext) IsExiled() bool {
   249  	return ctx.exiled
   250  }
   251  
   252  // Flush is the shortcut for ctx.Response.GetHijackWriter().Flush().
   253  // Will return nil if the response writer is not hijacked.
   254  func (ctx *RequestContext) Flush() error {
   255  	if ctx.Response.GetHijackWriter() == nil {
   256  		return nil
   257  	}
   258  	return ctx.Response.GetHijackWriter().Flush()
   259  }
   260  
   261  func (ctx *RequestContext) SetClientIPFunc(f ClientIP) {
   262  	ctx.clientIPFunc = f
   263  }
   264  
   265  func (ctx *RequestContext) SetFormValueFunc(f FormValueFunc) {
   266  	ctx.formValueFunc = f
   267  }
   268  
   269  func (ctx *RequestContext) SetBinder(binder binding.Binder) {
   270  	ctx.binder = binder
   271  }
   272  
   273  func (ctx *RequestContext) SetValidator(validator binding.StructValidator) {
   274  	ctx.validator = validator
   275  }
   276  
   277  func (ctx *RequestContext) GetTraceInfo() traceinfo.TraceInfo {
   278  	return ctx.traceInfo
   279  }
   280  
   281  func (ctx *RequestContext) SetTraceInfo(t traceinfo.TraceInfo) {
   282  	ctx.traceInfo = t
   283  }
   284  
   285  func (ctx *RequestContext) IsEnableTrace() bool {
   286  	return ctx.enableTrace
   287  }
   288  
   289  // SetEnableTrace sets whether enable trace.
   290  //
   291  // NOTE: biz handler must not modify this value, otherwise, it may panic.
   292  func (ctx *RequestContext) SetEnableTrace(enable bool) {
   293  	ctx.enableTrace = enable
   294  }
   295  
   296  // NewContext make a pure RequestContext without any http request/response information
   297  //
   298  // Set the Request filed before use it for handlers
   299  func NewContext(maxParams uint16) *RequestContext {
   300  	v := make(param.Params, 0, maxParams)
   301  	ctx := &RequestContext{Params: v, index: -1}
   302  	return ctx
   303  }
   304  
   305  // Loop fn for every k/v in Keys
   306  func (ctx *RequestContext) ForEachKey(fn func(k string, v interface{})) {
   307  	ctx.mu.RLock()
   308  	for key, val := range ctx.Keys {
   309  		fn(key, val)
   310  	}
   311  	ctx.mu.RUnlock()
   312  }
   313  
   314  func (ctx *RequestContext) SetConn(c network.Conn) {
   315  	ctx.conn = c
   316  }
   317  
   318  func (ctx *RequestContext) GetConn() network.Conn {
   319  	return ctx.conn
   320  }
   321  
   322  func (ctx *RequestContext) SetHijackHandler(h HijackHandler) {
   323  	ctx.hijackHandler = h
   324  }
   325  
   326  func (ctx *RequestContext) GetHijackHandler() HijackHandler {
   327  	return ctx.hijackHandler
   328  }
   329  
   330  func (ctx *RequestContext) GetReader() network.Reader {
   331  	return ctx.conn
   332  }
   333  
   334  func (ctx *RequestContext) GetWriter() network.Writer {
   335  	return ctx.conn
   336  }
   337  
   338  func (ctx *RequestContext) GetIndex() int8 {
   339  	return ctx.index
   340  }
   341  
   342  // SetIndex reset the handler's execution index
   343  // Disclaimer: You can loop yourself to deal with this, use wisely.
   344  func (ctx *RequestContext) SetIndex(index int8) {
   345  	ctx.index = index
   346  }
   347  
   348  type HandlerFunc func(c context.Context, ctx *RequestContext)
   349  
   350  // HandlersChain defines a HandlerFunc array.
   351  type HandlersChain []HandlerFunc
   352  
   353  type HandlerNameOperator interface {
   354  	SetHandlerName(handler HandlerFunc, name string)
   355  	GetHandlerName(handler HandlerFunc) string
   356  }
   357  
   358  func SetHandlerNameOperator(o HandlerNameOperator) {
   359  	inbuiltHandlerNameOperator = o
   360  }
   361  
   362  type inbuiltHandlerNameOperatorStruct struct {
   363  	handlerNames map[uintptr]string
   364  }
   365  
   366  func (o *inbuiltHandlerNameOperatorStruct) SetHandlerName(handler HandlerFunc, name string) {
   367  	o.handlerNames[getFuncAddr(handler)] = name
   368  }
   369  
   370  func (o *inbuiltHandlerNameOperatorStruct) GetHandlerName(handler HandlerFunc) string {
   371  	return o.handlerNames[getFuncAddr(handler)]
   372  }
   373  
   374  type concurrentHandlerNameOperatorStruct struct {
   375  	handlerNames map[uintptr]string
   376  	lock         sync.RWMutex
   377  }
   378  
   379  func (o *concurrentHandlerNameOperatorStruct) SetHandlerName(handler HandlerFunc, name string) {
   380  	o.lock.Lock()
   381  	defer o.lock.Unlock()
   382  	o.handlerNames[getFuncAddr(handler)] = name
   383  }
   384  
   385  func (o *concurrentHandlerNameOperatorStruct) GetHandlerName(handler HandlerFunc) string {
   386  	o.lock.RLock()
   387  	defer o.lock.RUnlock()
   388  	return o.handlerNames[getFuncAddr(handler)]
   389  }
   390  
   391  func SetConcurrentHandlerNameOperator() {
   392  	SetHandlerNameOperator(&concurrentHandlerNameOperatorStruct{handlerNames: map[uintptr]string{}})
   393  }
   394  
   395  func init() {
   396  	inbuiltHandlerNameOperator = &inbuiltHandlerNameOperatorStruct{handlerNames: map[uintptr]string{}}
   397  }
   398  
   399  var inbuiltHandlerNameOperator HandlerNameOperator
   400  
   401  func SetHandlerName(handler HandlerFunc, name string) {
   402  	inbuiltHandlerNameOperator.SetHandlerName(handler, name)
   403  }
   404  
   405  func GetHandlerName(handler HandlerFunc) string {
   406  	return inbuiltHandlerNameOperator.GetHandlerName(handler)
   407  }
   408  
   409  func getFuncAddr(v interface{}) uintptr {
   410  	return reflect.ValueOf(reflect.ValueOf(v)).Field(1).Pointer()
   411  }
   412  
   413  // HijackHandler must process the hijacked connection c.
   414  //
   415  // If KeepHijackedConns is disabled, which is by default,
   416  // the connection c is automatically closed after returning from HijackHandler.
   417  //
   418  // The connection c must not be used after returning from the handler, if KeepHijackedConns is disabled.
   419  //
   420  // When KeepHijackedConns enabled, hertz will not Close() the connection,
   421  // you must do it when you need it. You must not use c in any way after calling Close().
   422  //
   423  // network.Connection provide two options of io: net.Conn and zero-copy read/write
   424  type HijackHandler func(c network.Conn)
   425  
   426  // Hijack registers the given handler for connection hijacking.
   427  //
   428  // The handler is called after returning from RequestHandler
   429  // and sending http response. The current connection is passed
   430  // to the handler. The connection is automatically closed after
   431  // returning from the handler.
   432  //
   433  // The server skips calling the handler in the following cases:
   434  //
   435  //   - 'Connection: close' header exists in either request or response.
   436  //   - Unexpected error during response writing to the connection.
   437  //
   438  // The server stops processing requests from hijacked connections.
   439  //
   440  // Server limits such as Concurrency, ReadTimeout, WriteTimeout, etc.
   441  // aren't applied to hijacked connections.
   442  //
   443  // The handler must not retain references to ctx members.
   444  //
   445  // Arbitrary 'Connection: Upgrade' protocols may be implemented
   446  // with HijackHandler. For instance,
   447  //
   448  //   - WebSocket ( https://en.wikipedia.org/wiki/WebSocket )
   449  //   - HTTP/2.0 ( https://en.wikipedia.org/wiki/HTTP/2 )
   450  func (ctx *RequestContext) Hijack(handler HijackHandler) {
   451  	ctx.hijackHandler = handler
   452  }
   453  
   454  // Last returns the last handler of the handler chain.
   455  //
   456  // Generally speaking, the last handler is the main handler.
   457  func (c HandlersChain) Last() HandlerFunc {
   458  	if length := len(c); length > 0 {
   459  		return c[length-1]
   460  	}
   461  	return nil
   462  }
   463  
   464  func (ctx *RequestContext) Finished() <-chan struct{} {
   465  	ctx.finishedMu.Lock()
   466  	if ctx.finished == nil {
   467  		ctx.finished = make(chan struct{})
   468  	}
   469  	ch := ctx.finished
   470  	ctx.finishedMu.Unlock()
   471  	return ch
   472  }
   473  
   474  // GetRequest returns a copy of Request.
   475  func (ctx *RequestContext) GetRequest() (dst *protocol.Request) {
   476  	dst = &protocol.Request{}
   477  	ctx.Request.CopyTo(dst)
   478  	return
   479  }
   480  
   481  // GetResponse returns a copy of Response.
   482  func (ctx *RequestContext) GetResponse() (dst *protocol.Response) {
   483  	dst = &protocol.Response{}
   484  	ctx.Response.CopyTo(dst)
   485  	return
   486  }
   487  
   488  // Value returns the value associated with this context for key, or nil
   489  // if no value is associated with key. Successive calls to Value with
   490  // the same key returns the same result.
   491  //
   492  // In case the Key is reset after response, Value() return nil if ctx.Key is nil.
   493  func (ctx *RequestContext) Value(key interface{}) interface{} {
   494  	// this ctx has been reset, return nil.
   495  	if ctx.Keys == nil {
   496  		return nil
   497  	}
   498  	if keyString, ok := key.(string); ok {
   499  		val, _ := ctx.Get(keyString)
   500  		return val
   501  	}
   502  	return nil
   503  }
   504  
   505  // Hijacked returns true after Hijack is called.
   506  func (ctx *RequestContext) Hijacked() bool {
   507  	return ctx.hijackHandler != nil
   508  }
   509  
   510  // SetBodyStream sets response body stream and, optionally body size.
   511  //
   512  // bodyStream.Close() is called after finishing reading all body data
   513  // if it implements io.Closer.
   514  //
   515  // If bodySize is >= 0, then bodySize bytes must be provided by bodyStream
   516  // before returning io.EOF.
   517  //
   518  // If bodySize < 0, then bodyStream is read until io.EOF.
   519  //
   520  // See also SetBodyStreamWriter.
   521  func (ctx *RequestContext) SetBodyStream(bodyStream io.Reader, bodySize int) {
   522  	ctx.Response.SetBodyStream(bodyStream, bodySize)
   523  }
   524  
   525  // Host returns requested host.
   526  //
   527  // The host is valid until returning from RequestHandler.
   528  func (ctx *RequestContext) Host() []byte {
   529  	return ctx.URI().Host()
   530  }
   531  
   532  // RemoteAddr returns client address for the given request.
   533  //
   534  // If address is nil, it will return zeroTCPAddr.
   535  func (ctx *RequestContext) RemoteAddr() net.Addr {
   536  	if ctx.conn == nil {
   537  		return zeroTCPAddr
   538  	}
   539  	addr := ctx.conn.RemoteAddr()
   540  	if addr == nil {
   541  		return zeroTCPAddr
   542  	}
   543  	return addr
   544  }
   545  
   546  // WriteString appends s to response body.
   547  func (ctx *RequestContext) WriteString(s string) (int, error) {
   548  	ctx.Response.AppendBodyString(s)
   549  	return len(s), nil
   550  }
   551  
   552  // SetContentType sets response Content-Type.
   553  func (ctx *RequestContext) SetContentType(contentType string) {
   554  	ctx.Response.Header.SetContentType(contentType)
   555  }
   556  
   557  // Path returns requested path.
   558  //
   559  // The path is valid until returning from RequestHandler.
   560  func (ctx *RequestContext) Path() []byte {
   561  	return ctx.URI().Path()
   562  }
   563  
   564  // NotModified resets response and sets '304 Not Modified' response status code.
   565  func (ctx *RequestContext) NotModified() {
   566  	ctx.Response.Reset()
   567  	ctx.SetStatusCode(consts.StatusNotModified)
   568  }
   569  
   570  // IfModifiedSince returns true if lastModified exceeds 'If-Modified-Since'
   571  // value from the request header.
   572  //
   573  // The function returns true also 'If-Modified-Since' request header is missing.
   574  func (ctx *RequestContext) IfModifiedSince(lastModified time.Time) bool {
   575  	ifModStr := ctx.Request.Header.PeekIfModifiedSinceBytes()
   576  	if len(ifModStr) == 0 {
   577  		return true
   578  	}
   579  	ifMod, err := bytesconv.ParseHTTPDate(ifModStr)
   580  	if err != nil {
   581  		return true
   582  	}
   583  	lastModified = lastModified.Truncate(time.Second)
   584  	return ifMod.Before(lastModified)
   585  }
   586  
   587  // URI returns requested uri.
   588  //
   589  // The uri is valid until returning from RequestHandler.
   590  func (ctx *RequestContext) URI() *protocol.URI {
   591  	return ctx.Request.URI()
   592  }
   593  
   594  func (ctx *RequestContext) String(code int, format string, values ...interface{}) {
   595  	ctx.Render(code, render.String{Format: format, Data: values})
   596  }
   597  
   598  // FullPath returns a matched route full path. For not found routes
   599  // returns an empty string.
   600  //
   601  //	router.GET("/user/:id", func(c context.Context, ctx *app.RequestContext) {
   602  //	    ctx.FullPath() == "/user/:id" // true
   603  //	})
   604  func (ctx *RequestContext) FullPath() string {
   605  	return ctx.fullPath
   606  }
   607  
   608  func (ctx *RequestContext) SetFullPath(p string) {
   609  	ctx.fullPath = p
   610  }
   611  
   612  // SetStatusCode sets response status code.
   613  func (ctx *RequestContext) SetStatusCode(statusCode int) {
   614  	ctx.Response.SetStatusCode(statusCode)
   615  }
   616  
   617  // Write writes p into response body.
   618  func (ctx *RequestContext) Write(p []byte) (int, error) {
   619  	ctx.Response.AppendBody(p)
   620  	return len(p), nil
   621  }
   622  
   623  // File writes the specified file into the body stream in an efficient way.
   624  func (ctx *RequestContext) File(filepath string) {
   625  	ServeFile(ctx, filepath)
   626  }
   627  
   628  func (ctx *RequestContext) FileFromFS(filepath string, fs *FS) {
   629  	defer func(old string) {
   630  		ctx.Request.URI().SetPath(old)
   631  	}(string(ctx.Request.URI().Path()))
   632  
   633  	ctx.Request.URI().SetPath(filepath)
   634  
   635  	fs.NewRequestHandler()(context.Background(), ctx)
   636  }
   637  
   638  // FileAttachment use an efficient way to write the file to body stream.
   639  //
   640  // When client download the file, it will rename the file as filename
   641  func (ctx *RequestContext) FileAttachment(filepath, filename string) {
   642  	ctx.Response.Header.Set("content-disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
   643  	ServeFile(ctx, filepath)
   644  }
   645  
   646  // SetBodyString sets response body to the given value.
   647  func (ctx *RequestContext) SetBodyString(body string) {
   648  	ctx.Response.SetBodyString(body)
   649  }
   650  
   651  // SetContentTypeBytes sets response Content-Type.
   652  //
   653  // It is safe modifying contentType buffer after function return.
   654  func (ctx *RequestContext) SetContentTypeBytes(contentType []byte) {
   655  	ctx.Response.Header.SetContentTypeBytes(contentType)
   656  }
   657  
   658  // FormFile returns the first file for the provided form key.
   659  func (ctx *RequestContext) FormFile(name string) (*multipart.FileHeader, error) {
   660  	return ctx.Request.FormFile(name)
   661  }
   662  
   663  // FormValue returns form value associated with the given key.
   664  //
   665  // The value is searched in the following places:
   666  //
   667  //   - Query string.
   668  //   - POST or PUT body.
   669  //
   670  // There are more fine-grained methods for obtaining form values:
   671  //
   672  //   - QueryArgs for obtaining values from query string.
   673  //   - PostArgs for obtaining values from POST or PUT body.
   674  //   - MultipartForm for obtaining values from multipart form.
   675  //   - FormFile for obtaining uploaded files.
   676  //
   677  // The returned value is valid until returning from RequestHandler.
   678  // Use engine.SetCustomFormValueFunc to change action of FormValue.
   679  func (ctx *RequestContext) FormValue(key string) []byte {
   680  	if ctx.formValueFunc != nil {
   681  		return ctx.formValueFunc(ctx, key)
   682  	}
   683  	return defaultFormValue(ctx, key)
   684  }
   685  
   686  func (ctx *RequestContext) multipartFormValue(key string) (string, bool) {
   687  	mf, err := ctx.MultipartForm()
   688  	if err == nil && mf.Value != nil {
   689  		vv := mf.Value[key]
   690  		if len(vv) > 0 {
   691  			return vv[0], true
   692  		}
   693  	}
   694  	return "", false
   695  }
   696  
   697  func (ctx *RequestContext) multipartFormValueArray(key string) ([]string, bool) {
   698  	mf, err := ctx.MultipartForm()
   699  	if err == nil && mf.Value != nil {
   700  		vv := mf.Value[key]
   701  		if len(vv) > 0 {
   702  			return vv, true
   703  		}
   704  	}
   705  	return nil, false
   706  }
   707  
   708  func (ctx *RequestContext) RequestBodyStream() io.Reader {
   709  	return ctx.Request.BodyStream()
   710  }
   711  
   712  // MultipartForm returns request's multipart form.
   713  //
   714  // Returns errNoMultipartForm if request's content-type
   715  // isn't 'multipart/form-data'.
   716  //
   717  // All uploaded temporary files are automatically deleted after
   718  // returning from RequestHandler. Either move or copy uploaded files
   719  // into new place if you want retaining them.
   720  //
   721  // Use SaveMultipartFile function for permanently saving uploaded file.
   722  //
   723  // The returned form is valid until returning from RequestHandler.
   724  //
   725  // See also FormFile and FormValue.
   726  func (ctx *RequestContext) MultipartForm() (*multipart.Form, error) {
   727  	return ctx.Request.MultipartForm()
   728  }
   729  
   730  // SaveUploadedFile uploads the form file to specific dst.
   731  func (ctx *RequestContext) SaveUploadedFile(file *multipart.FileHeader, dst string) error {
   732  	src, err := file.Open()
   733  	if err != nil {
   734  		return err
   735  	}
   736  	defer src.Close()
   737  
   738  	out, err := os.Create(dst)
   739  	if err != nil {
   740  		return err
   741  	}
   742  	defer out.Close()
   743  
   744  	_, err = io.Copy(out, src)
   745  	return err
   746  }
   747  
   748  // SetConnectionClose sets 'Connection: close' response header.
   749  func (ctx *RequestContext) SetConnectionClose() {
   750  	ctx.Response.SetConnectionClose()
   751  }
   752  
   753  // IsGet returns true if request method is GET.
   754  func (ctx *RequestContext) IsGet() bool {
   755  	return ctx.Request.Header.IsGet()
   756  }
   757  
   758  // IsHead returns true if request method is HEAD.
   759  func (ctx *RequestContext) IsHead() bool {
   760  	return ctx.Request.Header.IsHead()
   761  }
   762  
   763  // IsPost returns true if request method is POST.
   764  func (ctx *RequestContext) IsPost() bool {
   765  	return ctx.Request.Header.IsPost()
   766  }
   767  
   768  // Method return request method.
   769  //
   770  // Returned value is valid until returning from RequestHandler.
   771  func (ctx *RequestContext) Method() []byte {
   772  	return ctx.Request.Header.Method()
   773  }
   774  
   775  // NotFound resets response and sets '404 Not Found' response status code.
   776  func (ctx *RequestContext) NotFound() {
   777  	ctx.Response.Reset()
   778  	ctx.SetStatusCode(consts.StatusNotFound)
   779  	ctx.SetBodyString(consts.StatusMessage(consts.StatusNotFound))
   780  }
   781  
   782  func (ctx *RequestContext) redirect(uri []byte, statusCode int) {
   783  	ctx.Response.Header.SetCanonical(bytestr.StrLocation, uri)
   784  	statusCode = getRedirectStatusCode(statusCode)
   785  	ctx.Response.SetStatusCode(statusCode)
   786  }
   787  
   788  func getRedirectStatusCode(statusCode int) int {
   789  	if statusCode == consts.StatusMovedPermanently || statusCode == consts.StatusFound ||
   790  		statusCode == consts.StatusSeeOther || statusCode == consts.StatusTemporaryRedirect ||
   791  		statusCode == consts.StatusPermanentRedirect {
   792  		return statusCode
   793  	}
   794  	return consts.StatusFound
   795  }
   796  
   797  // Copy returns a copy of the current context that can be safely used outside
   798  // the request's scope.
   799  //
   800  // NOTE: If you want to pass requestContext to a goroutine, call this method
   801  // to get a copy of requestContext.
   802  func (ctx *RequestContext) Copy() *RequestContext {
   803  	cp := &RequestContext{
   804  		conn:   ctx.conn,
   805  		Params: ctx.Params,
   806  	}
   807  	ctx.Request.CopyTo(&cp.Request)
   808  	ctx.Response.CopyTo(&cp.Response)
   809  	cp.index = rConsts.AbortIndex
   810  	cp.handlers = nil
   811  	cp.Keys = map[string]interface{}{}
   812  	ctx.mu.RLock()
   813  	for k, v := range ctx.Keys {
   814  		cp.Keys[k] = v
   815  	}
   816  	ctx.mu.RUnlock()
   817  	paramCopy := make([]param.Param, len(cp.Params))
   818  	copy(paramCopy, cp.Params)
   819  	cp.Params = paramCopy
   820  	cp.fullPath = ctx.fullPath
   821  	cp.clientIPFunc = ctx.clientIPFunc
   822  	cp.formValueFunc = ctx.formValueFunc
   823  	cp.binder = ctx.binder
   824  	cp.validator = ctx.validator
   825  	return cp
   826  }
   827  
   828  // Next should be used only inside middleware.
   829  // It executes the pending handlers in the chain inside the calling handler.
   830  func (ctx *RequestContext) Next(c context.Context) {
   831  	ctx.index++
   832  	for ctx.index < int8(len(ctx.handlers)) {
   833  		ctx.handlers[ctx.index](c, ctx)
   834  		ctx.index++
   835  	}
   836  }
   837  
   838  // Handler returns the main handler.
   839  func (ctx *RequestContext) Handler() HandlerFunc {
   840  	return ctx.handlers.Last()
   841  }
   842  
   843  // Handlers returns the handler chain.
   844  func (ctx *RequestContext) Handlers() HandlersChain {
   845  	return ctx.handlers
   846  }
   847  
   848  func (ctx *RequestContext) SetHandlers(hc HandlersChain) {
   849  	ctx.handlers = hc
   850  }
   851  
   852  // HandlerName returns the main handler's name.
   853  //
   854  // For example if the handler is "handleGetUsers()", this function will return "main.handleGetUsers".
   855  func (ctx *RequestContext) HandlerName() string {
   856  	return utils.NameOfFunction(ctx.handlers.Last())
   857  }
   858  
   859  func (ctx *RequestContext) ResetWithoutConn() {
   860  	ctx.Params = ctx.Params[0:0]
   861  	ctx.Errors = ctx.Errors[0:0]
   862  	ctx.handlers = nil
   863  	ctx.index = -1
   864  	ctx.fullPath = ""
   865  	ctx.Keys = nil
   866  
   867  	if ctx.finished != nil {
   868  		close(ctx.finished)
   869  		ctx.finished = nil
   870  	}
   871  
   872  	ctx.Request.ResetWithoutConn()
   873  	ctx.Response.Reset()
   874  	if ctx.IsEnableTrace() {
   875  		ctx.traceInfo.Reset()
   876  	}
   877  }
   878  
   879  // Reset resets requestContext.
   880  //
   881  // NOTE: It is an internal function. You should not use it.
   882  func (ctx *RequestContext) Reset() {
   883  	ctx.ResetWithoutConn()
   884  	ctx.conn = nil
   885  }
   886  
   887  // Redirect returns an HTTP redirect to the specific location.
   888  // Note that this will not stop the current handler.
   889  // In other words, even if Redirect() is called, the remaining handlers will still be executed and cause unexpected result.
   890  // So it should call Abort to ensure the remaining handlers of this request will not be called.
   891  //
   892  //	ctx.Abort()
   893  //	return
   894  func (ctx *RequestContext) Redirect(statusCode int, uri []byte) {
   895  	ctx.redirect(uri, statusCode)
   896  }
   897  
   898  // Header is an intelligent shortcut for ctx.Response.Header.Set(key, value).
   899  // It writes a header in the response.
   900  // If value == "", this method removes the header `ctx.Response.Header.Del(key)`.
   901  func (ctx *RequestContext) Header(key, value string) {
   902  	if value == "" {
   903  		ctx.Response.Header.Del(key)
   904  		return
   905  	}
   906  	ctx.Response.Header.Set(key, value)
   907  }
   908  
   909  // Set is used to store a new key/value pair exclusively for this context.
   910  // It also lazy initializes  c.Keys if it was not used previously.
   911  func (ctx *RequestContext) Set(key string, value interface{}) {
   912  	ctx.mu.Lock()
   913  	if ctx.Keys == nil {
   914  		ctx.Keys = make(map[string]interface{})
   915  	}
   916  
   917  	ctx.Keys[key] = value
   918  	ctx.mu.Unlock()
   919  }
   920  
   921  // Get returns the value for the given key, ie: (value, true).
   922  // If the value does not exist it returns (nil, false)
   923  func (ctx *RequestContext) Get(key string) (value interface{}, exists bool) {
   924  	ctx.mu.RLock()
   925  	value, exists = ctx.Keys[key]
   926  	ctx.mu.RUnlock()
   927  	return
   928  }
   929  
   930  // MustGet returns the value for the given key if it exists, otherwise it panics.
   931  func (ctx *RequestContext) MustGet(key string) interface{} {
   932  	if value, exists := ctx.Get(key); exists {
   933  		return value
   934  	}
   935  	panic("Key \"" + key + "\" does not exist")
   936  }
   937  
   938  // GetString returns the value associated with the key as a string. Return "" when type is error.
   939  func (ctx *RequestContext) GetString(key string) (s string) {
   940  	if val, ok := ctx.Get(key); ok && val != nil {
   941  		s, _ = val.(string)
   942  	}
   943  	return
   944  }
   945  
   946  // GetBool returns the value associated with the key as a boolean. Return false when type is error.
   947  func (ctx *RequestContext) GetBool(key string) (b bool) {
   948  	if val, ok := ctx.Get(key); ok && val != nil {
   949  		b, _ = val.(bool)
   950  	}
   951  	return
   952  }
   953  
   954  // GetInt returns the value associated with the key as an integer. Return 0 when type is error.
   955  func (ctx *RequestContext) GetInt(key string) (i int) {
   956  	if val, ok := ctx.Get(key); ok && val != nil {
   957  		i, _ = val.(int)
   958  	}
   959  	return
   960  }
   961  
   962  // GetInt32 returns the value associated with the key as an integer. Return int32(0) when type is error.
   963  func (ctx *RequestContext) GetInt32(key string) (i32 int32) {
   964  	if val, ok := ctx.Get(key); ok && val != nil {
   965  		i32, _ = val.(int32)
   966  	}
   967  	return
   968  }
   969  
   970  // GetInt64 returns the value associated with the key as an integer. Return int64(0) when type is error.
   971  func (ctx *RequestContext) GetInt64(key string) (i64 int64) {
   972  	if val, ok := ctx.Get(key); ok && val != nil {
   973  		i64, _ = val.(int64)
   974  	}
   975  	return
   976  }
   977  
   978  // GetUint returns the value associated with the key as an unsigned integer. Return uint(0) when type is error.
   979  func (ctx *RequestContext) GetUint(key string) (ui uint) {
   980  	if val, ok := ctx.Get(key); ok && val != nil {
   981  		ui, _ = val.(uint)
   982  	}
   983  	return
   984  }
   985  
   986  // GetUint32 returns the value associated with the key as an unsigned integer. Return uint32(0) when type is error.
   987  func (ctx *RequestContext) GetUint32(key string) (ui32 uint32) {
   988  	if val, ok := ctx.Get(key); ok && val != nil {
   989  		ui32, _ = val.(uint32)
   990  	}
   991  	return
   992  }
   993  
   994  // GetUint64 returns the value associated with the key as an unsigned integer. Return uint64(0) when type is error.
   995  func (ctx *RequestContext) GetUint64(key string) (ui64 uint64) {
   996  	if val, ok := ctx.Get(key); ok && val != nil {
   997  		ui64, _ = val.(uint64)
   998  	}
   999  	return
  1000  }
  1001  
  1002  // GetFloat32 returns the value associated with the key as a float32. Return float32(0.0) when type is error.
  1003  func (ctx *RequestContext) GetFloat32(key string) (f32 float32) {
  1004  	if val, ok := ctx.Get(key); ok && val != nil {
  1005  		f32, _ = val.(float32)
  1006  	}
  1007  	return
  1008  }
  1009  
  1010  // GetFloat64 returns the value associated with the key as a float64. Return 0.0 when type is error.
  1011  func (ctx *RequestContext) GetFloat64(key string) (f64 float64) {
  1012  	if val, ok := ctx.Get(key); ok && val != nil {
  1013  		f64, _ = val.(float64)
  1014  	}
  1015  	return
  1016  }
  1017  
  1018  // GetTime returns the value associated with the key as time. Return time.Time{} when type is error.
  1019  func (ctx *RequestContext) GetTime(key string) (t time.Time) {
  1020  	if val, ok := ctx.Get(key); ok && val != nil {
  1021  		t, _ = val.(time.Time)
  1022  	}
  1023  	return
  1024  }
  1025  
  1026  // GetDuration returns the value associated with the key as a duration. Return time.Duration(0) when type is error.
  1027  func (ctx *RequestContext) GetDuration(key string) (d time.Duration) {
  1028  	if val, ok := ctx.Get(key); ok && val != nil {
  1029  		d, _ = val.(time.Duration)
  1030  	}
  1031  	return
  1032  }
  1033  
  1034  // GetStringSlice returns the value associated with the key as a slice of strings.
  1035  //
  1036  // Return []string(nil) when type is error.
  1037  func (ctx *RequestContext) GetStringSlice(key string) (ss []string) {
  1038  	if val, ok := ctx.Get(key); ok && val != nil {
  1039  		ss, _ = val.([]string)
  1040  	}
  1041  	return
  1042  }
  1043  
  1044  // GetStringMap returns the value associated with the key as a map of interfaces.
  1045  //
  1046  // Return map[string]interface{}(nil) when type is error.
  1047  func (ctx *RequestContext) GetStringMap(key string) (sm map[string]interface{}) {
  1048  	if val, ok := ctx.Get(key); ok && val != nil {
  1049  		sm, _ = val.(map[string]interface{})
  1050  	}
  1051  	return
  1052  }
  1053  
  1054  // GetStringMapString returns the value associated with the key as a map of strings.
  1055  //
  1056  // Return map[string]string(nil) when type is error.
  1057  func (ctx *RequestContext) GetStringMapString(key string) (sms map[string]string) {
  1058  	if val, ok := ctx.Get(key); ok && val != nil {
  1059  		sms, _ = val.(map[string]string)
  1060  	}
  1061  	return
  1062  }
  1063  
  1064  // GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings.
  1065  //
  1066  // Return map[string][]string(nil) when type is error.
  1067  func (ctx *RequestContext) GetStringMapStringSlice(key string) (smss map[string][]string) {
  1068  	if val, ok := ctx.Get(key); ok && val != nil {
  1069  		smss, _ = val.(map[string][]string)
  1070  	}
  1071  	return
  1072  }
  1073  
  1074  // Param returns the value of the URL param.
  1075  // It is a shortcut for c.Params.ByName(key)
  1076  //
  1077  //	router.GET("/user/:id", func(c context.Context, ctx *app.RequestContext) {
  1078  //	    // a GET request to /user/john
  1079  //	    id := ctx.Param("id") // id == "john"
  1080  //	})
  1081  func (ctx *RequestContext) Param(key string) string {
  1082  	return ctx.Params.ByName(key)
  1083  }
  1084  
  1085  // Abort prevents pending handlers from being called.
  1086  //
  1087  // Note that this will not stop the current handler.
  1088  // Let's say you have an authorization middleware that validates that the current request is authorized.
  1089  // If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers
  1090  // for this request are not called.
  1091  func (ctx *RequestContext) Abort() {
  1092  	ctx.index = rConsts.AbortIndex
  1093  }
  1094  
  1095  // AbortWithStatus calls `Abort()` and writes the headers with the specified status code.
  1096  //
  1097  // For example, a failed attempt to authenticate a request could use: context.AbortWithStatus(401).
  1098  func (ctx *RequestContext) AbortWithStatus(code int) {
  1099  	ctx.SetStatusCode(code)
  1100  	ctx.Abort()
  1101  }
  1102  
  1103  // AbortWithMsg sets response status code to the given value and sets response body
  1104  // to the given message.
  1105  //
  1106  // Warning: this will reset the response headers and body already set!
  1107  func (ctx *RequestContext) AbortWithMsg(msg string, statusCode int) {
  1108  	ctx.Response.Reset()
  1109  	ctx.SetStatusCode(statusCode)
  1110  	ctx.SetContentTypeBytes(bytestr.DefaultContentType)
  1111  	ctx.SetBodyString(msg)
  1112  	ctx.Abort()
  1113  }
  1114  
  1115  // AbortWithStatusJSON calls `Abort()` and then `JSON` internally.
  1116  //
  1117  // This method stops the chain, writes the status code and return a JSON body.
  1118  // It also sets the Content-Type as "application/json".
  1119  func (ctx *RequestContext) AbortWithStatusJSON(code int, jsonObj interface{}) {
  1120  	ctx.Abort()
  1121  	ctx.JSON(code, jsonObj)
  1122  }
  1123  
  1124  // Render writes the response headers and calls render.Render to render data.
  1125  func (ctx *RequestContext) Render(code int, r render.Render) {
  1126  	ctx.SetStatusCode(code)
  1127  
  1128  	if !bodyAllowedForStatus(code) {
  1129  		r.WriteContentType(&ctx.Response)
  1130  		return
  1131  	}
  1132  
  1133  	if err := r.Render(&ctx.Response); err != nil {
  1134  		panic(err)
  1135  	}
  1136  }
  1137  
  1138  // ProtoBuf serializes the given struct as ProtoBuf into the response body.
  1139  func (ctx *RequestContext) ProtoBuf(code int, obj interface{}) {
  1140  	ctx.Render(code, render.ProtoBuf{Data: obj})
  1141  }
  1142  
  1143  // JSON serializes the given struct as JSON into the response body.
  1144  //
  1145  // It also sets the Content-Type as "application/json".
  1146  func (ctx *RequestContext) JSON(code int, obj interface{}) {
  1147  	ctx.Render(code, render.JSONRender{Data: obj})
  1148  }
  1149  
  1150  // PureJSON serializes the given struct as JSON into the response body.
  1151  // PureJSON, unlike JSON, does not replace special html characters with their unicode entities.
  1152  func (ctx *RequestContext) PureJSON(code int, obj interface{}) {
  1153  	ctx.Render(code, render.PureJSON{Data: obj})
  1154  }
  1155  
  1156  // IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body.
  1157  // It also sets the Content-Type as "application/json".
  1158  func (ctx *RequestContext) IndentedJSON(code int, obj interface{}) {
  1159  	ctx.Render(code, render.IndentedJSON{Data: obj})
  1160  }
  1161  
  1162  // HTML renders the HTTP template specified by its file name.
  1163  //
  1164  // It also updates the HTTP code and sets the Content-Type as "text/html".
  1165  // See http://golang.org/doc/articles/wiki/
  1166  func (ctx *RequestContext) HTML(code int, name string, obj interface{}) {
  1167  	instance := ctx.HTMLRender.Instance(name, obj)
  1168  	ctx.Render(code, instance)
  1169  }
  1170  
  1171  // Data writes some data into the body stream and updates the HTTP code.
  1172  func (ctx *RequestContext) Data(code int, contentType string, data []byte) {
  1173  	ctx.Render(code, render.Data{
  1174  		ContentType: contentType,
  1175  		Data:        data,
  1176  	})
  1177  }
  1178  
  1179  // XML serializes the given struct as XML into the response body.
  1180  //
  1181  // It also sets the Content-Type as "application/xml".
  1182  func (ctx *RequestContext) XML(code int, obj interface{}) {
  1183  	ctx.Render(code, render.XML{Data: obj})
  1184  }
  1185  
  1186  // AbortWithError calls `AbortWithStatus()` and `Error()` internally.
  1187  //
  1188  // This method stops the chain, writes the status code and pushes the specified error to `c.Errors`.
  1189  // See RequestContext.Error() for more details.
  1190  func (ctx *RequestContext) AbortWithError(code int, err error) *errors.Error {
  1191  	ctx.AbortWithStatus(code)
  1192  	return ctx.Error(err)
  1193  }
  1194  
  1195  // IsAborted returns true if the current context has aborted.
  1196  func (ctx *RequestContext) IsAborted() bool {
  1197  	return ctx.index >= rConsts.AbortIndex
  1198  }
  1199  
  1200  // Error attaches an error to the current context. The error is pushed to a list of errors.
  1201  //
  1202  // It's a good idea to call Error for each error that occurred during the resolution of a request.
  1203  // A middleware can be used to collect all the errors and push them to a database together,
  1204  // print a log, or append it in the HTTP response.
  1205  // Error will panic if err is nil.
  1206  func (ctx *RequestContext) Error(err error) *errors.Error {
  1207  	if err == nil {
  1208  		panic("err is nil")
  1209  	}
  1210  
  1211  	parsedError, ok := err.(*errors.Error)
  1212  	if !ok {
  1213  		parsedError = &errors.Error{
  1214  			Err:  err,
  1215  			Type: errors.ErrorTypePrivate,
  1216  		}
  1217  	}
  1218  
  1219  	ctx.Errors = append(ctx.Errors, parsedError)
  1220  	return parsedError
  1221  }
  1222  
  1223  // ContentType returns the Content-Type header of the request.
  1224  func (ctx *RequestContext) ContentType() []byte {
  1225  	return ctx.Request.Header.ContentType()
  1226  }
  1227  
  1228  // Cookie returns the value of the request cookie key.
  1229  func (ctx *RequestContext) Cookie(key string) []byte {
  1230  	return ctx.Request.Header.Cookie(key)
  1231  }
  1232  
  1233  // SetCookie adds a Set-Cookie header to the Response's headers.
  1234  //
  1235  //	Parameter introduce:
  1236  //	name and value is used to set cookie's name and value, eg. Set-Cookie: name=value
  1237  //	maxAge is use to set cookie's expiry date, eg. Set-Cookie: name=value; max-age=1
  1238  //	path and domain is used to set the scope of a cookie, eg. Set-Cookie: name=value;domain=localhost; path=/;
  1239  //	secure and httpOnly is used to sent cookies securely; eg. Set-Cookie: name=value;HttpOnly; secure;
  1240  //	sameSite let servers specify whether/when cookies are sent with cross-site requests; eg. Set-Cookie: name=value;HttpOnly; secure; SameSite=Lax;
  1241  //
  1242  //	For example:
  1243  //	1. ctx.SetCookie("user", "hertz", 1, "/", "localhost",protocol.CookieSameSiteLaxMode, true, true)
  1244  //	add response header --->  Set-Cookie: user=hertz; max-age=1; domain=localhost; path=/; HttpOnly; secure; SameSite=Lax;
  1245  //	2. ctx.SetCookie("user", "hertz", 10, "/", "localhost",protocol.CookieSameSiteLaxMode, false, false)
  1246  //	add response header --->  Set-Cookie: user=hertz; max-age=10; domain=localhost; path=/; SameSite=Lax;
  1247  //	3. ctx.SetCookie("", "hertz", 10, "/", "localhost",protocol.CookieSameSiteLaxMode, false, false)
  1248  //	add response header --->  Set-Cookie: hertz; max-age=10; domain=localhost; path=/; SameSite=Lax;
  1249  //	4. ctx.SetCookie("user", "", 10, "/", "localhost",protocol.CookieSameSiteLaxMode, false, false)
  1250  //	add response header --->  Set-Cookie: user=; max-age=10; domain=localhost; path=/; SameSite=Lax;
  1251  func (ctx *RequestContext) SetCookie(name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly bool) {
  1252  	ctx.setCookie(name, value, maxAge, path, domain, sameSite, secure, httpOnly, false)
  1253  }
  1254  
  1255  func (ctx *RequestContext) setCookie(name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly, partitioned bool) {
  1256  	if path == "" {
  1257  		path = "/"
  1258  	}
  1259  	cookie := protocol.AcquireCookie()
  1260  	defer protocol.ReleaseCookie(cookie)
  1261  	cookie.SetKey(name)
  1262  	cookie.SetValue(url.QueryEscape(value))
  1263  	cookie.SetMaxAge(maxAge)
  1264  	cookie.SetPath(path)
  1265  	cookie.SetDomain(domain)
  1266  	cookie.SetSecure(secure)
  1267  	cookie.SetHTTPOnly(httpOnly)
  1268  	cookie.SetSameSite(sameSite)
  1269  	cookie.SetPartitioned(partitioned)
  1270  	ctx.Response.Header.SetCookie(cookie)
  1271  }
  1272  
  1273  // SetPartitionedCookie adds a partitioned cookie to the Response's headers.
  1274  // Use protocol.CookieSameSiteNoneMode for cross-site cookies to work.
  1275  //
  1276  // Usage: ctx.SetPartitionedCookie("user", "name", 10, "/", "localhost", protocol.CookieSameSiteNoneMode, true, true)
  1277  //
  1278  // This adds the response header: Set-Cookie: user=name; Max-Age=10; Domain=localhost; Path=/; HttpOnly; Secure; SameSite=None; Partitioned
  1279  func (ctx *RequestContext) SetPartitionedCookie(name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly bool) {
  1280  	ctx.setCookie(name, value, maxAge, path, domain, sameSite, secure, httpOnly, true)
  1281  }
  1282  
  1283  // UserAgent returns the value of the request user_agent.
  1284  func (ctx *RequestContext) UserAgent() []byte {
  1285  	return ctx.Request.Header.UserAgent()
  1286  }
  1287  
  1288  // Status sets the HTTP response code.
  1289  func (ctx *RequestContext) Status(code int) {
  1290  	ctx.SetStatusCode(code)
  1291  }
  1292  
  1293  // GetHeader returns value from request headers.
  1294  func (ctx *RequestContext) GetHeader(key string) []byte {
  1295  	return ctx.Request.Header.Peek(key)
  1296  }
  1297  
  1298  // GetRawData returns body data.
  1299  func (ctx *RequestContext) GetRawData() []byte {
  1300  	return ctx.Request.Body()
  1301  }
  1302  
  1303  // Body returns body data
  1304  func (ctx *RequestContext) Body() ([]byte, error) {
  1305  	return ctx.Request.BodyE()
  1306  }
  1307  
  1308  // ClientIP tries to parse the headers in [X-Real-Ip, X-Forwarded-For].
  1309  // It calls RemoteIP() under the hood. If it cannot satisfy the requirements,
  1310  // use engine.SetClientIPFunc to inject your own implementation.
  1311  func (ctx *RequestContext) ClientIP() string {
  1312  	if ctx.clientIPFunc != nil {
  1313  		return ctx.clientIPFunc(ctx)
  1314  	}
  1315  	return defaultClientIP(ctx)
  1316  }
  1317  
  1318  // QueryArgs returns query arguments from RequestURI.
  1319  //
  1320  // It doesn't return POST'ed arguments - use PostArgs() for this.
  1321  // Returned arguments are valid until returning from RequestHandler.
  1322  // See also PostArgs, FormValue and FormFile.
  1323  func (ctx *RequestContext) QueryArgs() *protocol.Args {
  1324  	return ctx.URI().QueryArgs()
  1325  }
  1326  
  1327  // PostArgs returns POST arguments.
  1328  //
  1329  // It doesn't return query arguments from RequestURI - use QueryArgs for this.
  1330  // Returned arguments are valid until returning from RequestHandler.
  1331  // See also QueryArgs, FormValue and FormFile.
  1332  func (ctx *RequestContext) PostArgs() *protocol.Args {
  1333  	return ctx.Request.PostArgs()
  1334  }
  1335  
  1336  // Query returns the keyed url query value if it exists, otherwise it returns an empty string `("")`.
  1337  //
  1338  // For example:
  1339  //
  1340  //	    GET /path?id=1234&name=Manu&value=
  1341  //		   c.Query("id") == "1234"
  1342  //		   c.Query("name") == "Manu"
  1343  //		   c.Query("value") == ""
  1344  //		   c.Query("wtf") == ""
  1345  func (ctx *RequestContext) Query(key string) string {
  1346  	value, _ := ctx.GetQuery(key)
  1347  	return value
  1348  }
  1349  
  1350  // DefaultQuery returns the keyed url query value if it exists,
  1351  // otherwise it returns the specified defaultValue string.
  1352  func (ctx *RequestContext) DefaultQuery(key, defaultValue string) string {
  1353  	if value, ok := ctx.GetQuery(key); ok {
  1354  		return value
  1355  	}
  1356  	return defaultValue
  1357  }
  1358  
  1359  // GetQuery returns the keyed url query value
  1360  //
  1361  // if it exists `(value, true)` (even when the value is an empty string) will be returned,
  1362  // otherwise it returns `("", false)`.
  1363  // For example:
  1364  //
  1365  //	GET /?name=Manu&lastname=
  1366  //	("Manu", true) == c.GetQuery("name")
  1367  //	("", false) == c.GetQuery("id")
  1368  //	("", true) == c.GetQuery("lastname")
  1369  func (ctx *RequestContext) GetQuery(key string) (string, bool) {
  1370  	return ctx.QueryArgs().PeekExists(key)
  1371  }
  1372  
  1373  // PostForm returns the specified key from a POST urlencoded form or multipart form
  1374  // when it exists, otherwise it returns an empty string `("")`.
  1375  func (ctx *RequestContext) PostForm(key string) string {
  1376  	value, _ := ctx.GetPostForm(key)
  1377  	return value
  1378  }
  1379  
  1380  // PostFormArray returns the specified key from a POST urlencoded form or multipart form
  1381  // when it exists, otherwise it returns an empty array `([])`.
  1382  func (ctx *RequestContext) PostFormArray(key string) []string {
  1383  	values, _ := ctx.GetPostFormArray(key)
  1384  	return values
  1385  }
  1386  
  1387  // DefaultPostForm returns the specified key from a POST urlencoded form or multipart form
  1388  // when it exists, otherwise it returns the specified defaultValue string.
  1389  //
  1390  // See: PostForm() and GetPostForm() for further information.
  1391  func (ctx *RequestContext) DefaultPostForm(key, defaultValue string) string {
  1392  	if value, ok := ctx.GetPostForm(key); ok {
  1393  		return value
  1394  	}
  1395  	return defaultValue
  1396  }
  1397  
  1398  // GetPostForm is like PostForm(key). It returns the specified key from a POST urlencoded
  1399  // form or multipart form when it exists `(value, true)` (even when the value is an empty string),
  1400  // otherwise it returns ("", false).
  1401  //
  1402  // For example, during a PATCH request to update the user's email:
  1403  //
  1404  //	    email=mail@example.com  -->  ("mail@example.com", true) := GetPostForm("email") // set email to "mail@example.com"
  1405  //		   email=                  -->  ("", true) := GetPostForm("email") // set email to ""
  1406  //	                            -->  ("", false) := GetPostForm("email") // do nothing with email
  1407  func (ctx *RequestContext) GetPostForm(key string) (string, bool) {
  1408  	if v, exists := ctx.PostArgs().PeekExists(key); exists {
  1409  		return v, exists
  1410  	}
  1411  	return ctx.multipartFormValue(key)
  1412  }
  1413  
  1414  // GetPostFormArray is like PostFormArray(key). It returns the specified key from a POST urlencoded
  1415  // form or multipart form when it exists `([]string, true)` (even when the value is an empty string),
  1416  // otherwise it returns ([]string(nil), false).
  1417  //
  1418  // For example, during a PATCH request to update the item's tags:
  1419  //
  1420  //	    tag=tag1 tag=tag2 tag=tag3  -->  (["tag1", "tag2", "tag3"], true) := GetPostFormArray("tags") // set tags to ["tag1", "tag2", "tag3"]
  1421  //		   tags=                  -->  (nil, true) := GetPostFormArray("tags") // set tags to nil
  1422  //	                            -->  (nil, false) := GetPostFormArray("tags") // do nothing with tags
  1423  func (ctx *RequestContext) GetPostFormArray(key string) ([]string, bool) {
  1424  	vs := ctx.PostArgs().PeekAll(key)
  1425  	values := make([]string, len(vs))
  1426  	for i, v := range vs {
  1427  		values[i] = string(v)
  1428  	}
  1429  	if len(values) == 0 {
  1430  		return ctx.multipartFormValueArray(key)
  1431  	} else {
  1432  		return values, true
  1433  	}
  1434  }
  1435  
  1436  // bodyAllowedForStatus is a copy of http.bodyAllowedForStatus non-exported function.
  1437  func bodyAllowedForStatus(status int) bool {
  1438  	switch {
  1439  	case status >= 100 && status <= 199:
  1440  		return false
  1441  	case status == consts.StatusNoContent:
  1442  		return false
  1443  	case status == consts.StatusNotModified:
  1444  		return false
  1445  	}
  1446  	return true
  1447  }
  1448  
  1449  func (ctx *RequestContext) getBinder() binding.Binder {
  1450  	if ctx.binder != nil {
  1451  		return ctx.binder
  1452  	}
  1453  	return binding.DefaultBinder()
  1454  }
  1455  
  1456  func (ctx *RequestContext) getValidator() binding.StructValidator {
  1457  	if ctx.validator != nil {
  1458  		return ctx.validator
  1459  	}
  1460  	return binding.DefaultValidator()
  1461  }
  1462  
  1463  // BindAndValidate binds data from *RequestContext to obj and validates them if needed.
  1464  // NOTE: obj should be a pointer.
  1465  func (ctx *RequestContext) BindAndValidate(obj interface{}) error {
  1466  	return ctx.getBinder().BindAndValidate(&ctx.Request, obj, ctx.Params)
  1467  }
  1468  
  1469  // Bind binds data from *RequestContext to obj.
  1470  // NOTE: obj should be a pointer.
  1471  func (ctx *RequestContext) Bind(obj interface{}) error {
  1472  	return ctx.getBinder().Bind(&ctx.Request, obj, ctx.Params)
  1473  }
  1474  
  1475  // Validate validates obj with "vd" tag
  1476  // NOTE: obj should be a pointer.
  1477  func (ctx *RequestContext) Validate(obj interface{}) error {
  1478  	return ctx.getValidator().ValidateStruct(obj)
  1479  }
  1480  
  1481  // BindQuery binds query parameters from *RequestContext to obj with 'query' tag. It will only use 'query' tag for binding.
  1482  // NOTE: obj should be a pointer.
  1483  func (ctx *RequestContext) BindQuery(obj interface{}) error {
  1484  	return ctx.getBinder().BindQuery(&ctx.Request, obj)
  1485  }
  1486  
  1487  // BindHeader binds header parameters from *RequestContext to obj with 'header' tag. It will only use 'header' tag for binding.
  1488  // NOTE: obj should be a pointer.
  1489  func (ctx *RequestContext) BindHeader(obj interface{}) error {
  1490  	return ctx.getBinder().BindHeader(&ctx.Request, obj)
  1491  }
  1492  
  1493  // BindPath binds router parameters from *RequestContext to obj with 'path' tag. It will only use 'path' tag for binding.
  1494  // NOTE: obj should be a pointer.
  1495  func (ctx *RequestContext) BindPath(obj interface{}) error {
  1496  	return ctx.getBinder().BindPath(&ctx.Request, obj, ctx.Params)
  1497  }
  1498  
  1499  // BindForm binds form parameters from *RequestContext to obj with 'form' tag. It will only use 'form' tag for binding.
  1500  // NOTE: obj should be a pointer.
  1501  func (ctx *RequestContext) BindForm(obj interface{}) error {
  1502  	if len(ctx.Request.Body()) == 0 {
  1503  		return fmt.Errorf("missing form body")
  1504  	}
  1505  	return ctx.getBinder().BindForm(&ctx.Request, obj)
  1506  }
  1507  
  1508  // BindJSON binds JSON body from *RequestContext.
  1509  // NOTE: obj should be a pointer.
  1510  func (ctx *RequestContext) BindJSON(obj interface{}) error {
  1511  	return ctx.getBinder().BindJSON(&ctx.Request, obj)
  1512  }
  1513  
  1514  // BindProtobuf binds protobuf body from *RequestContext.
  1515  // NOTE: obj should be a pointer.
  1516  func (ctx *RequestContext) BindProtobuf(obj interface{}) error {
  1517  	return ctx.getBinder().BindProtobuf(&ctx.Request, obj)
  1518  }
  1519  
  1520  // BindByContentType will select the binding type on the ContentType automatically.
  1521  // NOTE: obj should be a pointer.
  1522  func (ctx *RequestContext) BindByContentType(obj interface{}) error {
  1523  	if ctx.Request.Header.IsGet() {
  1524  		return ctx.BindQuery(obj)
  1525  	}
  1526  	ct := utils.FilterContentType(bytesconv.B2s(ctx.Request.Header.ContentType()))
  1527  	switch strings.ToLower(ct) {
  1528  	case consts.MIMEApplicationJSON:
  1529  		return ctx.BindJSON(obj)
  1530  	case consts.MIMEPROTOBUF:
  1531  		return ctx.BindProtobuf(obj)
  1532  	case consts.MIMEApplicationHTMLForm, consts.MIMEMultipartPOSTForm:
  1533  		return ctx.BindForm(obj)
  1534  	default:
  1535  		return fmt.Errorf("unsupported bind content-type for '%s'", ct)
  1536  	}
  1537  }
  1538  
  1539  // VisitAllQueryArgs calls f for each existing query arg.
  1540  //
  1541  // f must not retain references to key and value after returning.
  1542  // Make key and/or value copies if you need storing them after returning.
  1543  func (ctx *RequestContext) VisitAllQueryArgs(f func(key, value []byte)) {
  1544  	ctx.QueryArgs().VisitAll(f)
  1545  }
  1546  
  1547  // VisitAllPostArgs calls f for each existing post arg.
  1548  //
  1549  // f must not retain references to key and value after returning.
  1550  // Make key and/or value copies if you need storing them after returning.
  1551  func (ctx *RequestContext) VisitAllPostArgs(f func(key, value []byte)) {
  1552  	ctx.Request.PostArgs().VisitAll(f)
  1553  }
  1554  
  1555  // VisitAllHeaders calls f for each request header.
  1556  //
  1557  // f must not retain references to key and/or value after returning.
  1558  // Copy key and/or value contents before returning if you need retaining them.
  1559  //
  1560  // To get the headers in order they were received use VisitAllInOrder.
  1561  func (ctx *RequestContext) VisitAllHeaders(f func(key, value []byte)) {
  1562  	ctx.Request.Header.VisitAll(f)
  1563  }
  1564  
  1565  // VisitAllCookie calls f for each request cookie.
  1566  //
  1567  // f must not retain references to key and/or value after returning.
  1568  func (ctx *RequestContext) VisitAllCookie(f func(key, value []byte)) {
  1569  	ctx.Request.Header.VisitAllCookie(f)
  1570  }