---
id: ctx
title: 🧠 Ctx
description: >-
  The Ctx interface represents the Context which holds the HTTP request and
  response. It has methods for the request query string, parameters, body, HTTP
  headers, and so on.
sidebar_position: 3
---

### Abandon

Marks the context as abandoned. An abandoned context will not be returned to the pool when `ReleaseCtx` is called. This is used internally by the [timeout middleware](../middleware/timeout.md) to return immediately while the handler goroutine continues safely.

```go title="Signature"
func (c fiber.Ctx) Abandon()
func (c fiber.Ctx) IsAbandoned() bool
func (c fiber.Ctx) ForceRelease()
```

| Method         | Description                                                                 |
|:---------------|:----------------------------------------------------------------------------|
| `Abandon()`    | Marks the context as abandoned. ReleaseCtx becomes a no-op for this context. |
| `IsAbandoned()`| Returns `true` if `Abandon()` was called on this context.                   |
| `ForceRelease()`| Releases an abandoned context back to the pool. Must only be called after the handler has completely finished. |

:::caution
These methods are primarily for internal use and advanced middleware development. Most applications should not need to call them directly.
:::

### App

Returns the [\*App](app.md) reference so you can easily access all application settings.

```go title="Signature"
func (c fiber.Ctx) App() *App
```

```go title="Example"
app.Get("/stack", func(c fiber.Ctx) error {
  return c.JSON(c.App().Stack())
})
```

### Bind

Bind returns a helper for decoding the request body, query string, headers, cookies, and more.

For full details, see the [Bind](./bind.md) documentation.

```go title="Signature"
func (c fiber.Ctx) Bind() *Bind
```

```go title="Example"
app.Post("/", func(c fiber.Ctx) error {
  user := new(User)
  // Bind the request body to a struct:
  return c.Bind().Body(user)
})
```

### Context

Returns a `context.Context` that was previously set with [`SetContext`](#setcontext).
If no context was set, it returns `context.Background()`. Unlike `fiber.Ctx` itself,
the returned context is safe to use after the handler completes.

```go title="Signature"
func (c fiber.Ctx) Context() context.Context
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  ctx := c.Context()
  go doWork(ctx)
  return nil
})
```

### context.Context

`Ctx` implements `context.Context`. However due to [current limitations in how fasthttp](https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945) works, `Deadline()`, `Done()` and `Err()` are no-ops. The `fiber.Ctx` instance is reused after the handler returns and must not be used for asynchronous operations once the handler has completed. Call [`Context`](#context) within the handler to obtain a `context.Context` that can be used outside the handler.

```go title="Signature"
func (c fiber.Ctx) Deadline() (deadline time.Time, ok bool)
func (c fiber.Ctx) Done() <-chan struct{}
func (c fiber.Ctx) Err() error
func (c fiber.Ctx) Value(key any) any
```

```go title="Example"

func doSomething(ctx context.Context) {
  // ...
}

app.Get("/", func(c fiber.Ctx) error {
  doSomething(c)
})
```

#### Value

Value can be used to retrieve [**`Locals`**](#locals).

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Locals(userKey, "admin")
  user := c.Value(userKey) // returns "admin"
})
```

### Drop

Terminates the client connection silently without sending any HTTP headers or response body.

This can be used for scenarios where you want to block certain requests without notifying the client, such as mitigating
DDoS attacks or protecting sensitive endpoints from unauthorized access.

```go title="Signature"
func (c fiber.Ctx) Drop() error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  if c.IP() == "192.168.1.1" {
    return c.Drop()
  }

  return c.SendString("Hello World!")
})
```

### FullPath

Returns the full path of the matched route. This includes any prefixes that were added by [groups](../guide/routing.md#grouping) or mounts.

```go title="Signature"
func (c fiber.Ctx) FullPath() string
```

```go title="Example"
api := app.Group("/api")
api.Get("/users/:id", func(c fiber.Ctx) error {
  return c.JSON(fiber.Map{
    "route": c.FullPath(), // "/api/users/:id"
  })
})

app.Use(func(c fiber.Ctx) error {
  beforeNext := c.FullPath() // "/"

  if err := c.Next(); err != nil {
    return err
  }

  afterNext := c.FullPath() // "/api/users/:id"
  // ... react to the downstream handler's route path
  return nil
})
```

### GetReqHeaders

Returns the HTTP request headers as a map. Because a header can appear multiple times in a request, each key maps to a slice with all values for that header.

```go title="Signature"
func (c fiber.Ctx) GetReqHeaders() map[string][]string
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### GetRespHeader

Returns the HTTP response header specified by the field.

:::tip
The match is **case-insensitive**.
:::

```go title="Signature"
func (c fiber.Ctx) GetRespHeader(key string, defaultValue ...string) string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.GetRespHeader("X-Request-Id")       // "8d7ad5e3-aaf3-450b-a241-2beb887efd54"
  c.GetRespHeader("Content-Type")       // "text/plain"
  c.GetRespHeader("something", "john")  // "john"
  // ..
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### GetRespHeaders

Returns the HTTP response headers as a map. Since a header can be set multiple times in a single request, the values of the map are slices of strings containing all the different values of the header.

```go title="Signature"
func (c fiber.Ctx) GetRespHeaders() map[string][]string
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### GetRouteURL

Generates URLs to named routes, with parameters. URLs are relative, for example: "/user/1831"

```go title="Signature"
func (c fiber.Ctx) GetRouteURL(routeName string, params Map) (string, error)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
    return c.SendString("Home page")
}).Name("home")

app.Get("/user/:id", func(c fiber.Ctx) error {
    return c.SendString(c.Params("id"))
}).Name("user.show")

app.Get("/test", func(c fiber.Ctx) error {
    location, _ := c.GetRouteURL("user.show", fiber.Map{"id": 1})
    return c.SendString(location)
})

// /test returns "/user/1"
```

### HasBody

Returns `true` if the incoming request contains a body or a `Content-Length` header greater than zero.

```go title="Signature"
func (c fiber.Ctx) HasBody() bool
```

```go title="Example"
app.Post("/", func(c fiber.Ctx) error {
  if !c.HasBody() {
    return c.SendStatus(fiber.StatusBadRequest)
  }
  return c.SendString("OK")
})
```

### IsMiddleware

Returns `true` if the current request handler was registered as middleware.

```go title="Signature"
func (c fiber.Ctx) IsMiddleware() bool
```

```go title="Example"
app.Get("/route", func(c fiber.Ctx) error {
  fmt.Println(c.IsMiddleware()) // true
  return c.Next()
}, func(c fiber.Ctx) error {
  fmt.Println(c.IsMiddleware()) // false
  return c.SendStatus(fiber.StatusOK)
})
```

### IsPreflight

Returns `true` if the request is a CORS preflight (`OPTIONS` + `Access-Control-Request-Method` + `Origin`).

```go title="Signature"
func (c fiber.Ctx) IsPreflight() bool
```

```go title="Example"
app.Use(func(c fiber.Ctx) error {
  if c.IsPreflight() {
    return c.SendStatus(fiber.StatusNoContent)
  }
  return c.Next()
})
```

### IsWebSocket

Returns `true` if the request includes a WebSocket upgrade handshake.

```go title="Signature"
func (c fiber.Ctx) IsWebSocket() bool
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  if c.IsWebSocket() {
    // handle websocket
  }
  return c.Next()
})
```

### Locals

Stores variables scoped to the request, making them available only to matching routes. The variables are removed after the request completes. If a stored value implements `io.Closer`, Fiber calls its `Close` method before removal.

:::tip
This is useful if you want to pass some **specific** data to the next middleware. Remember to perform type assertions when retrieving the data to ensure it is of the expected type. You can also use a non-exported type as a key to avoid collisions.
:::

```go title="Signature"
func (c fiber.Ctx) Locals(key any, value ...any) any
```

```go title="Example"

// keyType is an unexported type for keys defined in this package.
// This prevents collisions with keys defined in other packages.
type keyType int

// userKey is the key for user.User values in Contexts. It is
// unexported; clients use user.NewContext and user.FromContext
// instead of using this key directly.
var userKey keyType

app.Use(func(c fiber.Ctx) error {
  c.Locals(userKey, "admin") // Stores the string "admin" under a non-exported type key
  return c.Next()
})

app.Get("/admin", func(c fiber.Ctx) error {
  user, ok := c.Locals(userKey).(string) // Retrieves the data stored under the key and performs a type assertion
  if ok && user == "admin" {
    return c.Status(fiber.StatusOK).SendString("Welcome, admin!")
  }
  return c.SendStatus(fiber.StatusForbidden)
})
```

An alternative version of the `Locals` method that takes advantage of Go's generics feature is also available. This version allows for the manipulation and retrieval of local values within a request's context with a more specific data type.

```go title="Signature"
func Locals[V any](c fiber.Ctx, key any, value ...V) V
```

```go title="Example"
app.Use(func(c fiber.Ctx) error {
  fiber.Locals[string](c, "john", "doe")
  fiber.Locals[int](c, "age", 18)
  fiber.Locals[bool](c, "isHuman", true)
  return c.Next()
})

app.Get("/test", func(c fiber.Ctx) error {
  fiber.Locals[string](c, "john")    // "doe"
  fiber.Locals[int](c, "age")        // 18
  fiber.Locals[bool](c, "isHuman")   // true
  return nil
})
```

Make sure to understand and correctly implement the `Locals` method in both its standard and generic form for better control over route-specific data within your application.

### Matched

Returns `true` if the current request path was matched by the router.

```go title="Signature"
func (c fiber.Ctx) Matched() bool
```

```go title="Example"
app.Use(func(c fiber.Ctx) error {
  if c.Matched() {
    return c.Next()
  }
  return c.Status(fiber.StatusNotFound).SendString("Not Found")
})
```

### Next

When **Next** is called, it executes the next method in the stack that matches the current route. You can pass an error struct within the method that will end the chaining and call the [error handler](../guide/error-handling).

