diff --git a/ctx.go b/ctx.go index e630a345f6..5437d36a36 100644 --- a/ctx.go +++ b/ctx.go @@ -41,6 +41,11 @@ type contextKey int // userContextKey define the key name for storing context.Context in *fasthttp.RequestCtx const userContextKey contextKey = 0 // __local_user_context__ +// DefaultCtx is the default implementation of the Ctx interface +// generation tool `go install github.com/vburenin/ifacemaker@975a95966976eeb2d4365a7fb236e274c54da64c` +// https://github.com/vburenin/ifacemaker/blob/975a95966976eeb2d4365a7fb236e274c54da64c/ifacemaker.go#L14-L30 +// +//go:generate ifacemaker --file ctx.go --struct DefaultCtx --iface Ctx --pkg fiber --output ctx_interface_gen.go --not-exported true --iface-comment "Ctx represents the Context which hold the HTTP request and response.\nIt has methods for the request query string, parameters, body, HTTP headers and so on." type DefaultCtx struct { app *App // Reference to *App route *Route // Reference to *Route @@ -1711,16 +1716,80 @@ func (c *DefaultCtx) Bind() *Bind { return c.bind } -// Convert a string value to a specified type, handling errors and optional default values. -func Convert[T any](value string, convertor func(string) (T, error), defaultValue ...T) (T, error) { - converted, err := convertor(value) - if err != nil { - if len(defaultValue) > 0 { - return defaultValue[0], nil - } +// Reset is a method to reset context fields by given request when to use server handlers. +func (c *DefaultCtx) Reset(fctx *fasthttp.RequestCtx) { + // Reset route and handler index + c.indexRoute = -1 + c.indexHandler = 0 + // Reset matched flag + c.matched = false + // Set paths + c.pathOriginal = c.app.getString(fctx.URI().PathOriginal()) + // Set method + c.method = c.app.getString(fctx.Request.Header.Method()) + c.methodINT = c.app.methodInt(c.method) + // Attach *fasthttp.RequestCtx to ctx + c.fasthttp = fctx + // reset base uri + c.baseURI = "" + // Prettify path + c.configDependentPaths() +} - return converted, fmt.Errorf("failed to convert: %w", err) +// Release is a method to reset context fields when to use ReleaseCtx() +func (c *DefaultCtx) release() { + c.route = nil + c.fasthttp = nil + c.bind = nil + c.redirectionMessages = c.redirectionMessages[:0] + c.viewBindMap = sync.Map{} + if c.redirect != nil { + ReleaseRedirect(c.redirect) + c.redirect = nil } +} + +// Methods to use with next stack. +func (c *DefaultCtx) getMethodINT() int { + return c.methodINT +} + +func (c *DefaultCtx) getIndexRoute() int { + return c.indexRoute +} + +func (c *DefaultCtx) getTreePath() string { + return c.treePath +} + +func (c *DefaultCtx) getDetectionPath() string { + return c.detectionPath +} + +func (c *DefaultCtx) getPathOriginal() string { + return c.pathOriginal +} + +func (c *DefaultCtx) getValues() *[maxParams]string { + return &c.values +} + +func (c *DefaultCtx) getMatched() bool { + return c.matched +} + +func (c *DefaultCtx) setIndexHandler(handler int) { + c.indexHandler = handler +} + +func (c *DefaultCtx) setIndexRoute(route int) { + c.indexRoute = route +} + +func (c *DefaultCtx) setMatched(matched bool) { + c.matched = matched +} - return converted, nil +func (c *DefaultCtx) setRoute(route *Route) { + c.route = route } diff --git a/ctx_interface.go b/ctx_interface.go index 2950c088de..ca438d82c5 100644 --- a/ctx_interface.go +++ b/ctx_interface.go @@ -5,384 +5,11 @@ package fiber import ( - "context" - "crypto/tls" "errors" - "io" - "mime/multipart" - "sync" "github.com/valyala/fasthttp" ) -// Ctx represents the Context which hold the HTTP request and response. -// It has methods for the request query string, parameters, body, HTTP headers and so on. -type Ctx interface { - // Accepts checks if the specified extensions or content types are acceptable. - Accepts(offers ...string) string - - // AcceptsCharsets checks if the specified charset is acceptable. - AcceptsCharsets(offers ...string) string - - // AcceptsEncodings checks if the specified encoding is acceptable. - AcceptsEncodings(offers ...string) string - - // AcceptsLanguages checks if the specified language is acceptable. - AcceptsLanguages(offers ...string) string - - // App returns the *App reference to the instance of the Fiber application - App() *App - - // Append the specified value to the HTTP response header field. - // If the header is not already set, it creates the header with the specified value. - Append(field string, values ...string) - - // Attachment sets the HTTP response Content-Disposition header field to attachment. - Attachment(filename ...string) - - // AutoFormat performs content-negotiation on the Accept HTTP header. - // It uses Accepts to select a proper format. - // The supported content types are text/html, text/plain, application/json, and application/xml. - // For more flexible content negotiation, use Format. - // If the header is not specified or there is no proper format, text/plain is used. - AutoFormat(body any) error - - // BaseURL returns (protocol + host + base path). - BaseURL() string - - // Body contains the raw body submitted in a POST request. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - Body() []byte - - // ClearCookie expires a specific cookie by key on the client side. - // If no key is provided it expires all cookies that came with the request. - ClearCookie(key ...string) - - // Context returns *fasthttp.RequestCtx that carries a deadline - // a cancellation signal, and other values across API boundaries. - Context() *fasthttp.RequestCtx - - // UserContext returns a context implementation that was set by - // user earlier or returns a non-nil, empty context,if it was not set earlier. - UserContext() context.Context - - // SetUserContext sets a context implementation by user. - SetUserContext(ctx context.Context) - - // Cookie sets a cookie by passing a cookie struct. - Cookie(cookie *Cookie) - - // Cookies is used for getting a cookie value by key. - // Defaults to the empty string "" if the cookie doesn't exist. - // If a default value is given, it will return that value if the cookie doesn't exist. - // The returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting to use the value outside the Handler. - Cookies(key string, defaultValue ...string) string - - // Download transfers the file from path as an attachment. - // Typically, browsers will prompt the user for download. - // By default, the Content-Disposition header filename= parameter is the filepath (this typically appears in the browser dialog). - // Override this default with the filename parameter. - Download(file string, filename ...string) error - - // Request return the *fasthttp.Request object - // This allows you to use all fasthttp request methods - // https://godoc.org/github.com/valyala/fasthttp#Request - Request() *fasthttp.Request - - // Response return the *fasthttp.Response object - // This allows you to use all fasthttp response methods - // https://godoc.org/github.com/valyala/fasthttp#Response - Response() *fasthttp.Response - - // Format performs content-negotiation on the Accept HTTP header. - // It uses Accepts to select a proper format and calls the matching - // user-provided handler function. - // If no accepted format is found, and a format with MediaType "default" is given, - // that default handler is called. If no format is found and no default is given, - // StatusNotAcceptable is sent. - Format(handlers ...ResFmt) error - - // FormFile returns the first file by key from a MultipartForm. - FormFile(key string) (*multipart.FileHeader, error) - - // FormValue returns the first value by key from a MultipartForm. - // Defaults to the empty string "" if the form value doesn't exist. - // If a default value is given, it will return that value if the form value does not exist. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - FormValue(key string, defaultValue ...string) string - - // Fresh returns true when the response is still “fresh” in the client's cache, - // otherwise false is returned to indicate that the client cache is now stale - // and the full response should be sent. - // When a client sends the Cache-Control: no-cache request header to indicate an end-to-end - // reload request, this module will return false to make handling these requests transparent. - // https://github.com/jshttp/fresh/blob/10e0471669dbbfbfd8de65bc6efac2ddd0bfa057/index.js#L33 - Fresh() bool - - // Get returns the HTTP request header specified by field. - // Field names are case-insensitive - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - Get(key string, defaultValue ...string) string - - // GetRespHeader returns the HTTP response header specified by field. - // Field names are case-insensitive - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - GetRespHeader(key string, defaultValue ...string) string - - // GetRespHeaders returns the HTTP response headers. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - GetRespHeaders() map[string][]string - - // GetReqHeaders returns the HTTP request headers. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - GetReqHeaders() map[string][]string - - // Host contains the host derived from the X-Forwarded-Host or Host HTTP header. - // Returned value is only valid within the handler. Do not store any references. - // In a network context, `Host` refers to the combination of a hostname and potentially a port number used for connecting, - // while `Hostname` refers specifically to the name assigned to a device on a network, excluding any port information. - // Example: URL: https://example.com:8080 -> Host: example.com:8080 - // Make copies or use the Immutable setting instead. - // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. - Host() string - - // Hostname contains the hostname derived from the X-Forwarded-Host or Host HTTP header using the c.Host() method. - // Returned value is only valid within the handler. Do not store any references. - // Example: URL: https://example.com:8080 -> Hostname: example.com - // Make copies or use the Immutable setting instead. - // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. - Hostname() string - - // Port returns the remote port of the request. - Port() string - - // IP returns the remote IP address of the request. - // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. - IP() string - - // IPs returns an string slice of IP addresses specified in the X-Forwarded-For request header. - IPs() (ips []string) - - // Is returns the matching content type, - // if the incoming request's Content-Type HTTP header field matches the MIME type specified by the type parameter - Is(extension string) bool - - // JSON converts any interface or string to JSON. - // Array and slice values encode as JSON arrays, - // except that []byte encodes as a base64-encoded string, - // and a nil slice encodes as the null JSON value. - // If the ctype parameter is given, this method will set the - // Content-Type header equal to ctype. If ctype is not given, - // The Content-Type header will be set to application/json. - JSON(data any, ctype ...string) error - - // JSONP sends a JSON response with JSONP support. - // This method is identical to JSON, except that it opts-in to JSONP callback support. - // By default, the callback name is simply callback. - JSONP(data any, callback ...string) error - - // XML converts any interface or string to XML. - // This method also sets the content header to application/xml. - XML(data any) error - - // Links joins the links followed by the property to populate the response's Link HTTP header field. - Links(link ...string) - - // Locals makes it possible to pass any values under string keys scoped to the request - // and therefore available to all following routes that match the request. - Locals(key any, value ...any) (val any) - - // Location sets the response Location HTTP header to the specified path parameter. - Location(path string) - - // Method contains a string corresponding to the HTTP method of the request: GET, POST, PUT and so on. - Method(override ...string) string - - // MultipartForm parse form entries from binary. - // This returns a map[string][]string, so given a key the value will be a string slice. - MultipartForm() (*multipart.Form, error) - - // Next executes the next method in the stack that matches the current route. - Next() (err error) - - // RestartRouting instead of going to the next handler. This may be useful after - // changing the request path. Note that handlers might be executed again. - RestartRouting() error - - // OriginalURL contains the original request URL. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting to use the value outside the Handler. - OriginalURL() string - - // Params is used to get the route parameters. - // Defaults to empty string "" if the param doesn't exist. - // If a default value is given, it will return that value if the param doesn't exist. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting to use the value outside the Handler. - Params(key string, defaultValue ...string) string - - // Path returns the path part of the request URL. - // Optionally, you could override the path. - Path(override ...string) string - - // Scheme contains the request scheme string: http or https for TLS requests. - // Use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. - Scheme() string - - // Protocol returns the HTTP protocol of request: HTTP/1.1 and HTTP/2. - Protocol() string - - // Queries returns a map of query parameters and their values. - // - // GET /?name=alex&wanna_cake=2&id= - // Queries()["name"] == "alex" - // Queries()["wanna_cake"] == "2" - // Queries()["id"] == "" - // - // GET /?field1=value1&field1=value2&field2=value3 - // Queries()["field1"] == "value2" - // Queries()["field2"] == "value3" - // - // GET /?list_a=1&list_a=2&list_a=3&list_b[]=1&list_b[]=2&list_b[]=3&list_c=1,2,3 - // Queries()["list_a"] == "3" - // Queries()["list_b[]"] == "3" - // Queries()["list_c"] == "1,2,3" - // - // GET /api/search?filters.author.name=John&filters.category.name=Technology&filters[customer][name]=Alice&filters[status]=pending - // Queries()["filters.author.name"] == "John" - // Queries()["filters.category.name"] == "Technology" - // Queries()["filters[customer][name]"] == "Alice" - // Queries()["filters[status]"] == "pending" - Queries() map[string]string - - // Query returns the query string parameter in the url. - // Defaults to empty string "" if the query doesn't exist. - // If a default value is given, it will return that value if the query doesn't exist. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting to use the value outside the Handler. - Query(key string, defaultValue ...string) string - - // Range returns a struct containing the type and a slice of ranges. - Range(size int) (rangeData Range, err error) - - // Redirect returns the Redirect reference. - // Use Redirect().Status() to set custom redirection status code. - // If status is not specified, status defaults to 302 Found. - // You can use Redirect().To(), Redirect().Route() and Redirect().Back() for redirection. - Redirect() *Redirect - - // ViewBind Add vars to default view var map binding to template engine. - // Variables are read by the Render method and may be overwritten. - ViewBind(vars Map) error - - // GetRouteURL generates URLs to named routes, with parameters. URLs are relative, for example: "/user/1831" - GetRouteURL(routeName string, params Map) (string, error) - - // Render a template with data and sends a text/html response. - // We support the following engines: https://github.com/gofiber/template - Render(name string, bind Map, layouts ...string) error - - // Route returns the matched Route struct. - Route() *Route - - // SaveFile saves any multipart file to disk. - SaveFile(fileheader *multipart.FileHeader, path string) error - - // SaveFileToStorage saves any multipart file to an external storage system. - SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error - - // Secure returns whether a secure connection was established. - Secure() bool - - // Send sets the HTTP response body without copying it. - // From this point onward the body argument must not be changed. - Send(body []byte) error - - // SendFile transfers the file from the given path. - // The file is not compressed by default, enable this by passing a 'true' argument - // Sets the Content-Type response HTTP header field based on the filenames extension. - SendFile(file string, compress ...bool) error - - // SendStatus sets the HTTP status code and if the response body is empty, - // it sets the correct status message in the body. - SendStatus(status int) error - - // SendString sets the HTTP response body for string types. - // This means no type assertion, recommended for faster performance - SendString(body string) error - - // SendStream sets response body stream and optional body size. - SendStream(stream io.Reader, size ...int) error - - // Set sets the response's HTTP header field to the specified key, value. - Set(key, val string) - - // Subdomains returns a string slice of subdomains in the domain name of the request. - // The subdomain offset, which defaults to 2, is used for determining the beginning of the subdomain segments. - Subdomains(offset ...int) []string - - // Stale is not implemented yet, pull requests are welcome! - Stale() bool - - // Status sets the HTTP status for the response. - // This method is chainable. - Status(status int) Ctx - - // String returns unique string representation of the ctx. - // - // The returned value may be useful for logging. - String() string - - // Type sets the Content-Type HTTP header to the MIME type specified by the file extension. - Type(extension string, charset ...string) Ctx - - // Vary adds the given header field to the Vary response header. - // This will append the header, if not already listed, otherwise leaves it listed in the current location. - Vary(fields ...string) - - // Write appends p into response body. - Write(p []byte) (int, error) - - // Writef appends f & a into response body writer. - Writef(f string, a ...any) (int, error) - - // WriteString appends s to response body. - WriteString(s string) (int, error) - - // XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest, - // indicating that the request was issued by a client library (such as jQuery). - XHR() bool - - // IsProxyTrusted checks trustworthiness of remote ip. - // If EnableTrustedProxyCheck false, it returns true - // IsProxyTrusted can check remote ip by proxy ranges and ip map. - IsProxyTrusted() bool - - // IsFromLocal will return true if request came from local. - IsFromLocal() bool - - // Reset is a method to reset context fields by given request when to use server handlers. - Reset(fctx *fasthttp.RequestCtx) - - // Bind You can bind body, cookie, headers etc. into the map, map slice, struct easily by using Binding method. - // It gives custom binding support, detailed binding options and more. - // Replacement of: BodyParser, ParamsParser, GetReqHeaders, GetRespHeaders, AllParams, QueryParser, ReqHeaderParser - Bind() *Bind - - // ClientHelloInfo return CHI from context - ClientHelloInfo() *tls.ClientHelloInfo - - // Release is a method to reset context fields when to use ReleaseCtx() - release() -} - type CustomCtx interface { Ctx @@ -440,81 +67,3 @@ func (app *App) ReleaseCtx(c Ctx) { c.release() app.pool.Put(c) } - -// Reset is a method to reset context fields by given request when to use server handlers. -func (c *DefaultCtx) Reset(fctx *fasthttp.RequestCtx) { - // Reset route and handler index - c.indexRoute = -1 - c.indexHandler = 0 - // Reset matched flag - c.matched = false - // Set paths - c.pathOriginal = c.app.getString(fctx.URI().PathOriginal()) - // Set method - c.method = c.app.getString(fctx.Request.Header.Method()) - c.methodINT = c.app.methodInt(c.method) - // Attach *fasthttp.RequestCtx to ctx - c.fasthttp = fctx - // reset base uri - c.baseURI = "" - // Prettify path - c.configDependentPaths() -} - -// Release is a method to reset context fields when to use ReleaseCtx() -func (c *DefaultCtx) release() { - c.route = nil - c.fasthttp = nil - c.bind = nil - c.redirectionMessages = c.redirectionMessages[:0] - c.viewBindMap = sync.Map{} - if c.redirect != nil { - ReleaseRedirect(c.redirect) - c.redirect = nil - } -} - -// Methods to use with next stack. -func (c *DefaultCtx) getMethodINT() int { - return c.methodINT -} - -func (c *DefaultCtx) getIndexRoute() int { - return c.indexRoute -} - -func (c *DefaultCtx) getTreePath() string { - return c.treePath -} - -func (c *DefaultCtx) getDetectionPath() string { - return c.detectionPath -} - -func (c *DefaultCtx) getPathOriginal() string { - return c.pathOriginal -} - -func (c *DefaultCtx) getValues() *[maxParams]string { - return &c.values -} - -func (c *DefaultCtx) getMatched() bool { - return c.matched -} - -func (c *DefaultCtx) setIndexHandler(handler int) { - c.indexHandler = handler -} - -func (c *DefaultCtx) setIndexRoute(route int) { - c.indexRoute = route -} - -func (c *DefaultCtx) setMatched(matched bool) { - c.matched = matched -} - -func (c *DefaultCtx) setRoute(route *Route) { - c.route = route -} diff --git a/ctx_interface_gen.go b/ctx_interface_gen.go new file mode 100644 index 0000000000..8107965772 --- /dev/null +++ b/ctx_interface_gen.go @@ -0,0 +1,341 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package fiber + +import ( + "context" + "crypto/tls" + "io" + "mime/multipart" + + "github.com/valyala/fasthttp" +) + +// Ctx represents the Context which hold the HTTP request and response. +// It has methods for the request query string, parameters, body, HTTP headers and so on. +type Ctx interface { + // Accepts checks if the specified extensions or content types are acceptable. + Accepts(offers ...string) string + // AcceptsCharsets checks if the specified charset is acceptable. + AcceptsCharsets(offers ...string) string + // AcceptsEncodings checks if the specified encoding is acceptable. + AcceptsEncodings(offers ...string) string + // AcceptsLanguages checks if the specified language is acceptable. + AcceptsLanguages(offers ...string) string + // App returns the *App reference to the instance of the Fiber application + App() *App + // Append the specified value to the HTTP response header field. + // If the header is not already set, it creates the header with the specified value. + Append(field string, values ...string) + // Attachment sets the HTTP response Content-Disposition header field to attachment. + Attachment(filename ...string) + // BaseURL returns (protocol + host + base path). + BaseURL() string + // BodyRaw contains the raw body submitted in a POST request. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + BodyRaw() []byte + tryDecodeBodyInOrder(originalBody *[]byte, encodings []string) ([]byte, uint8, error) + // Body contains the raw body submitted in a POST request. + // This method will decompress the body if the 'Content-Encoding' header is provided. + // It returns the original (or decompressed) body data which is valid only within the handler. + // Don't store direct references to the returned data. + // If you need to keep the body's data later, make a copy or use the Immutable option. + Body() []byte + // ClearCookie expires a specific cookie by key on the client side. + // If no key is provided it expires all cookies that came with the request. + ClearCookie(key ...string) + // Context returns *fasthttp.RequestCtx that carries a deadline + // a cancellation signal, and other values across API boundaries. + Context() *fasthttp.RequestCtx + // UserContext returns a context implementation that was set by + // user earlier or returns a non-nil, empty context,if it was not set earlier. + UserContext() context.Context + // SetUserContext sets a context implementation by user. + SetUserContext(ctx context.Context) + // Cookie sets a cookie by passing a cookie struct. + Cookie(cookie *Cookie) + // Cookies are used for getting a cookie value by key. + // Defaults to the empty string "" if the cookie doesn't exist. + // If a default value is given, it will return that value if the cookie doesn't exist. + // The returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting to use the value outside the Handler. + Cookies(key string, defaultValue ...string) string + // Download transfers the file from path as an attachment. + // Typically, browsers will prompt the user for download. + // By default, the Content-Disposition header filename= parameter is the filepath (this typically appears in the browser dialog). + // Override this default with the filename parameter. + Download(file string, filename ...string) error + // Request return the *fasthttp.Request object + // This allows you to use all fasthttp request methods + // https://godoc.org/github.com/valyala/fasthttp#Request + Request() *fasthttp.Request + // Response return the *fasthttp.Response object + // This allows you to use all fasthttp response methods + // https://godoc.org/github.com/valyala/fasthttp#Response + Response() *fasthttp.Response + // Format performs content-negotiation on the Accept HTTP header. + // It uses Accepts to select a proper format and calls the matching + // user-provided handler function. + // If no accepted format is found, and a format with MediaType "default" is given, + // that default handler is called. If no format is found and no default is given, + // StatusNotAcceptable is sent. + Format(handlers ...ResFmt) error + // AutoFormat performs content-negotiation on the Accept HTTP header. + // It uses Accepts to select a proper format. + // The supported content types are text/html, text/plain, application/json, and application/xml. + // For more flexible content negotiation, use Format. + // If the header is not specified or there is no proper format, text/plain is used. + AutoFormat(body any) error + // FormFile returns the first file by key from a MultipartForm. + FormFile(key string) (*multipart.FileHeader, error) + // FormValue returns the first value by key from a MultipartForm. + // Search is performed in QueryArgs, PostArgs, MultipartForm and FormFile in this particular order. + // Defaults to the empty string "" if the form value doesn't exist. + // If a default value is given, it will return that value if the form value does not exist. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + FormValue(key string, defaultValue ...string) string + // Fresh returns true when the response is still “fresh” in the client's cache, + // otherwise false is returned to indicate that the client cache is now stale + // and the full response should be sent. + // When a client sends the Cache-Control: no-cache request header to indicate an end-to-end + // reload request, this module will return false to make handling these requests transparent. + // https://github.com/jshttp/fresh/blob/10e0471669dbbfbfd8de65bc6efac2ddd0bfa057/index.js#L33 + Fresh() bool + // Get returns the HTTP request header specified by field. + // Field names are case-insensitive + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + Get(key string, defaultValue ...string) string + // GetRespHeader returns the HTTP response header specified by field. + // Field names are case-insensitive + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + GetRespHeader(key string, defaultValue ...string) string + // GetRespHeaders returns the HTTP response headers. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + GetRespHeaders() map[string][]string + // GetReqHeaders returns the HTTP request headers. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + GetReqHeaders() map[string][]string + // Host contains the host derived from the X-Forwarded-Host or Host HTTP header. + // Returned value is only valid within the handler. Do not store any references. + // In a network context, `Host` refers to the combination of a hostname and potentially a port number used for connecting, + // while `Hostname` refers specifically to the name assigned to a device on a network, excluding any port information. + // Example: URL: https://example.com:8080 -> Host: example.com:8080 + // Make copies or use the Immutable setting instead. + // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. + Host() string + // Hostname contains the hostname derived from the X-Forwarded-Host or Host HTTP header using the c.Host() method. + // Returned value is only valid within the handler. Do not store any references. + // Example: URL: https://example.com:8080 -> Hostname: example.com + // Make copies or use the Immutable setting instead. + // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. + Hostname() string + // Port returns the remote port of the request. + Port() string + // IP returns the remote IP address of the request. + // If ProxyHeader and IP Validation is configured, it will parse that header and return the first valid IP address. + // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. + IP() string + // extractIPsFromHeader will return a slice of IPs it found given a header name in the order they appear. + // When IP validation is enabled, any invalid IPs will be omitted. + extractIPsFromHeader(header string) []string + // extractIPFromHeader will attempt to pull the real client IP from the given header when IP validation is enabled. + // currently, it will return the first valid IP address in header. + // when IP validation is disabled, it will simply return the value of the header without any inspection. + // Implementation is almost the same as in extractIPsFromHeader, but without allocation of []string. + extractIPFromHeader(header string) string + // IPs returns a string slice of IP addresses specified in the X-Forwarded-For request header. + // When IP validation is enabled, only valid IPs are returned. + IPs() []string + // Is returns the matching content type, + // if the incoming request's Content-Type HTTP header field matches the MIME type specified by the type parameter + Is(extension string) bool + // JSON converts any interface or string to JSON. + // Array and slice values encode as JSON arrays, + // except that []byte encodes as a base64-encoded string, + // and a nil slice encodes as the null JSON value. + // If the ctype parameter is given, this method will set the + // Content-Type header equal to ctype. If ctype is not given, + // The Content-Type header will be set to application/json. + JSON(data any, ctype ...string) error + // JSONP sends a JSON response with JSONP support. + // This method is identical to JSON, except that it opts-in to JSONP callback support. + // By default, the callback name is simply callback. + JSONP(data any, callback ...string) error + // XML converts any interface or string to XML. + // This method also sets the content header to application/xml. + XML(data any) error + // Links joins the links followed by the property to populate the response's Link HTTP header field. + Links(link ...string) + // Locals makes it possible to pass any values under keys scoped to the request + // and therefore available to all following routes that match the request. + Locals(key any, value ...any) any + // Location sets the response Location HTTP header to the specified path parameter. + Location(path string) + // Method returns the HTTP request method for the context, optionally overridden by the provided argument. + // If no override is given or if the provided override is not a valid HTTP method, it returns the current method from the context. + // Otherwise, it updates the context's method and returns the overridden method as a string. + Method(override ...string) string + // MultipartForm parse form entries from binary. + // This returns a map[string][]string, so given a key the value will be a string slice. + MultipartForm() (*multipart.Form, error) + // ClientHelloInfo return CHI from context + ClientHelloInfo() *tls.ClientHelloInfo + // Next executes the next method in the stack that matches the current route. + Next() error + // RestartRouting instead of going to the next handler. This may be useful after + // changing the request path. Note that handlers might be executed again. + RestartRouting() error + // OriginalURL contains the original request URL. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting to use the value outside the Handler. + OriginalURL() string + // Params is used to get the route parameters. + // Defaults to empty string "" if the param doesn't exist. + // If a default value is given, it will return that value if the param doesn't exist. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting to use the value outside the Handler. + Params(key string, defaultValue ...string) string + // Path returns the path part of the request URL. + // Optionally, you could override the path. + Path(override ...string) string + // Scheme contains the request protocol string: http or https for TLS requests. + // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. + Scheme() string + // Protocol returns the HTTP protocol of request: HTTP/1.1 and HTTP/2. + Protocol() string + // Query returns the query string parameter in the url. + // Defaults to empty string "" if the query doesn't exist. + // If a default value is given, it will return that value if the query doesn't exist. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting to use the value outside the Handler. + Query(key string, defaultValue ...string) string + // Queries returns a map of query parameters and their values. + // + // GET /?name=alex&wanna_cake=2&id= + // Queries()["name"] == "alex" + // Queries()["wanna_cake"] == "2" + // Queries()["id"] == "" + // + // GET /?field1=value1&field1=value2&field2=value3 + // Queries()["field1"] == "value2" + // Queries()["field2"] == "value3" + // + // GET /?list_a=1&list_a=2&list_a=3&list_b[]=1&list_b[]=2&list_b[]=3&list_c=1,2,3 + // Queries()["list_a"] == "3" + // Queries()["list_b[]"] == "3" + // Queries()["list_c"] == "1,2,3" + // + // GET /api/search?filters.author.name=John&filters.category.name=Technology&filters[customer][name]=Alice&filters[status]=pending + // Queries()["filters.author.name"] == "John" + // Queries()["filters.category.name"] == "Technology" + // Queries()["filters[customer][name]"] == "Alice" + // Queries()["filters[status]"] == "pending" + Queries() map[string]string + // Range returns a struct containing the type and a slice of ranges. + Range(size int) (Range, error) + // Redirect returns the Redirect reference. + // Use Redirect().Status() to set custom redirection status code. + // If status is not specified, status defaults to 302 Found. + // You can use Redirect().To(), Redirect().Route() and Redirect().Back() for redirection. + Redirect() *Redirect + // ViewBind Add vars to default view var map binding to template engine. + // Variables are read by the Render method and may be overwritten. + ViewBind(vars Map) error + // getLocationFromRoute get URL location from route using parameters + getLocationFromRoute(route Route, params Map) (string, error) + // GetRouteURL generates URLs to named routes, with parameters. URLs are relative, for example: "/user/1831" + GetRouteURL(routeName string, params Map) (string, error) + // Render a template with data and sends a text/html response. + // We support the following engines: https://github.com/gofiber/template + Render(name string, bind Map, layouts ...string) error + renderExtensions(bind any) + // Route returns the matched Route struct. + Route() *Route + // SaveFile saves any multipart file to disk. + SaveFile(fileheader *multipart.FileHeader, path string) error + // SaveFileToStorage saves any multipart file to an external storage system. + SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error + // Secure returns whether a secure connection was established. + Secure() bool + // Send sets the HTTP response body without copying it. + // From this point onward the body argument must not be changed. + Send(body []byte) error + // SendFile transfers the file from the given path. + // The file is not compressed by default, enable this by passing a 'true' argument + // Sets the Content-Type response HTTP header field based on the filenames extension. + SendFile(file string, compress ...bool) error + // SendStatus sets the HTTP status code and if the response body is empty, + // it sets the correct status message in the body. + SendStatus(status int) error + // SendString sets the HTTP response body for string types. + // This means no type assertion, recommended for faster performance + SendString(body string) error + // SendStream sets response body stream and optional body size. + SendStream(stream io.Reader, size ...int) error + // Set sets the response's HTTP header field to the specified key, value. + Set(key, val string) + setCanonical(key, val string) + // Subdomains returns a string slice of subdomains in the domain name of the request. + // The subdomain offset, which defaults to 2, is used for determining the beginning of the subdomain segments. + Subdomains(offset ...int) []string + // Stale is not implemented yet, pull requests are welcome! + Stale() bool + // Status sets the HTTP status for the response. + // This method is chainable. + Status(status int) Ctx + // String returns unique string representation of the ctx. + // + // The returned value may be useful for logging. + String() string + // Type sets the Content-Type HTTP header to the MIME type specified by the file extension. + Type(extension string, charset ...string) Ctx + // Vary adds the given header field to the Vary response header. + // This will append the header, if not already listed, otherwise leaves it listed in the current location. + Vary(fields ...string) + // Write appends p into response body. + Write(p []byte) (int, error) + // Writef appends f & a into response body writer. + Writef(f string, a ...any) (int, error) + // WriteString appends s to response body. + WriteString(s string) (int, error) + // XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest, + // indicating that the request was issued by a client library (such as jQuery). + XHR() bool + // configDependentPaths set paths for route recognition and prepared paths for the user, + // here the features for caseSensitive, decoded paths, strict paths are evaluated + configDependentPaths() + // IsProxyTrusted checks trustworthiness of remote ip. + // If EnableTrustedProxyCheck false, it returns true + // IsProxyTrusted can check remote ip by proxy ranges and ip map. + IsProxyTrusted() bool + // IsLocalHost will return true if address is a localhost address. + isLocalHost(address string) bool + // IsFromLocal will return true if request came from local. + IsFromLocal() bool + // Bind You can bind body, cookie, headers etc. into the map, map slice, struct easily by using Binding method. + // It gives custom binding support, detailed binding options and more. + // Replacement of: BodyParser, ParamsParser, GetReqHeaders, GetRespHeaders, AllParams, QueryParser, ReqHeaderParser + Bind() *Bind + // Reset is a method to reset context fields by given request when to use server handlers. + Reset(fctx *fasthttp.RequestCtx) + // Release is a method to reset context fields when to use ReleaseCtx() + release() + // Methods to use with next stack. + getMethodINT() int + getIndexRoute() int + getTreePath() string + getDetectionPath() string + getPathOriginal() string + getValues() *[maxParams]string + getMatched() bool + setIndexHandler(handler int) + setIndexRoute(route int) + setMatched(matched bool) + setRoute(route *Route) +} diff --git a/helpers.go b/helpers.go index 4a564da97a..203f51da54 100644 --- a/helpers.go +++ b/helpers.go @@ -707,6 +707,20 @@ func IndexRune(str string, needle int32) bool { return false } +// Convert a string value to a specified type, handling errors and optional default values. +func Convert[T any](value string, convertor func(string) (T, error), defaultValue ...T) (T, error) { + converted, err := convertor(value) + if err != nil { + if len(defaultValue) > 0 { + return defaultValue[0], nil + } + + return converted, fmt.Errorf("failed to convert: %w", err) + } + + return converted, nil +} + // assertValueType asserts the type of the result to the type of the value func assertValueType[V GenericType, T any](result T) V { v, ok := any(result).(V) diff --git a/middleware/idempotency/response.go b/middleware/idempotency/response.go index f42d1a3311..da09630faa 100644 --- a/middleware/idempotency/response.go +++ b/middleware/idempotency/response.go @@ -1,5 +1,8 @@ package idempotency +// response is a struct that represents the response of a request. +// generation tool `go install github.com/tinylib/msgp@latest` +// //go:generate msgp -o=response_msgp.go -io=false -unexported type response struct { StatusCode int `msg:"sc"`