```go title="Signature"
func (c fiber.Ctx) Next() error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  fmt.Println("1st route!")
  return c.Next()
})

app.Get("*", func(c fiber.Ctx) error {
  fmt.Println("2nd route!")
  return c.Next()
})

app.Get("/", func(c fiber.Ctx) error {
  fmt.Println("3rd route!")
  return c.SendString("Hello, World!")
})
```

### OverrideParam

Overwrites the value of an existing route parameter.

:::note
If the parameter does not exist, this method does nothing.
:::

```go title="Signature"
func (c fiber.Ctx) OverrideParam(name, value string)
```

```go title="Example"
// GET http://example.com/user
app.Get("/user/:name", func(c fiber.Ctx) error {
  // mutate parameter
  c.OverrideParam("name", "new value")
  return c.SendString(c.Params("name")) // sends "new value"
})
// GET http://example.com/shop/tech/1
app.Get("/shop/*", func(c fiber.Ctx) error {
  // mutate parameter
  c.OverrideParam("*", "new tech") // replaces "tech/1" with "new tech"
  return c.SendString(c.Params("*")) // sends "new tech"
})

```

Unnamed route parameters can be accessed by their character (`*` or `+`) followed by their position index (e.g., `*1` for the first wildcard, `*2` for the second).

```go title="Example"
// GET /v1/brand/4/shop/blue/xs
app.Get("/v1/*/shop/*", func(c fiber.Ctx) error {
  // mutate parameter
  c.OverrideParam("*1", "updated brand")
  c.OverrideParam("*2", "updated data")

  param1 := c.Params("*1") // "updated brand"
  param2 := c.Params("*2") // "updated data"

  // ...
})
```

### Redirect

Returns the Redirect reference.

For detailed information, check the [Redirect](./redirect.md) documentation.

```go title="Signature"
func (c fiber.Ctx) Redirect() *Redirect
```

```go title="Example"
app.Get("/coffee", func(c fiber.Ctx) error {
    return c.Redirect().To("/teapot")
})

app.Get("/teapot", func(c fiber.Ctx) error {
    return c.Status(fiber.StatusTeapot).Send("🍵 short and stout 🍵")
})
```

### Request

Returns the [*fasthttp.Request](https://pkg.go.dev/github.com/valyala/fasthttp#Request) pointer.

```go title="Signature"
func (c fiber.Ctx) Request() *fasthttp.Request
```

:::info
Returns `nil` if the context has been released (e.g., after the handler completes and the context is returned to the pool).
:::

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Request().Header.Method()
  // => []byte("GET")
})
```

### RequestCtx

Returns [\*fasthttp.RequestCtx](https://pkg.go.dev/github.com/valyala/fasthttp#RequestCtx) that is compatible with the `context.Context` interface that requires a deadline, a cancellation signal, and other values across API boundaries.

```go title="Signature"
func (c fiber.Ctx) RequestCtx() *fasthttp.RequestCtx
```

:::info
Please read the [Fasthttp Documentation](https://pkg.go.dev/github.com/valyala/fasthttp?tab=doc) for more information.
:::

### Reset

Resets the context fields by the given request when using server handlers.

```go title="Signature"
func (c fiber.Ctx) Reset(fctx *fasthttp.RequestCtx)
```

It is used outside of the Fiber Handlers to reset the context for the next request.

### Response

Returns the [\*fasthttp.Response](https://pkg.go.dev/github.com/valyala/fasthttp#Response) pointer.

```go title="Signature"
func (c fiber.Ctx) Response() *fasthttp.Response
```

:::info
Returns `nil` if the context has been released (e.g., after the handler completes and the context is returned to the pool).
:::

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Response().BodyWriter().Write([]byte("Hello, World!"))
  // => "Hello, World!"
  return nil
})
```

### RestartRouting

Instead of executing the next method when calling [Next](ctx.md#next), **RestartRouting** restarts execution from the first method that matches the current route. This may be helpful after overriding the path, i.e., an internal redirect. Note that handlers might be executed again, which could result in an infinite loop.

```go title="Signature"
func (c fiber.Ctx) RestartRouting() error
```

```go title="Example"
app.Get("/new", func(c fiber.Ctx) error {
  return c.SendString("From /new")
})

app.Get("/old", func(c fiber.Ctx) error {
  c.Path("/new")
  return c.RestartRouting()
})
```

### Route

Returns the matched [Route](https://pkg.go.dev/github.com/gofiber/fiber?tab=doc#Route) struct.

```go title="Signature"
func (c fiber.Ctx) Route() *Route
```

```go title="Example"
// http://localhost:8080/hello

app.Get("/hello/:name", func(c fiber.Ctx) error {
  r := c.Route()
  fmt.Println(r.Method, r.Path, r.Params, r.Handlers)
  // GET /hello/:name handler [name]

  // ...
})
```

:::caution
Do not rely on `c.Route()` in middlewares **before** calling `c.Next()` - `c.Route()` returns the **last executed route**.
:::

```go title="Example"
func MyMiddleware() fiber.Handler {
  return func(c fiber.Ctx) error {
    beforeNext := c.Route().Path // Will be '/'
    err := c.Next()
    afterNext := c.Route().Path // Will be '/hello/:name'
    return err
  }
}
```

### SetContext

Sets the base `context.Context` used by [`Context`](#context). Use this to
propagate deadlines, cancellation signals, or values to asynchronous operations.

```go title="Signature"
func (c fiber.Ctx) SetContext(ctx context.Context)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.SetContext(context.WithValue(context.Background(), "user", "alice"))
  ctx := c.Context()
  go doWork(ctx)
  return nil
})
```

### String

Returns a unique string representation of the context.

```go title="Signature"
func (c fiber.Ctx) String() string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.String() // => "#0000000100000001 - 127.0.0.1:3000 <-> 127.0.0.1:61516 - GET http://localhost:3000/"

  // ...
})
```

### ViewBind

Adds variables to the default view variable map binding to the template engine.
Variables are read by the `Render` method and may be overwritten.

```go title="Signature"
func (c fiber.Ctx) ViewBind(vars Map) error
```

```go title="Example"
app.Use(func(c fiber.Ctx) error {
  c.ViewBind(fiber.Map{
    "Title": "Hello, World!",
  })
  return c.Next()
})

app.Get("/", func(c fiber.Ctx) error {
  return c.Render("xxx.tmpl", fiber.Map{}) // Render will use the Title variable
})
```

## Request

Methods which operate on the incoming request.

:::tip
Use `c.Req()` to limit gopls suggestions to only these methods!
:::

### AcceptEncoding

Returns the `Accept-Encoding` request header.

```go title="Signature"
func (c fiber.Ctx) AcceptEncoding() string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.AcceptEncoding() // "gzip, br"
  return nil
})
```

### AcceptLanguage

Returns the `Accept-Language` request header.

```go title="Signature"
func (c fiber.Ctx) AcceptLanguage() string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.AcceptLanguage() // "en-US,en;q=0.9"
  return nil
})
```

### Accepts

Checks if the specified **extensions** or **content** **types** are acceptable.

:::info
Based on the request’s [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) HTTP header.
:::

```go title="Signature"
func (c fiber.Ctx) Accepts(offers ...string) string
func (c fiber.Ctx) AcceptsCharsets(offers ...string) string
func (c fiber.Ctx) AcceptsEncodings(offers ...string) string
func (c fiber.Ctx) AcceptsLanguages(offers ...string) string
func (c fiber.Ctx) AcceptsLanguagesExtended(offers ...string) string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Accepts("html")             // "html"
  c.Accepts("text/html")        // "text/html"
  c.Accepts("json", "text")     // "json"
  c.Accepts("application/json") // "application/json"
  c.Accepts("text/plain", "application/json") // "application/json", due to quality
  c.Accepts("image/png")        // ""
  c.Accepts("png")              // ""
  // ...
})
```

```go title="Example 2"
// Accept: text/html, text/*, application/json, */*; q=0

app.Get("/", func(c fiber.Ctx) error {
  c.Accepts("text/plain", "application/json") // "application/json", due to specificity
  c.Accepts("application/json", "text/html") // "text/html", due to first match
  c.Accepts("image/png")                      // "", due to */* with q=0 is Not Acceptable
  // ...
})
```

Media-Type parameters are supported.

```go title="Example 3"
// Accept: text/plain, application/json; version=1; foo=bar

app.Get("/", func(c fiber.Ctx) error {
  // Extra parameters in the accept are ignored
  c.Accepts("text/plain;format=flowed") // "text/plain;format=flowed"

  // An offer must contain all parameters present in the Accept type
  c.Accepts("application/json") // ""

  // Parameter order and capitalization do not matter. Quotes on values are stripped.
  c.Accepts(`application/json;foo="bar";VERSION=1`) // "application/json;foo="bar";VERSION=1"
})
```

```go title="Example 4"
// Accept: text/plain;format=flowed;q=0.9, text/plain
// i.e., "I prefer text/plain;format=flowed less than other forms of text/plain"

app.Get("/", func(c fiber.Ctx) error {
  // Beware: the order in which offers are listed matters.
  // Although the client specified they prefer not to receive format=flowed,
  // the text/plain Accept matches with "text/plain;format=flowed" first, so it is returned.
  c.Accepts("text/plain;format=flowed", "text/plain") // "text/plain;format=flowed"

  // Here, things behave as expected:
  c.Accepts("text/plain", "text/plain;format=flowed") // "text/plain"
})
```

Fiber provides similar functions for the other accept headers.

For `Accept-Language`, Fiber uses the [Basic Filtering](https://www.rfc-editor.org/rfc/rfc4647#section-3.3.1) algorithm. A language range matches an offer only if it exactly equals the tag or is a prefix followed by a hyphen. For example, the range `en` matches `en-US`, but `en-US` does not match `en`.

`AcceptsLanguagesExtended` applies [Extended Filtering](https://www.rfc-editor.org/rfc/rfc4647#section-3.3.2) where `*` may match zero or more subtags and wildcard matches can slide across subtags unless blocked by a singleton like `x`.

```go
// Accept-Charset: utf-8, iso-8859-1;q=0.2
// Accept-Encoding: gzip, compress;q=0.2
// Accept-Language: en;q=0.8, nl, ru

app.Get("/", func(c fiber.Ctx) error {
  c.AcceptsCharsets("utf-16", "iso-8859-1")
  // "iso-8859-1"

  c.AcceptsEncodings("compress", "br")
  // "compress"

  c.AcceptsLanguages("pt", "nl", "ru")
  // "nl"

  c.AcceptsLanguagesExtended("en-US", "fr-CA")
  // depends on extended ranges in the request header
  // ...
})
```

### AcceptsEventStream

Returns `true` when the `Accept` header allows `text/event-stream`.

```go title="Signature"
func (c fiber.Ctx) AcceptsEventStream() bool
```

```go title="Example"
// Accept: text/html, application/json;q=0.9

app.Get("/", func(c fiber.Ctx) error {
  c.AcceptsEventStream() // false
  return nil
})
```

### AcceptsHTML

Returns `true` when the `Accept` header allows HTML.

```go title="Signature"
func (c fiber.Ctx) AcceptsHTML() bool
```

```go title="Example"
// Accept: text/html, application/json;q=0.9

app.Get("/", func(c fiber.Ctx) error {
  c.AcceptsHTML() // true
  return nil
})
```

### AcceptsJSON

Returns `true` when the `Accept` header allows JSON.

```go title="Signature"
func (c fiber.Ctx) AcceptsJSON() bool
```

```go title="Example"
// Accept: text/html, application/json;q=0.9

app.Get("/", func(c fiber.Ctx) error {
  c.AcceptsJSON() // true
  return nil
})
```

### AcceptsXML

Returns `true` when the `Accept` header allows XML.

```go title="Signature"
func (c fiber.Ctx) AcceptsXML() bool
```

```go title="Example"
// Accept: text/html, application/json;q=0.9

app.Get("/", func(c fiber.Ctx) error {
  c.AcceptsXML() // false
  return nil
})
```

### BaseURL

Returns the base URL (**protocol** + **host**) as a `string`.

```go title="Signature"
func (c fiber.Ctx) BaseURL() string
```

```go title="Example"
// GET https://example.com/page#chapter-1

app.Get("/", func(c fiber.Ctx) error {
  c.BaseURL() // "https://example.com"
  // ...
})
```

### Body

As per the header `Content-Encoding`, this method will try to perform a file decompression from the **body** bytes. In case no `Content-Encoding` header is sent (or when it is set to `identity`), it will perform as [BodyRaw](#bodyraw). If an unknown or unsupported encoding is encountered, the response status will be `415 Unsupported Media Type` or `501 Not Implemented`. Decompression is bounded by the app [BodyLimit](./fiber.md#bodylimit).

```go title="Signature"
func (c fiber.Ctx) Body() []byte
```

```go title="Example"
// echo 'user=john' | gzip | curl -v -i --data-binary @- -H "Content-Encoding: gzip" http://localhost:8080

app.Post("/", func(c fiber.Ctx) error {
  // Decompress body from POST request based on the Content-Encoding and return the raw content:
  return c.Send(c.Body()) // []byte("user=john")
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### BodyRaw

Returns the raw request **body**.

```go title="Signature"
func (c fiber.Ctx) BodyRaw() []byte
```

```go title="Example"
// curl -X POST http://localhost:8080 -d user=john

app.Post("/", func(c fiber.Ctx) error {
  // Get raw body from POST request:
  return c.Send(c.BodyRaw()) // []byte("user=john")
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### Charset

Returns the `charset` parameter from the `Content-Type` header.

```go title="Signature"
func (c fiber.Ctx) Charset() string
```

```go title="Example"
// Content-Type: application/json; charset=utf-8

app.Post("/", func(c fiber.Ctx) error {
  c.Charset() // "utf-8"
  return nil
})
```

### ClientHelloInfo

`ClientHelloInfo` contains information from a ClientHello message to guide application logic in the `GetCertificate` and `GetConfigForClient` callbacks.
Refer to the [ClientHelloInfo](https://golang.org/pkg/crypto/tls/#ClientHelloInfo) struct documentation for details on the returned struct.

```go title="Signature"
func (c fiber.Ctx) ClientHelloInfo() *tls.ClientHelloInfo
```

```go title="Example"
// GET http://example.com/hello
app.Get("/hello", func(c fiber.Ctx) error {
  chi := c.ClientHelloInfo()
  // ...
})
```

### Cookies

Gets a cookie value by key. You can pass an optional default value that will be returned if the cookie key does not exist.

```go title="Signature"
func (c fiber.Ctx) Cookies(key string, defaultValue ...string) string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  // Get cookie by key:
  c.Cookies("name")         // "john"
  c.Cookies("empty", "doe") // "doe"
  // ...
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Use [`App.GetString`](./app.md#getstring) or [`App.GetBytes`](./app.md#getbytes) when immutability is enabled, or manually copy values (for example with [`utils.CopyString`](https://github.com/gofiber/utils) / `utils.CopyBytes`) when it's disabled. [Read more...](../#zero-allocation)
:::

### FormFile

MultipartForm files can be retrieved by name, the **first** file from the given key is returned.

```go title="Signature"
func (c fiber.Ctx) FormFile(key string) (*multipart.FileHeader, error)
```

```go title="Example"
app.Post("/", func(c fiber.Ctx) error {
  // Get first file from form field "document":
  file, err := c.FormFile("document")

  // Save file to root directory:
  return c.SaveFile(file, fmt.Sprintf("./%s", file.Filename))
})
```

### FormValue

Form values can be retrieved by name, the **first** value for the given key is returned.

```go title="Signature"
func (c fiber.Ctx) FormValue(key string, defaultValue ...string) string
```

```go title="Example"
app.Post("/", func(c fiber.Ctx) error {
  // Get first value from form field "name":
  c.FormValue("name")
  // => "john" or "" if not exist

  // ..
})
```

:::info

The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)

:::

### Fresh

When the response is still **fresh** in the client's cache **true** is returned; 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, `Fresh` will return false to make handling these requests transparent.

Read more on [https://expressjs.com/en/4x/api.html\#req.fresh](https://expressjs.com/en/4x/api.html#req.fresh)

```go title="Signature"
func (c fiber.Ctx) Fresh() bool
```

### FullURL

Returns the full request URL (protocol + host + original URL).

```go title="Signature"
func (c fiber.Ctx) FullURL() string
```

```go title="Example"
// GET http://example.com/search?q=fiber

app.Get("/", func(c fiber.Ctx) error {
  c.FullURL() // "http://example.com/search?q=fiber"
  return nil
})
```

### Get

Returns the HTTP request header specified by the field.

:::tip
The match is **case-insensitive**.
:::

```go title="Signature"
func (c fiber.Ctx) Get(key string, defaultValue ...string) string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Get("Content-Type")       // "text/plain"
  c.Get("CoNtEnT-TypE")       // "text/plain"
  c.Get("something", "john")  // "john"
  // ..
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### HasHeader

Reports whether the request includes a header with the given key.

```go title="Signature"
func (c fiber.Ctx) HasHeader(key string) bool
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.HasHeader("X-Trace-Id")
  return nil
})
```

### Host

Returns the host derived from the [Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host) HTTP header.

In a network context, [`Host`](#host) refers to the combination of a hostname and potentially a port number used for connecting, while [`Hostname`](#hostname) refers specifically to the name assigned to a device on a network, excluding any port information.

```go title="Signature"
func (c fiber.Ctx) Host() string
```

```go title="Example"
// GET http://google.com:8080/search

app.Get("/", func(c fiber.Ctx) error {
  c.Host()      // "google.com:8080"
  c.Hostname()  // "google.com"

  // ...
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### Hostname

Returns the hostname derived from the [Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host) HTTP header.

```go title="Signature"
func (c fiber.Ctx) Hostname() string
```

```go title="Example"
// GET http://google.com/search

app.Get("/", func(c fiber.Ctx) error {
  c.Hostname() // "google.com"

  // ...
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### IP

Returns the remote IP address of the request.

```go title="Signature"
func (c fiber.Ctx) IP() string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.IP() // "127.0.0.1"

  // ...
})
```

:::info
By default, `c.IP()` returns the remote IP address from the TCP connection. When your Fiber app is behind a reverse proxy (like Nginx, Traefik, or a load balancer), you need to configure **both** [`TrustProxy`](fiber.md#trustproxy) and [`ProxyHeader`](fiber.md#proxyheader) to read the client IP from proxy headers like `X-Forwarded-For`.

**Important:** You must enable `TrustProxy` and configure trusted proxy IPs to prevent header spoofing. Simply setting `ProxyHeader` alone will not work.

**Note:** When using a proxy header such as `X-Forwarded-For`, `c.IP()` returns the raw header value unless [`EnableIPValidation`](fiber.md#enableipvalidation) is enabled. For `X-Forwarded-For`, this raw value may be a comma-separated list of IPs; enable `EnableIPValidation` if you need `c.IP()` to return a single, validated client IP.
:::

#### Configuration for apps behind a reverse proxy

```go title="Example - Basic Configuration"
app := fiber.New(fiber.Config{
  // Enable proxy support
  TrustProxy: true,
  // Specify which header contains the real client IP
  ProxyHeader: fiber.HeaderXForwardedFor,
  // Configure which proxy IPs to trust
  TrustProxyConfig: fiber.TrustProxyConfig{
    // Trust private IP ranges (for internal load balancers)
    Private: true,
    // Or specify exact proxy IPs/ranges
    // Proxies: []string{"10.10.0.58", "192.168.0.0/24"},
  },
})
```

```go title="Example - Specific Proxy IPs"
app := fiber.New(fiber.Config{
  TrustProxy: true,
  ProxyHeader: fiber.HeaderXForwardedFor,
  TrustProxyConfig: fiber.TrustProxyConfig{
    // Trust only specific proxy IP addresses
    Proxies: []string{"10.10.0.58", "192.168.1.0/24"},
  },
})
```

See [`TrustProxy`](fiber.md#trustproxy) and [`TrustProxyConfig`](fiber.md#trustproxyconfig) for more details on security considerations and configuration options.

### IPs

Returns an array of IP addresses specified in the [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) request header.

```go title="Signature"
func (c fiber.Ctx) IPs() []string
```

```go title="Example"
// X-Forwarded-For: proxy1, 127.0.0.1, proxy3

app.Get("/", func(c fiber.Ctx) error {
  c.IPs() // ["proxy1", "127.0.0.1", "proxy3"]

  // ...
})
```

:::caution
Improper use of the X-Forwarded-For header can be a security risk. For details, see the [Security and privacy concerns](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For#security_and_privacy_concerns) section.
:::

### Is

Returns the matching **content type**, if the incoming request’s [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) HTTP header field matches the [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) specified by the type parameter.

:::info
If the request has **no** body, it returns **false**.
:::

```go title="Signature"
func (c fiber.Ctx) Is(extension string) bool
```

```go title="Example"
// Content-Type: text/html; charset=utf-8

app.Get("/", func(c fiber.Ctx) error {
  c.Is("html")  // true
  c.Is(".html") // true
  c.Is("json")  // false

  // ...
})
```

### IsForm

Reports whether the `Content-Type` header is form-encoded.

```go title="Signature"
func (c fiber.Ctx) IsForm() bool
```

```go title="Example"
// Content-Type: application/x-www-form-urlencoded

app.Post("/", func(c fiber.Ctx) error {
  c.IsForm() // true
  return nil
})
```

### IsFromLocal

Returns `true` if the request came from localhost.

```go title="Signature"
func (c fiber.Ctx) IsFromLocal() bool
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  // If request came from localhost, return true; else return false
  c.IsFromLocal()

  // ...
})
```

### IsFromUnixSocket

Returns `true` if the request came in over a Unix domain socket.

```go title="Signature"
func (c fiber.Ctx) IsFromUnixSocket() bool
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  if c.IsFromUnixSocket() {
    return c.SendString("Connected via Unix socket")
  }
  return c.SendString("Connected via TCP")
})
```

### IsJSON

Reports whether the `Content-Type` header is JSON.

```go title="Signature"
func (c fiber.Ctx) IsJSON() bool
```

```go title="Example"
// Content-Type: application/json; charset=utf-8

app.Post("/", func(c fiber.Ctx) error {
  c.IsJSON() // true
  return nil
})
```

### IsMultipart

Reports whether the `Content-Type` header is multipart form data.

```go title="Signature"
func (c fiber.Ctx) IsMultipart() bool
```

```go title="Example"
// Content-Type: multipart/form-data; boundary=abc123

app.Post("/", func(c fiber.Ctx) error {
  c.IsMultipart() // true
  return nil
})
```

### IsProxyTrusted

Checks the trustworthiness of the remote IP.
If [`TrustProxy`](fiber.md#trustproxy) is `false`, it returns `true`.
`IsProxyTrusted` can check the remote IP by proxy ranges and IP map.

```go title="Signature"
func (c fiber.Ctx) IsProxyTrusted() bool
```

```go title="Example"
app := fiber.New(fiber.Config{
  // TrustProxy enables the trusted proxy check
  TrustProxy: true,
  // TrustProxyConfig allows for configuring trusted proxies.
  // Proxies is a list of trusted proxy IP ranges/addresses
  TrustProxyConfig: fiber.TrustProxyConfig{
    Proxies: []string{"0.8.0.0", "1.1.1.1/30"}, // IP address or IP address range
    Loopback: true,   // Trust loopback addresses (127.0.0.0/8, ::1/128)
    UnixSocket: true, // Trust Unix domain socket connections
  },
})

app.Get("/", func(c fiber.Ctx) error {
  // If request came from trusted proxy, return true; else return false
  c.IsProxyTrusted()

  // ...
})
```

### MediaType

Returns the MIME type from the `Content-Type` header without parameters.

```go title="Signature"
func (c fiber.Ctx) MediaType() string
```

```go title="Example"
// Content-Type: application/json; charset=utf-8

app.Post("/", func(c fiber.Ctx) error {
  c.MediaType() // "application/json"
  return nil
})
```

### Method

Returns a string corresponding to the HTTP method of the request: `GET`, `POST`, `PUT`, and so on.
Optionally, you can override the method by passing a string.

```go title="Signature"
func (c fiber.Ctx) Method(override ...string) string
```

```go title="Example"
app.Post("/override", func(c fiber.Ctx) error {
  c.Method()          // "POST"

  c.Method("GET")
  c.Method()          // "GET"

  // ...
})
```

### MultipartForm

To access multipart form entries, you can parse the binary with `MultipartForm()`. This returns a `*multipart.Form`, allowing you to access form values and files. Parsing is bounded by the app [BodyLimit](./fiber.md#bodylimit).

```go title="Signature"
func (c fiber.Ctx) MultipartForm() (*multipart.Form, error)
```

```go title="Example"
app.Post("/", func(c fiber.Ctx) error {
  // Parse the multipart form:
  if form, err := c.MultipartForm(); err == nil {
    // => *multipart.Form

    if token := form.Value["token"]; len(token) > 0 {
      // Get key value:
      fmt.Println(token[0])
    }

    // Get all files from "documents" key:
    files := form.File["documents"]
    // => []*multipart.FileHeader

    // Loop through files:
    for _, file := range files {
      fmt.Println(file.Filename, file.Size, file.Header["Content-Type"][0])
      // => "tutorial.pdf" 360641 "application/pdf"

      // Save the files to disk:
      if err := c.SaveFile(file, fmt.Sprintf("./%s", file.Filename)); err != nil {
        return err
      }
    }
  }

  return nil
})
```

### OriginalURL

Returns the original request URL.

```go title="Signature"
func (c fiber.Ctx) OriginalURL() string
```

```go title="Example"
// GET http://example.com/search?q=something

app.Get("/", func(c fiber.Ctx) error {
  c.OriginalURL() // "/search?q=something"

  // ...
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

### Params

This method can be used to get the route parameters. You can pass an optional default value that will be returned if the param key does not exist.

:::info
Defaults to an empty string \(`""`\) if the param **doesn't** exist.
:::

```go title="Signature"
func (c fiber.Ctx) Params(key string, defaultValue ...string) string
```

```go title="Example"
// GET http://example.com/user/fenny
app.Get("/user/:name", func(c fiber.Ctx) error {
  c.Params("name") // "fenny"

  // ...
})

// GET http://example.com/user/fenny/123
app.Get("/user/*", func(c fiber.Ctx) error {
  c.Params("*")  // "fenny/123"
  c.Params("*1") // "fenny/123"

  // ...
})
```

Unnamed route parameters \(\*, +\) can be fetched by the **character** and the **counter** in the route.

```go title="Example"
// ROUTE: /v1/*/shop/*
// GET:   /v1/brand/4/shop/blue/xs
c.Params("*1")  // "brand/4"
c.Params("*2")  // "blue/xs"
```

For reasons of **downward compatibility**, the first parameter segment for the parameter character can also be accessed without the counter.

```go title="Example"
app.Get("/v1/*/shop/*", func(c fiber.Ctx) error {
  c.Params("*") // outputs the value of the first wildcard segment
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

In certain scenarios, it can be useful to have an alternative approach to handle different types of parameters, not
just strings. This can be achieved using a generic `Params` function known as `Params[V GenericType](c fiber.Ctx, key string, defaultValue ...V) V`.
This function is capable of parsing a route parameter and returning a value of a type that is assumed and specified by `V GenericType`.

```go title="Signature"
func Params[V GenericType](c fiber.Ctx, key string, defaultValue ...V) V
```

```go title="Example"
// GET http://example.com/user/114
app.Get("/user/:id", func(c fiber.Ctx) error{
  fiber.Params[string](c, "id") // returns "114" as string.
  fiber.Params[int](c, "id")    // returns 114 as integer
  fiber.Params[string](c, "number") // returns "" (default string type)
  fiber.Params[int](c, "number")    // returns 0 (default integer value type)
})
```

The generic `Params` function supports returning the following data types based on `V GenericType`:

- Integer: `int`, `int8`, `int16`, `int32`, `int64`
- Unsigned integer: `uint`, `uint8`, `uint16`, `uint32`, `uint64`
- Floating-point numbers: `float32`, `float64`
- Boolean: `bool`
- String: `string`
- Byte array: `[]byte`

### Path

Contains the path part of the request URL. Optionally, you can override the path by passing a string. For internal redirects, you might want to call [RestartRouting](ctx.md#restartrouting) instead of [Next](ctx.md#next).

```go title="Signature"
func (c fiber.Ctx) Path(override ...string) string
```

```go title="Example"
// GET http://example.com/users?sort=desc

app.Get("/users", func(c fiber.Ctx) error {
  c.Path()       // "/users"

  c.Path("/john")
  c.Path()       // "/john"

  // ...
})
```

### Port

Returns the remote port of the request.

```go title="Signature"
func (c fiber.Ctx) Port() string
```

```go title="Example"
// GET http://example.com:8080

app.Get("/", func(c fiber.Ctx) error {
  c.Port() // "8080"

  // ...
})
```

### Protocol

Contains the request protocol string: `http` or `https` for **TLS** requests.

```go title="Signature"
func (c fiber.Ctx) Protocol() string
```

```go title="Example"
// GET http://example.com

app.Get("/", func(c fiber.Ctx) error {
  c.Protocol() // "http"

  // ...
})
```

### Queries

`Queries` is a function that returns an object containing a property for each query string parameter in the route.

```go title="Signature"
func (c fiber.Ctx) Queries() map[string]string
```

```go title="Example"
// GET http://example.com/?name=alex&want_pizza=false&id=

app.Get("/", func(c fiber.Ctx) error {
    m := c.Queries()
    m["name"]        // "alex"
    m["want_pizza"]  // "false"
    m["id"]          // ""
    // ...
})
```

```go title="Example"
// GET http://example.com/?field1=value1&field1=value2&field2=value3

app.Get("/", func (c fiber.Ctx) error {
    m := c.Queries()
    m["field1"] // "value2"
    m["field2"] // "value3"
})
```

```go title="Example"
// GET http://example.com/?list_a=1&list_a=2&list_a=3&list_b[]=1&list_b[]=2&list_b[]=3&list_c=1,2,3

app.Get("/", func(c fiber.Ctx) error {
    m := c.Queries()
    m["list_a"] // "3"
    m["list_b[]"] // "3"
    m["list_c"] // "1,2,3"
})
```

```go title="Example"
// GET /api/posts?filters.author.name=John&filters.category.name=Technology

app.Get("/", func(c fiber.Ctx) error {
    m := c.Queries()
    m["filters.author.name"] // John
    m["filters.category.name"] // Technology
})
```

```go title="Example"
// GET /api/posts?tags=apple,orange,banana&filters[tags]=apple,orange,banana&filters[category][name]=fruits&filters.tags=apple,orange,banana&filters.category.name=fruits

app.Get("/", func(c fiber.Ctx) error {
    m := c.Queries()
    m["tags"] // apple,orange,banana
    m["filters[tags]"] // apple,orange,banana
    m["filters[category][name]"] // fruits
    m["filters.tags"] // apple,orange,banana
    m["filters.category.name"] // fruits
})
```

### Query

This method returns a string corresponding to a query string parameter by name. You can pass an optional default value that will be returned if the query key does not exist.

:::info
If there is **no** query string, it returns an **empty string**.
:::

```go title="Signature"
func (c fiber.Ctx) Query(key string, defaultValue ...string) string
```

```go title="Example"
// GET http://example.com/?order=desc&brand=nike

app.Get("/", func(c fiber.Ctx) error {
  c.Query("order")         // "desc"
  c.Query("brand")         // "nike"
  c.Query("empty", "nike") // "nike"

  // ...
})
```

:::info
The returned value is valid only within the handler. Do not store references.
Make copies or use the [**`Immutable`**](./fiber.md#immutable) setting instead. [Read more...](../#zero-allocation)
:::

In certain scenarios, it can be useful to have an alternative approach to handle different types of query parameters, not
just strings. This can be achieved using a generic `Query` function known as `Query[V GenericType](c fiber.Ctx, key string, defaultValue ...V) V`.
This function is capable of parsing a query string and returning a value of a type that is assumed and specified by `V GenericType`.

Here is the signature for the generic `Query` function:

```go title="Signature"
func Query[V GenericType](c fiber.Ctx, key string, defaultValue ...V) V
```

```go title="Example"
// GET http://example.com/?page=1&brand=nike&new=true

app.Get("/", func(c fiber.Ctx) error {
  fiber.Query[int](c, "page")     // 1
  fiber.Query[string](c, "brand") // "nike"
  fiber.Query[bool](c, "new")     // true

  // ...
})
```

In this case, `Query[V GenericType](c Ctx, key string, defaultValue ...V) V` can retrieve `page` as an integer, `brand` as a string, and `new` as a boolean. The function uses the appropriate parsing function for each specified type to ensure the correct type is returned. This simplifies the retrieval process of different types of query parameters, making your controller actions cleaner.
The generic `Query` function supports returning the following data types based on `V GenericType`:

- Integer: `int`, `int8`, `int16`, `int32`, `int64`
- Unsigned integer: `uint`, `uint8`, `uint16`, `uint32`, `uint64`
- Floating-point numbers: `float32`, `float64`
- Boolean: `bool`
- String: `string`
- Byte array: `[]byte`

### Range

Returns a struct containing the type and a slice of ranges.
Only the canonical `bytes` unit is recognized and any optional
whitespace around range specifiers will be ignored, as specified
in RFC 9110.
If none of the requested ranges are satisfiable, the method automatically
sets the HTTP status code to **416 Range Not Satisfiable** and populates the
`Content-Range` header with the current representation size.

```go title="Signature"
func (c fiber.Ctx) Range(size int64) (Range, error)
```

```go title="Example"
// Range: bytes=500-700, 700-900
app.Get("/", func(c fiber.Ctx) error {
  r := c.Range(1000)
  if r.Type == "bytes" {
      for _, rng := range r.Ranges {
      fmt.Println(rng)
      // [500, 700]
    }
  }
})
```

### Referer

Returns the `Referer` request header.

```go title="Signature"
func (c fiber.Ctx) Referer() string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Referer() // "https://example.com"
  return nil
})
```

### RequestID

```go title="Signature"
func (c fiber.Ctx) RequestID() string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.RequestID() // "8d7ad5e3-aaf3-450b-a241-2beb887efd54"
  return nil
})
```

### SaveFile

Method is used to save **any** multipart file to disk.

```go title="Signature"
func (c fiber.Ctx) SaveFile(fh *multipart.FileHeader, path string) error
```

```go title="Example"
app.Post("/", func(c fiber.Ctx) error {
  // Parse the multipart form:
  if form, err := c.MultipartForm(); err == nil {
    // => *multipart.Form

    // Get all files from "documents" key:
    files := form.File["documents"]
    // => []*multipart.FileHeader

    // Loop through files:
    for _, file := range files {
      fmt.Println(file.Filename, file.Size, file.Header["Content-Type"][0])
      // => "tutorial.pdf" 360641 "application/pdf"

      // Save the files to disk:
      if err := c.SaveFile(file, fmt.Sprintf("./%s", file.Filename)); err != nil {
        return err
      }
    }
    return err
  }
})
```

### SaveFileToStorage

Method is used to save **any** multipart file to an external storage system.

```go title="Signature"
func (c fiber.Ctx) SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error
```

```go title="Example"
storage := memory.New()

app.Post("/", func(c fiber.Ctx) error {
  // Parse the multipart form:
  if form, err := c.MultipartForm(); err == nil {
    // => *multipart.Form

    // Get all files from "documents" key:
    files := form.File["documents"]
    // => []*multipart.FileHeader

    // Loop through files:
    for _, file := range files {
      fmt.Println(file.Filename, file.Size, file.Header["Content-Type"][0])
      // => "tutorial.pdf" 360641 "application/pdf"

      // Save the files to storage:
      if err := c.SaveFileToStorage(file, fmt.Sprintf("./%s", file.Filename), storage); err != nil {
        return err
      }
    }
    return err
  }
})
```

### Schema

Contains the request protocol string: `http` or `https` for TLS requests.

:::info
Please use [`Config.TrustProxy`](fiber.md#trustproxy) to prevent header spoofing if your app is behind a proxy.
:::

```go title="Signature"
func (c fiber.Ctx) Schema() string
```

```go title="Example"
// GET http://example.com

app.Get("/", func(c fiber.Ctx) error {
  c.Schema() // "http"

  // ...
})
```

### Secure

A boolean property that is `true` if a **TLS** connection is established.

```go title="Signature"
func (c fiber.Ctx) Secure() bool
```

```go title="Example"
// Secure() method is equivalent to:
c.Protocol() == "https"
```

### Stale

When the client's cached response is **stale**, this method returns **true**. It
is the logical complement of [`Fresh`](#fresh), which checks whether the cached
representation is still valid.

[https://expressjs.com/en/4x/api.html#req.stale](https://expressjs.com/en/4x/api.html#req.stale)

```go title="Signature"
func (c fiber.Ctx) Stale() bool
```

### Subdomains

Returns a slice with the host’s sub-domain labels. The dot-separated parts that precede the registrable domain (`example`) and the top-level domain (ex: `com`).

The `subdomain offset` (default `2`) tells Fiber how many labels, counting from the right-hand side, are always discarded.
Passing an `offset` argument lets you override that value for a single call.

```go
func (c fiber.Ctx) Subdomains(offset ...int) []string
```

| `offset`               | Result                                  | Meaning                                       |
| ---------------------- | --------------------------------------- | --------------------------------------------- |
| *omitted* → **2**      | trim 2 right-most labels                | drop the registrable domain **and** the TLD   |
| `1` to `len(labels)-1` | trim exactly `offset` right-most labels | custom trimming of available labels           |
| `>= len(labels)`       | **return `[]`**                         | offset exceeds available labels → empty slice |
| `0`                    | **return every label**                  | keep the entire host unchanged                |
| `< 0`                  | **return `[]`**                         | negative offsets are invalid → empty slice    |

#### Example

```go
// Host: "tobi.ferrets.example.com"

app.Get("/", func(c fiber.Ctx) error {
  c.Subdomains()    // ["tobi", "ferrets"]
  c.Subdomains(1)   // ["tobi", "ferrets", "example"]
  c.Subdomains(0)   // ["tobi", "ferrets", "example", "com"]
  c.Subdomains(-1)  // []
  // ...
})
```

### UserAgent

Returns the `User-Agent` request header.

```go title="Signature"
func (c fiber.Ctx) UserAgent() string
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.UserAgent() // "Mozilla/5.0 ..."
  return nil
})
```

### XHR

A boolean property that is `true` if the request’s [X-Requested-With](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) header field is [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest), indicating that the request was issued by a client library (such as [jQuery](https://api.jquery.com/jQuery.ajax/)).

```go title="Signature"
func (c fiber.Ctx) XHR() bool
```

```go title="Example"
// X-Requested-With: XMLHttpRequest

app.Get("/", func(c fiber.Ctx) error {
  c.XHR() // true

  // ...
})
```

## Response

Methods which modify the response object.

:::tip
Use `c.Res()` to limit gopls suggestions to only these methods!
:::

### Append

Appends the specified **value** to the HTTP response header field.

:::caution
If the header is **not** already set, it creates the header with the specified value.
:::

```go title="Signature"
func (c fiber.Ctx) Append(field string, values ...string)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Append("Link", "http://google.com", "http://localhost")
  // => Link: http://google.com, http://localhost

  c.Append("Link", "Test")
  // => Link: http://google.com, http://localhost, Test

  // ...
})
```

### Attachment

Sets the HTTP response [Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) header field to `attachment`.

```go title="Signature"
func (c fiber.Ctx) Attachment(filename ...string)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Attachment()
  // => Content-Disposition: attachment

  c.Attachment("./upload/images/logo.png")
  // => Content-Disposition: attachment; filename="logo.png"
  // => Content-Type: image/png

  // ...
})
```

Non-ASCII filenames are encoded using the `filename*` parameter as defined in
[RFC 6266](https://www.rfc-editor.org/rfc/rfc6266) and
[RFC 8187](https://www.rfc-editor.org/rfc/rfc8187):

```go title="Example"
app.Get("/non-ascii", func(c fiber.Ctx) error {
  c.Attachment("./files/文件.txt")
  // => Content-Disposition: attachment; filename="文件.txt"; filename*=UTF-8''%E6%96%87%E4%BB%B6.txt
  return nil
})
```

### AutoFormat

Performs content-negotiation on the [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) HTTP header. It uses [Accepts](ctx.md#accepts) to select a proper format.
The supported content types are `text/html`, `text/plain`, `application/json`, `application/vnd.msgpack`, `application/xml`, and `application/cbor`.
For more flexible content negotiation, use [Format](ctx.md#format).

:::info
If the header is **not** specified or there is **no** proper format, **text/plain** is used.
:::

```go title="Signature"
func (c fiber.Ctx) AutoFormat(body any) error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  // Accept: text/plain
  c.AutoFormat("Hello, World!")
  // => Hello, World!

  // Accept: text/html
  c.AutoFormat("Hello, World!")
  // => <p>Hello, World!</p>

  type User struct {
    Name string
  }
  user := User{"John Doe"}

  // Accept: application/json
  c.AutoFormat(user)
  // => {"Name":"John Doe"}

  // Accept: application/vnd.msgpack
  c.AutoFormat(user)
  // => 82 a4 6e 61 6d 65 a4 6a 6f 68 6e a4 70 61 73 73 a3 64 6f 65

  // Accept: application/cbor
  c.AutoFormat(user)
  // => a1 64 4e 61 6d 65 68 4a 6f 68 6e 20 44 6f 65

  // Accept: application/xml
  c.AutoFormat(user)
  // => <User><Name>John Doe</Name></User>
  // ..
})
```

### CBOR

CBOR converts any interface or string to CBOR encoded bytes.

> **Note:** Before using any CBOR-related features, make sure to follow the [CBOR setup instructions](../guide/advance-format.md#cbor).

:::info
CBOR also sets the content header to the `ctype` parameter. If no `ctype` is passed in, the header is set to `application/cbor`.
:::

```go title="Signature"
func (c fiber.Ctx) CBOR(data any, ctype ...string) error
```

```go title="Example"
type SomeStruct struct {
  Name string `cbor:"name"`
  Age  uint8 `cbor:"age"`
}

app.Get("/cbor", func(c fiber.Ctx) error {
  // Create data struct:
  data := SomeStruct{
    Name: "Grame",
    Age:  20,
  }

  return c.CBOR(data)
  // => Content-Type: application/cbor
  // => \xa2dnameeGramecage\x14

  return c.CBOR(fiber.Map{
    "name": "Grame",
    "age":  20,
  })
  // => Content-Type: application/cbor
  // => \xa2dnameeGramecage\x14

  return c.CBOR(fiber.Map{
    "type":     "https://example.com/probs/out-of-credit",
    "title":    "You do not have enough credit.",
    "status":   403,
    "detail":   "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
  })
  // => Content-Type: application/cbor
  // => \xa5dtypex'https://example.com/probs/out-of-creditetitlex\x1eYou do not have enough credit.fstatus\x19\x01\x93fdetailx.Your current balance is 30, but that costs 50.hinstancew/account/12345/msgs/abc
})
```

### ClearCookie

Expires a client cookie (or all cookies if left empty).

```go title="Signature"
func (c fiber.Ctx) ClearCookie(key ...string)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  // Clears all cookies:
  c.ClearCookie()

  // Expire specific cookie by name:
  c.ClearCookie("user")

  // Expire multiple cookies by names:
  c.ClearCookie("token", "session", "track_id", "version")
  // ...
})
```

:::caution
Web browsers and other compliant clients will only clear the cookie if the given options are identical to those when creating the cookie, excluding `Expires` and `MaxAge`. `ClearCookie` will not set these values for you - a technique similar to the one shown below should be used to ensure your cookie is deleted.
:::

```go title="Example"
app.Get("/set", func(c fiber.Ctx) error {
    c.Cookie(&fiber.Cookie{
        Name:     "token",
        Value:    "randomvalue",
        Expires:  time.Now().Add(24 * time.Hour),
        HTTPOnly: true,
        SameSite: "Lax",
    })

    // ...
})

app.Get("/delete", func(c fiber.Ctx) error {
    c.Cookie(&fiber.Cookie{
        Name:     "token",
        Expires:  fasthttp.CookieExpireDelete, // Use fasthttp's built-in constant
        HTTPOnly: true,
        SameSite: "Lax",
    })

    // ...
})
```

You can also use `c.Cookie()` to expire cookies with specific `Path` or `Domain` attributes:

```go title="Example"
app.Get("/logout", func(c fiber.Ctx) error {
    // Expire a cookie with path and domain
    c.Cookie(&fiber.Cookie{
        Name:    "token",
        Path:    "/api",
        Domain:  "example.com",
        Expires: fasthttp.CookieExpireDelete,
    })

    return c.SendStatus(fiber.StatusOK)
})
```

### Cookie

Sets a cookie.

```go title="Signature"
func (c fiber.Ctx) Cookie(cookie *Cookie)
```

```go
type Cookie struct {
    Name        string    `json:"name"`         // The name of the cookie
    Value       string    `json:"value"`        // The value of the cookie
    Path        string    `json:"path"`         // Specifies a URL path which is allowed to receive the cookie
    Domain      string    `json:"domain"`       // Specifies the domain which is allowed to receive the cookie
    MaxAge      int       `json:"max_age"`      // The maximum age (in seconds) of the cookie
    Expires     time.Time `json:"expires"`      // The expiration date of the cookie
    Secure      bool      `json:"secure"`       // Indicates that the cookie should only be transmitted over a secure HTTPS connection
    HTTPOnly    bool      `json:"http_only"`    // Indicates that the cookie is accessible only through the HTTP protocol
    SameSite    string    `json:"same_site"`    // Controls whether or not a cookie is sent with cross-site requests
    Partitioned bool      `json:"partitioned"`  // Indicates if the cookie is stored in a partitioned cookie jar
    SessionOnly bool      `json:"session_only"` // Indicates if the cookie is a session-only cookie
}
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  // Create cookie
  cookie := new(fiber.Cookie)
  cookie.Name = "john"
  cookie.Value = "doe"
  cookie.Expires = time.Now().Add(24 * time.Hour)

  // Set cookie
  c.Cookie(cookie)
  // ...
})
```

:::info
When setting a cookie with `SameSite=None`, Fiber automatically sets `Secure=true` as required by RFC 6265bis and modern browsers. This ensures compliance with the "None" SameSite policy which mandates that cookies must be sent over secure connections.

For more information, see:

- [Mozilla Documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#none)
- [Chrome Documentation](https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure)

:::

:::info
Partitioned cookies allow partitioning the cookie jar by top-level site, enhancing user privacy by preventing cookies from being shared across different sites. This feature is particularly useful in scenarios where a user interacts with embedded third-party services that should not have access to the main site's cookies. You can check out [CHIPS](https://developers.google.com/privacy-sandbox/3pcd/chips) for more information.
:::

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  // Create a new partitioned cookie
  cookie := new(fiber.Cookie)
  cookie.Name = "user_session"
  cookie.Value = "abc123"
  cookie.Partitioned = true  // This cookie will be stored in a separate jar when it's embedded into another website

  // Set the cookie in the response
  c.Cookie(cookie)
  return c.SendString("Partitioned cookie set")
})
```

### Download

Transfers the file from the given path as an `attachment`.

Typically, browsers will prompt the user to download. By default, the [Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) header `filename=` parameter is the file path (this typically appears in the browser dialog).
Override this default with the `filename` parameter.

```go title="Signature"
func (c fiber.Ctx) Download(file string, filename ...string) error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  return c.Download("./files/report-12345.pdf")
  // => Download report-12345.pdf

  return c.Download("./files/report-12345.pdf", "report.pdf")
  // => Download report.pdf
})
```

For filenames containing non-ASCII characters, a `filename*` parameter is added
according to [RFC 6266](https://www.rfc-editor.org/rfc/rfc6266) and
[RFC 8187](https://www.rfc-editor.org/rfc/rfc8187):

```go title="Example"
app.Get("/non-ascii", func(c fiber.Ctx) error {
  return c.Download("./files/文件.txt")
  // => Content-Disposition: attachment; filename="文件.txt"; filename*=UTF-8''%E6%96%87%E4%BB%B6.txt
})
```

### End

End immediately flushes the current response and closes the underlying connection.

```go title="Signature"
func (c fiber.Ctx) End() error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
    c.SendString("Hello World!")
    return c.End()
})
```

:::caution
Calling `c.End()` will disallow further writes to the underlying connection.
:::

:::warning
`c.End()` does **not** work in streaming mode (e.g. when using `fasthttp`'s `HijackConn` or `SendStream`).
In streaming mode the connection is managed asynchronously and `ctx.Conn()` may return `nil`,
so `c.End()` will return `nil` without flushing or closing the connection.
:::

End can be used to stop a middleware from modifying a response of a handler/other middleware down the method chain
when they regain control after calling `c.Next()`.

```go title="Example"
// Error Logging/Responding middleware
app.Use(func(c fiber.Ctx) error {
    err := c.Next()

    // Log errors & write the error to the response
    if err != nil {
        log.Printf("Got error in middleware: %v", err)
        return c.Writef("(got error %v)", err)
    }

    // No errors occurred
    return nil
})

// Handler with simulated error
app.Get("/", func(c fiber.Ctx) error {
    // Closes the connection instantly after writing from this handler
    // and disallow further modification of its response
    defer c.End()

    c.SendString("Hello, ... I forgot what comes next!")
    return errors.New("some error")
})
```

### Format

Performs content-negotiation on the [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) HTTP header. It uses [Accepts](ctx.md#accepts) to select a proper format from the supplied offers. A default handler can be provided by setting the `MediaType` to `"default"`. If no offers match and no default is provided, a 406 (Not Acceptable) response is sent. The Content-Type is automatically set when a handler is selected.

:::info
If the Accept header is **not** specified, the first handler will be used.
:::

```go title="Signature"
func (c fiber.Ctx) Format(handlers ...ResFmt) error
```

```go title="Example"
// Accept: application/json => {"command":"eat","subject":"fruit"}
// Accept: text/plain => Eat Fruit!
// Accept: application/xml => Not Acceptable
app.Get("/no-default", func(c fiber.Ctx) error {
  return c.Format(
    fiber.ResFmt{"application/json", func(c fiber.Ctx) error {
      return c.JSON(fiber.Map{
        "command": "eat",
        "subject": "fruit",
      })
    }},
    fiber.ResFmt{"text/plain", func(c fiber.Ctx) error {
      return c.SendString("Eat Fruit!")
    }},
  )
})

// Accept: application/json => {"command":"eat","subject":"fruit"}
// Accept: text/plain => Eat Fruit!
// Accept: application/xml => Eat Fruit!
app.Get("/default", func(c fiber.Ctx) error {
  textHandler := func(c fiber.Ctx) error {
    return c.SendString("Eat Fruit!")
  }

  handlers := []fiber.ResFmt{
    {"application/json", func(c fiber.Ctx) error {
      return c.JSON(fiber.Map{
        "command": "eat",
        "subject": "fruit",
      })
    }},
    {"text/plain", textHandler},
    {"default", textHandler},
  }

  return c.Format(handlers...)
})
```

### JSON

Converts any **interface** or **string** to JSON using the [encoding/json](https://pkg.go.dev/encoding/json) package.

:::info
JSON also sets the content header to the `ctype` parameter. If no `ctype` is passed in, the header is set to `application/json; charset=utf-8` by default.
:::

```go title="Signature"
func (c fiber.Ctx) JSON(data any, ctype ...string) error
```

```go title="Example"
type SomeStruct struct {
  Name string
  Age  uint8
}

app.Get("/json", func(c fiber.Ctx) error {
  // Create data struct:
  data := SomeStruct{
    Name: "Grame",
    Age:  20,
  }

  return c.JSON(data)
  // => Content-Type: application/json; charset=utf-8
  // => {"Name": "Grame", "Age": 20}

  return c.JSON(fiber.Map{
    "name": "Grame",
    "age":  20,
  })
  // => Content-Type: application/json; charset=utf-8
  // => {"name": "Grame", "age": 20}

  return c.JSON(fiber.Map{
    "type":     "https://example.com/probs/out-of-credit",
    "title":    "You do not have enough credit.",
    "status":   403,
    "detail":   "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
  }, "application/problem+json")
  // => Content-Type: application/problem+json
  // => "{
  // =>     "type": "https://example.com/probs/out-of-credit",
  // =>     "title": "You do not have enough credit.",
  // =>     "status": 403,
  // =>     "detail": "Your current balance is 30, but that costs 50.",
  // =>     "instance": "/account/12345/msgs/abc",
  // => }"
})
```

### JSONP

Sends a JSON response with JSONP support. This method is identical to [JSON](ctx.md#json), except that it opts-in to JSONP callback support. By default, the callback name is simply `callback`.

Override this by passing a **named string** in the method.

```go title="Signature"
func (c fiber.Ctx) JSONP(data any, callback ...string) error
```

```go title="Example"
type SomeStruct struct {
  Name string
  Age  uint8
}

app.Get("/", func(c fiber.Ctx) error {
  // Create data struct:
  data := SomeStruct{
    Name: "Grame",
    Age:  20,
  }

  return c.JSONP(data)
  // => callback({"Name": "Grame", "Age": 20})

  return c.JSONP(data, "customFunc")
  // => customFunc({"Name": "Grame", "Age": 20})
})
```

### Links

Joins the links followed by the property to populate the response’s [Link HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link) field.

```go title="Signature"
func (c fiber.Ctx) Links(link ...string)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Links(
    "http://api.example.com/users?page=2", "next",
    "http://api.example.com/users?page=5", "last",
  )
  // Link: <http://api.example.com/users?page=2>; rel="next",
  //       <http://api.example.com/users?page=5>; rel="last"

  // ...
})
```

### Location

Sets the response [Location](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location) HTTP header to the specified path parameter.

```go title="Signature"
func (c fiber.Ctx) Location(path string)
```

```go title="Example"
app.Post("/", func(c fiber.Ctx) error {
  c.Location("http://example.com")

  c.Location("/foo/bar")

  return nil
})
```

### MsgPack

> **Note:** Before using any MsgPack-related features, make sure to follow the [MsgPack setup instructions](../guide/advance-format.md#msgpack).

A compact binary alternative to [JSON](#json) for efficient data transfer between micro-services or from server to client. MessagePack serializes faster and yields smaller payloads than plain JSON.

Converts any **interface** or **string** to MsgPack using the [shamaton/msgpack](https://pkg.go.dev/github.com/shamaton/msgpack/v3) package.

:::info
MsgPack also sets the content header to the `ctype` parameter. If no `ctype` is passed in, the header is set to `application/vnd.msgpack`.
:::

```go title="Signature"
func (c fiber.Ctx) MsgPack(data any, ctype ...string) error
```

```go title="Example"
type SomeStruct struct {
  Name string
  Age  uint8
}

app.Get("/msgpack", func(c fiber.Ctx) error {
  // Create data struct:
  data := SomeStruct{
    Name: "Grame",
    Age:  20,
  }

  return c.MsgPack(data)
  // => Content-Type: application/vnd.msgpack
  // => 82 A4 4E 61 6D 65 A5 47 72 61 6D 65 A3 41 67 65 14

  return c.MsgPack(fiber.Map{
    "name": "Grame",
    "age":  20,
  })
  // => Content-Type: application/vnd.msgpack
  // => 82 A4 6E 61 6D 65 A5 47 72 61 6D 65 A3 61 67 65 14

  return c.MsgPack(fiber.Map{
    "type":     "https://example.com/probs/out-of-credit",
    "title":    "You do not have enough credit.",
    "status":   403,
    "detail":   "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
  }, "application/problem+msgpack")
})

// => Content-Type: application/problem+msgpack
// 85 A4 74 79 70 65 D9 27 68 74 74 70 73 3A 2F 2F 65 78 61 6D 70 6C 65 2E 63 6F 6D 2F 70 72 6F 62 73 2F 6F 75 74 2D 6F 66 2D 63 72 65 64 69 74 A5 74 69 74 6C 65 BE 59 6F 75 20 64 6F 20 6E 6F 74 20 68 61 76 65 20 65 6E 6F 75 67 68 20 63 72 65 64 69 74 2E A6 73 74 61 74 75 73 CD 01 93 A6 64 65 74 61 69 6C D9 2E 59 6F 75 72 20 63 75 72 72 65 6E 74 20 62 61 6C 61 6E 63 65 20 69 73 20 33 30 2C 20 62 75 74 20 74 68 61 74 20 63 6F 73 74 73 20 35 30 2E A8 69 6E 73 74 61 6E 63 65 B7 2F 61 63 63 6F 75 6E 74 2F 31 32 33 34 35 2F 6D 73 67 73 2F 61 62 63
```

### Render

Renders a view with data and sends a `text/html` response. By default, `Render` uses the default [**Go Template engine**](https://pkg.go.dev/html/template/). If you want to use another view engine, please take a look at our [**Template middleware**](https://docs.gofiber.io/template).

```go title="Signature"
func (c fiber.Ctx) Render(name string, bind any, layouts ...string) error
```

### Send

Sets the HTTP response body.

```go title="Signature"
func (c fiber.Ctx) Send(body []byte) error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  return c.Send([]byte("Hello, World!")) // => "Hello, World!"
})
```

Fiber also provides `SendString` and `SendStream` methods for raw inputs.

:::tip
Use this if you **don't need** type assertion, recommended for **faster** performance.
:::

```go title="Signature"
func (c fiber.Ctx) SendString(body string) error
func (c fiber.Ctx) SendStream(stream io.Reader, size ...int) error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  return c.SendString("Hello, World!")
  // => "Hello, World!"

  return c.SendStream(bytes.NewReader([]byte("Hello, World!")))
  // => "Hello, World!"
})
```

### SendEarlyHints

Sends an informational `103 Early Hints` response with one or more
[`Link` headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Link)
before the final response. This allows the browser to start preloading
resources while the server prepares the full response.

:::caution
This feature requires HTTP/2 or newer. Some legacy HTTP/1.1 clients may not support sendEarlyHints.
Early Hints (`103` responses) are supported in HTTP/2 and newer. Older HTTP/1.1 clients may ignore these interim responses or misbehave when receiving them.
See [Enabling HTTP/2](../guide/reverse-proxy#enabling-http2) for instructions on how to use a reverse proxy (e.g. Nginx or Traefik) to enable HTTP/2 support.
:::

```go title="Signature"
func (c fiber.Ctx) SendEarlyHints(hints []string) error
```

```go title="Example"
hints := []string{"<https://cdn.com/app.js>; rel=preload; as=script"}
app.Get("/early", func(c fiber.Ctx) error {
  if err := c.SendEarlyHints(hints); err != nil {
    return err
  }
  return c.SendString("done")
})
```

### SendFile

Transfers the file from the given path. Sets the [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) response HTTP header field based on the **file** extension or format.

```go title="Config" title="Config"
// SendFile defines configuration options when to transfer file with SendFile.
type SendFile struct {
  // FS is the file system to serve the static files from.
  // You can use interfaces compatible with fs.FS like embed.FS, os.DirFS etc.
  //
  // Optional. Default: nil
  FS fs.FS

  // When set to true, the server tries minimizing CPU usage by caching compressed files.
  // This works differently than the github.com/gofiber/compression middleware.
  // You have to set Content-Encoding header to compress the file.
  // Available compression methods are gzip, br, and zstd.
  //
  // Optional. Default: false
  Compress bool `json:"compress"`

  // When set to true, enables byte range requests.
  //
  // Optional. Default: false
  ByteRange bool `json:"byte_range"`

  // When set to true, enables direct download.
  //
  // Optional. Default: false
  Download bool `json:"download"`

  // Expiration duration for inactive file handlers.
  // Use a negative time.Duration to disable it.
  //
  // Optional. Default: 10 * time.Second
  CacheDuration time.Duration `json:"cache_duration"`

  // The value for the Cache-Control HTTP-header
  // that is set on the file response. MaxAge is defined in seconds.
  //
  // Optional. Default: 0
  MaxAge int `json:"max_age"`
}
```

```go title="Signature" title="Signature"
func (c fiber.Ctx) SendFile(file string, config ...SendFile) error
```

```go title="Example"
app.Get("/not-found", func(c fiber.Ctx) error {
  return c.SendFile("./public/404.html")

  // Disable compression
  return c.SendFile("./static/index.html", fiber.SendFile{
    Compress: false,
  })
})
```

:::info
If the file contains a URL-specific character, you have to escape it before passing the file path into the `SendFile` function.
:::

```go title="Example"
app.Get("/file-with-url-chars", func(c fiber.Ctx) error {
  return c.SendFile(url.PathEscape("hash_sign_#.txt"))
})
```

:::info
You can set the `CacheDuration` config property to `-1` to disable caching.
:::

```go title="Example"
app.Get("/file", func(c fiber.Ctx) error {
  return c.SendFile("style.css", fiber.SendFile{
    CacheDuration: -1,
  })
})
```

:::info
You can use multiple `SendFile` calls with different configurations in a single route. Fiber creates different filesystem handlers per config.
:::

```go title="Example"
app.Get("/file", func(c fiber.Ctx) error {
  switch c.Query("config") {
    case "filesystem":
      return c.SendFile("style.css", fiber.SendFile{
        FS: os.DirFS(".")
      })
    case "filesystem-compress":
      return c.SendFile("style.css", fiber.SendFile{
        FS: os.DirFS("."),
        Compress: true,
      })
    case "compress":
      return c.SendFile("style.css", fiber.SendFile{
        Compress: true,
      })
    default:
      return c.SendFile("style.css")
  }

  return nil
})
```

:::info
For sending multiple files from an embedded file system, [this functionality](../middleware/static.md#serving-files-using-embedfs) can be used.
:::

### SendStatus

Sets the status code and the correct status message in the body if the response body is **empty**.

:::tip
You can find all used status codes and messages [in the Fiber source code](https://github.com/gofiber/fiber/blob/dffab20bcdf4f3597d2c74633a7705a517d2c8c2/utils.go#L183-L244).
:::

```go title="Signature"
func (c fiber.Ctx) SendStatus(status int) error
```

```go title="Example"
app.Get("/not-found", func(c fiber.Ctx) error {
  return c.SendStatus(415)
  // => 415 "Unsupported Media Type"

  c.SendString("Hello, World!")
  return c.SendStatus(415)
  // => 415 "Hello, World!"
})
```

### SendStream

Sets the response body to a stream of data and adds an optional body size.

```go title="Signature"
func (c fiber.Ctx) SendStream(stream io.Reader, size ...int) error
```

:::info
`SendStream` operates asynchronously. The handler returns immediately after setting up the stream,
but the actual reading and sending of data happens **after** the handler completes. This is handled
by the underlying `fasthttp` library.

If the provided stream implements `io.Closer`, it will be automatically closed by `fasthttp` after
the response is fully sent or if an error occurs.
:::

:::caution
When passing `fiber.Ctx` as a `context.Context` to libraries that spawn goroutines (e.g., for streaming operations),
those goroutines may attempt to access the context after the handler returns. Since `fiber.Ctx` is recycled and
released after the handler completes, this can cause issues.

**Recommended approach**: Use `c.Context()` or `c.RequestCtx()` instead of passing `c` directly to such libraries.
See the [Context Guide](../guide/context.md) for more details.
:::

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  return c.SendStream(bytes.NewReader([]byte("Hello, World!")))
  // => "Hello, World!"
})
```

```go title="Example with file streaming"
app.Get("/download", func(c fiber.Ctx) error {
  file, err := os.Open("large-file.zip")
  if err != nil {
    return err
  }
  // File will be automatically closed by fasthttp after streaming completes
  
  stat, err := file.Stat()
  if err != nil {
    file.Close()
    return err
  }
  
  return c.SendStream(file, int(stat.Size()))
})
```

### SendStreamWriter

Sets the response body stream writer.

:::note
The argument `streamWriter` represents a function that populates
the response body using a buffered stream writer.
:::

```go title="Signature"
func (c Ctx) SendStreamWriter(streamWriter func(*bufio.Writer)) error
```

```go title="Example"
app.Get("/", func (c fiber.Ctx) error {
  return c.SendStreamWriter(func(w *bufio.Writer) {
    fmt.Fprintf(w, "Hello, World!\n")
  })
  // => "Hello, World!"
})
```

:::info
To send data before `streamWriter` returns, you can call `w.Flush()`
on the provided writer. Otherwise, the buffered stream flushes after
`streamWriter` returns.
:::

:::note
`w.Flush()` will return an error if the client disconnects before `streamWriter` finishes writing a response.
:::

```go title="Example"
app.Get("/wait", func(c fiber.Ctx) error {
  return c.SendStreamWriter(func(w *bufio.Writer) {
    // Begin Work
    fmt.Fprintf(w, "Please wait for 10 seconds\n")
    if err := w.Flush(); err != nil {
      log.Print("Client disconnected!")
      return
    }

    // Send progress over time
    time.Sleep(time.Second)
    for i := 0; i < 9; i++ {
      fmt.Fprintf(w, "Still waiting...\n")
      if err := w.Flush(); err != nil {
        // If client disconnected, cancel work and finish
        log.Print("Client disconnected!")
        return
      }
      time.Sleep(time.Second)
    }

    // Finish
    fmt.Fprintf(w, "Done!\n")
  })
})
```

### SendString

Sets the response body to a string.

```go title="Signature"
func (c fiber.Ctx) SendString(body string) error
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  return c.SendString("Hello, World!")
  // => "Hello, World!"
})
```

### Set

Sets the response’s HTTP header field to the specified `key`, `value`.

```go title="Signature"
func (c fiber.Ctx) Set(key string, val string)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Set("Content-Type", "text/plain")
  // => "Content-Type: text/plain"

  // ...
})
```

### Status

Sets the HTTP status for the response.

:::info
This method is **chainable**.
:::

```go title="Signature"
func (c fiber.Ctx) Status(status int) fiber.Ctx
```

```go title="Example"
app.Get("/fiber", func(c fiber.Ctx) error {
  c.Status(fiber.StatusOK)
  return nil
})

app.Get("/hello", func(c fiber.Ctx) error {
  return c.Status(fiber.StatusBadRequest).SendString("Bad Request")
})

app.Get("/world", func(c fiber.Ctx) error {
  return c.Status(fiber.StatusNotFound).SendFile("./public/gopher.png")
})
```

### Type

Sets the [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) HTTP header to the MIME type listed [in the Nginx MIME types configuration](https://github.com/nginx/nginx/blob/master/conf/mime.types) specified by the file **extension**.

:::info
This method is **chainable**.
:::

```go title="Signature"
func (c fiber.Ctx) Type(ext string, charset ...string) fiber.Ctx
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Type(".html") // => "text/html"
  c.Type("html")  // => "text/html"
  c.Type("png")   // => "image/png"

  c.Type("json", "utf-8")  // => "application/json; charset=utf-8"

  // ...
})
```

### Vary

Adds the given header field to the [Vary](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary) response header. This will append the header if not already listed; otherwise, it leaves it listed in the current location.

:::info
Multiple fields are **allowed**.
:::

```go title="Signature"
func (c fiber.Ctx) Vary(fields ...string)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Vary("Origin")     // => Vary: Origin
  c.Vary("User-Agent") // => Vary: Origin, User-Agent

  // No duplicates
  c.Vary("Origin") // => Vary: Origin, User-Agent

  c.Vary("Accept-Encoding", "Accept")
  // => Vary: Origin, User-Agent, Accept-Encoding, Accept

  // ...
})
```

### Write

Adopts the `Writer` interface.

```go title="Signature"
func (c fiber.Ctx) Write(p []byte) (n int, err error)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  c.Write([]byte("Hello, World!")) // => "Hello, World!"

  fmt.Fprintf(c, "%s\n", "Hello, World!") // => "Hello, World!"
})
```

### Writef

Writes a formatted string using a format specifier.

```go title="Signature"
func (c fiber.Ctx) Writef(format string, a ...any) (n int, err error)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  world := "World!"
  c.Writef("Hello, %s", world) // => "Hello, World!"

  fmt.Fprintf(c, "%s\n", "Hello, World!") // => "Hello, World!"
})
```

### WriteString

Writes a string to the response body.

```go title="Signature"
func (c fiber.Ctx) WriteString(s string) (n int, err error)
```

```go title="Example"
app.Get("/", func(c fiber.Ctx) error {
  return c.WriteString("Hello, World!")
  // => "Hello, World!"
})
```

### XML

Converts any **interface** or **string** to XML using the standard `encoding/xml` package.

:::info
XML also sets the content header to `application/xml; charset=utf-8`.
:::

```go title="Signature"
func (c fiber.Ctx) XML(data any) error
```

```go title="Example"
type SomeStruct struct {
  XMLName xml.Name `xml:"Fiber"`
  Name    string   `xml:"Name"`
  Age     uint8    `xml:"Age"`
}

app.Get("/", func(c fiber.Ctx) error {
  // Create data struct:
  data := SomeStruct{
    Name: "Grame",
    Age:  20,
  }

  return c.XML(data)
  // <Fiber>
  //     <Name>Grame</Name>
  //     <Age>20</Age>
  // </Fiber>
})
```
