跳到主要内容
版本: v2.x

🧠 Ctx

Accepts

检查指定的扩展名内容类型是否可接受。

信息

基于请求的 Accept HTTP 头。

签名
func (c *Ctx) Accepts(offers ...string)          string
func (c *Ctx) AcceptsCharsets(offers ...string) string
func (c *Ctx) AcceptsEncodings(offers ...string) string
func (c *Ctx) AcceptsLanguages(offers ...string) string
示例
// Accept: text/html, application/json; q=0.8, text/plain; q=0.5; charset="utf-8"

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") // ""
// ...
})
示例 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 */* without q factor 0 is Not Acceptable
// ...
})

支持 Media-Type 参数。

示例 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 does not matter. Quotes on values are stripped.
c.Accepts(`application/json;foo="bar";VERSION=1`) // "application/json;foo="bar";VERSION=1"
})
示例 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 为其他 accept 头提供了类似的功能。

// 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"
// ...
})

AllParams

Params 用于获取所有路由参数。使用 Params 方法获取参数。

签名
func (c *Ctx) AllParams() map[string]string
示例
// GET http://example.com/user/fenny
app.Get("/user/:name", func(c *fiber.Ctx) error {
c.AllParams() // "{"name": "fenny"}"

// ...
})

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

// ...
})

App

返回 *App 引用,以便轻松访问所有应用程序设置。

签名
func (c *Ctx) App() *App
示例
app.Get("/stack", func(c *fiber.Ctx) error {
return c.JSON(c.App().Stack())
})

Append

将指定的值附加到 HTTP 响应头字段中。

注意

如果头尚未设置,则使用指定的值创建该头。

签名
func (c *Ctx) Append(field string, values ...string)
示例
app.Get("/", func(c *fiber.Ctx) error {
c.Append("Link", "http://google.com", "http://localhost")
// => Link: http://localhost, http://google.com

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

// ...
})

Attachment

将 HTTP 响应的 Content-Disposition 头字段设置为 attachment

签名
func (c *Ctx) Attachment(filename ...string)
示例
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

// ...
})

BaseURL

string 类型返回基本 URL(协议 + 主机)。

签名
func (c *Ctx) BaseURL() string
示例
// GET https://example.com/page#chapter-1

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

Bind

将变量添加到默认视图变量映射,绑定到模板引擎。变量由 Render 方法读取,并可能被覆盖。

签名
func (c *Ctx) Bind(vars Map) error
示例
app.Use(func(c *fiber.Ctx) error {
c.Bind(fiber.Map{
"Title": "Hello, World!",
})
})

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

BodyRaw

返回原始请求

签名
func (c *Ctx) BodyRaw() []byte
示例
// 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")
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

Body

根据 Content-Encoding 头,此方法将尝试对请求字节进行文件解压缩。如果未发送 Content-Encoding 头,则行为与 BodyRaw 相同。

签名
func (c *Ctx) Body() []byte
示例
// 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")
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

BodyParser

将请求体绑定到结构体。

重要的是根据要解析的内容类型指定正确的结构体标签。例如,如果要解析一个包含名为 Pass 字段的 JSON 体,您将使用一个结构体字段 json:"pass"

内容类型结构体标签
application/x-www-form-urlencodedform
multipart/form-dataform
application/jsonjson
application/xmlxml
text/xmlxml
注意

处理 multipart/form-data 时,只有表单值可以直接分配给结构体字段。请求中包含的文件不会自动分配给结构体。必须使用 FormFile 或其他文件特定方法单独处理文件。

签名
func (c *Ctx) BodyParser(out interface{}) error
示例
// Field names should start with an uppercase letter
type Person struct {
Name string `json:"name" xml:"name" form:"name"`
Pass string `json:"pass" xml:"pass" form:"pass"`
}

app.Post("/", func(c *fiber.Ctx) error {
p := new(Person)

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

log.Println(p.Name) // john
log.Println(p.Pass) // doe

// ...
})

// Run tests with the following curl commands

// curl -X POST -H "Content-Type: application/json" --data "{\"name\":\"john\",\"pass\":\"doe\"}" localhost:3000

// curl -X POST -H "Content-Type: application/xml" --data "<login><name>john</name><pass>doe</pass></login>" localhost:3000

// curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data "name=john&pass=doe" localhost:3000

// curl -X POST -F name=john -F pass=doe http://localhost:3000

// curl -X POST "http://localhost:3000/?name=john&pass=doe"

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

ClearCookie

使客户端 cookie 过期(如果留空,则使所有 cookie 过期)

签名
func (c *Ctx) ClearCookie(key ...string)
示例
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")
// ...
})
注意

Web 浏览器和其他兼容的客户端只有在给定的选项(不包括 expires 和 maxAge)与创建 cookie 时相同的情况下,才会清除 cookie。ClearCookie 不会为您设置这些值 - 应使用类似下面所示的技术来确保您的 cookie 被删除。

示例
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",
// Set expiry date to the past
Expires: time.Now().Add(-(time.Hour * 2)),
HTTPOnly: true,
SameSite: "lax",
})

// ...
})

ClientHelloInfo

ClientHelloInfo 包含来自 ClientHello 消息的信息,用于指导 GetCertificate 和 GetConfigForClient 回调中的应用程序逻辑。您可以参考 ClientHelloInfo 结构体文档以获取有关返回结构体的更多信息。

签名
func (c *Ctx) ClientHelloInfo() *tls.ClientHelloInfo
示例
// GET http://example.com/hello
app.Get("/hello", func(c *fiber.Ctx) error {
chi := c.ClientHelloInfo()
// ...
})

Context

返回兼容 context.Context 接口的 *fasthttp.RequestCtx,该接口需要在 API 边界之间传递截止时间、取消信号和其他值。

签名
func (c *Ctx) Context() *fasthttp.RequestCtx
信息

请阅读 Fasthttp 文档以获取更多信息。

设置 cookie

签名
func (c *Ctx) Cookie(cookie *Cookie)
type Cookie struct {
Name string `json:"name"`
Value string `json:"value"`
Path string `json:"path"`
Domain string `json:"domain"`
MaxAge int `json:"max_age"`
Expires time.Time `json:"expires"`
Secure bool `json:"secure"`
HTTPOnly bool `json:"http_only"`
SameSite string `json:"same_site"`
SessionOnly bool `json:"session_only"`
}
示例
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)
// ...
})

CookieParser

此方法类似于 BodyParser,但用于 cookie 参数。重要的是使用结构体标签 "cookie"。例如,如果要解析一个包含名为 Age 字段的 cookie,您将使用一个结构体字段 cookie:"age"

签名
func (c *Ctx) CookieParser(out interface{}) error
示例
// Field names should start with an uppercase letter
type Person struct {
Name string `cookie:"name"`
Age int `cookie:"age"`
Job bool `cookie:"job"`
}

app.Get("/", func(c *fiber.Ctx) error {
p := new(Person)

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

log.Println(p.Name) // Joseph
log.Println(p.Age) // 23
log.Println(p.Job) // true
})
// Run tests with the following curl command
// curl.exe --cookie "name=Joseph; age=23; job=true" http://localhost:8000/

Cookies

根据键获取 cookie 值,您可以传递一个可选的默认值,如果 cookie 键不存在,将返回该默认值。

签名
func (c *Ctx) Cookies(key string, defaultValue ...string) string
示例
app.Get("/", func(c *fiber.Ctx) error {
// Get cookie by key:
c.Cookies("name") // "john"
c.Cookies("empty", "doe") // "doe"
// ...
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

Download

将文件从路径传输为 attachment

通常,浏览器会提示用户下载。默认情况下,Content-Dispositionfilename= 参数是文件路径(这通常出现在浏览器对话框中)。

使用 filename 参数覆盖此默认值。

签名
func (c *Ctx) Download(file string, filename ...string) error
示例
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
})

Format

Accept HTTP 头执行内容协商。它使用 Accepts 选择适当的格式。

信息

如果未指定头或没有适当的格式,则使用 text/plain

签名
func (c *Ctx) Format(body interface{}) error
示例
app.Get("/", func(c *fiber.Ctx) error {
// Accept: text/plain
c.Format("Hello, World!")
// => Hello, World!

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

// Accept: application/json
c.Format("Hello, World!")
// => "Hello, World!"
// ..
})

FormFile

MultipartForm 文件可以通过名称检索,返回给定键的第一个文件。

签名
func (c *Ctx) FormFile(key string) (*multipart.FileHeader, error)
示例
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

任何表单值都可以通过名称检索,返回给定键的第一个值。

签名
func (c *Ctx) FormValue(key string, defaultValue ...string) string
示例
app.Post("/", func(c *fiber.Ctx) error {
// Get first value from form field "name":
c.FormValue("name")
// => "john" or "" if not exist

// ..
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

Fresh

当响应在客户端缓存中仍然新鲜时,返回 true,否则返回 false 表示客户端缓存已过期,应发送完整响应。

当客户端发送 Cache-Control: no-cache 请求头以指示端到端重新加载请求时,Fresh 将返回 false,以便透明地处理这些请求。

更多信息请阅读 https://express.js.cn/en/4x/api.html#req.fresh

签名
func (c *Ctx) Fresh() bool

Get

返回由字段指定的 HTTP 请求头。

提示

匹配不区分大小写

签名
func (c *Ctx) Get(key string, defaultValue ...string) string
示例
app.Get("/", func(c *fiber.Ctx) error {
c.Get("Content-Type") // "text/plain"
c.Get("CoNtEnT-TypE") // "text/plain"
c.Get("something", "john") // "john"
// ..
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

GetReqHeaders

将 HTTP 请求头作为 map 返回。由于单个请求中的一个头可以设置多次,map 的值是包含该头所有不同值的字符串切片。

签名
func (c *Ctx) GetReqHeaders() map[string][]string

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

GetRespHeader

返回由字段指定的 HTTP 响应头。

提示

匹配不区分大小写

签名
func (c *Ctx) GetRespHeader(key string, defaultValue ...string) string
示例
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"
// ..
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

GetRespHeaders

将 HTTP 响应头作为 map 返回。由于单个请求中的一个头可以设置多次,map 的值是包含该头所有不同值的字符串切片。

签名
func (c *Ctx) GetRespHeaders() map[string][]string

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

GetRouteURL

生成带参数的命名路由 URL。URL 是相对的,例如:"/user/1831"

签名
func (c *Ctx) GetRouteURL(routeName string, params Map) (string, error)
示例
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"

Hostname

返回从 Host HTTP 头派生的主机名。

签名
func (c *Ctx) Hostname() string
示例
// GET http://google.com/search

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

// ...
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

IP

返回请求的远程 IP 地址。

签名
func (c *Ctx) IP() string
示例
app.Get("/", func(c *fiber.Ctx) error {
c.IP() // "127.0.0.1"

// ...
})

在 fiber 应用中注册代理请求头时,返回该头的 IP 地址 (Fiber 配置)

app := fiber.New(fiber.Config{
ProxyHeader: fiber.HeaderXForwardedFor,
})

IPs

返回 X-Forwarded-For 请求头中指定的 IP 地址数组。

签名
func (c *Ctx) IPs() []string
示例
// X-Forwarded-For: proxy1, 127.0.0.1, proxy3

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

// ...
})
注意

不当使用 X-Forwarded-For 头可能存在安全风险。详情请参阅安全与隐私注意事项部分。

Is

如果传入请求的 Content-Type HTTP 头字段与 type 参数指定的 MIME 类型匹配,则返回匹配的内容类型

信息

如果请求没有体,则返回 false

签名
func (c *Ctx) Is(extension string) bool
示例
// 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

// ...
})

IsFromLocal

如果请求来自 localhost,则返回 true

签名
func (c *Ctx) IsFromLocal() bool {
示例

app.Get("/", func(c *fiber.Ctx) error {
// If request came from localhost, return true else return false
c.IsFromLocal()

// ...
})

JSON

使用 encoding/json 包将任何 interfacestring 转换为 JSON。

信息

JSON 还会将内容头设置为 ctype 参数。如果未传入 ctype,则头设置为 application/json

签名
func (c *Ctx) JSON(data interface{}, ctype ...string) error
示例
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
// => "{"Name": "Grame", "Age": 20}"

return c.JSON(fiber.Map{
"name": "Grame",
"age": 20,
})
// => Content-Type: application/json
// => "{"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

发送支持 JSONP 的 JSON 响应。此方法与 JSON 相同,不同之处在于它支持 JSONP 回调。默认情况下,回调名称仅为 callback。

通过在方法中传递一个命名字符串来覆盖此设置。

签名
func (c *Ctx) JSONP(data interface{}, callback ...string) error
示例
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})
})

连接链接及后续属性以填充响应的 Link HTTP 头字段。

签名
func (c *Ctx) Links(link ...string)
示例
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"

// ...
})

Locals

此方法存储作用域限定于请求的变量,因此仅对匹配该请求的路由可用。存储的变量在请求处理后被移除。如果任何存储的数据实现了 io.Closer 接口,则在移除前会调用其 Close 方法。

提示

如果您想将某些特定数据传递给下一个中间件,这将很有用。请记住在检索数据时进行类型断言,以确保其类型符合预期。您还可以使用非导出类型作为键来避免冲突。

签名
func (c *Ctx) Locals(key interface{}, value ...interface{}) interface{}
示例
type keyType struct{}
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)
})

Location

将响应的 Location HTTP 头设置为指定的路径参数。

签名
func (c *Ctx) Location(path string)
示例
app.Post("/", func(c *fiber.Ctx) error {
c.Location("http://example.com")

c.Location("/foo/bar")

return nil
})

Method

返回与请求的 HTTP 方法对应的字符串:GETPOSTPUT 等等。可选地,您可以传递一个字符串来覆盖该方法。

签名
func (c *Ctx) Method(override ...string) string
示例
app.Post("/", func(c *fiber.Ctx) error {
c.Method() // "POST"

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

// ...
})

MultipartForm

要访问 multipart 表单条目,可以使用 MultipartForm() 解析二进制数据。这会返回一个 map[string][]string,因此给定一个键,值将是一个字符串切片。

签名
func (c *Ctx) MultipartForm() (*multipart.Form, error)
示例
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 err
})

Next

调用 Next 时,会执行栈中匹配当前路由的下一个方法。您可以在方法内传递一个错误结构体,这将结束链式调用并调用错误处理器

签名
func (c *Ctx) Next() error
示例
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!")
})

OriginalURL

返回原始请求 URL。

签名
func (c *Ctx) OriginalURL() string
示例
// GET http://example.com/search?q=something

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

// ...
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

Params

此方法可用于获取路由参数,您可以传递一个可选的默认值,如果参数键不存在,将返回该默认值。

信息

如果参数不存在,则默认为空字符串("")。

签名
func (c *Ctx) Params(key string, defaultValue ...string) string
示例
// 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"

// ...
})

未命名路由参数(*, +) 可以通过路由中的字符计数器获取。

示例
// ROUTE: /v1/*/shop/*
// GET: /v1/brand/4/shop/blue/xs
c.Params("*1") // "brand/4"
c.Params("*2") // "blue/xs"

出于向下兼容的原因,参数字符的第一个参数段也可以在没有计数器的情况下访问。

示例
app.Get("/v1/*/shop/*", func(c *fiber.Ctx) error {
c.Params("*") // outputs the values of the first wildcard segment
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

ParamsInt

此方法可用于从路由参数中获取一个整数。请注意,如果该参数不在请求中,将返回零。如果该参数不是数字,将返回零和一个错误

信息

如果参数不存在,则默认为整数零(0)。

签名
func (c *Ctx) ParamsInt(key string) (int, error)
示例
// GET http://example.com/user/123
app.Get("/user/:id", func(c *fiber.Ctx) error {
id, err := c.ParamsInt("id") // int 123 and no error

// ...
})

此方法等同于使用 atoi 和 ctx.Params

ParamsParser

此方法类似于 BodyParser,但用于路径参数。重要的是使用结构体标签 "params"。例如,如果要解析一个包含名为 Pass 字段的路径参数,您将使用一个结构体字段 params:"pass"

签名
func (c *Ctx) ParamsParser(out interface{}) error
示例
// GET http://example.com/user/111
app.Get("/user/:id", func(c *fiber.Ctx) error {
param := struct {ID uint `params:"id"`}{}

c.ParamsParser(&param) // "{"id": 111}"

// ...
})

Path

包含请求 URL 的路径部分。可选地,您可以通过传递一个字符串来覆盖路径。对于内部重定向,您可能希望调用 RestartRouting 而不是 Next

签名
func (c *Ctx) Path(override ...string) string
示例
// GET http://example.com/users?sort=desc

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

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

// ...
})

Protocol

包含请求协议字符串:httpTLS 请求的 https

签名
func (c *Ctx) Protocol() string
示例
// GET http://example.com

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

// ...
})

Queries

Queries 是一个函数,返回一个包含路由中每个查询字符串参数属性的对象。

签名
func (c *Ctx) Queries() map[string]string
示例
// 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"] // ""
// ...
})
示例
// 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
})
示例
// 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"
})
示例
// 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
})
示例
// 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

此属性是一个对象,包含路由中每个查询字符串参数的属性,您可以传递一个可选的默认值,如果查询键不存在,将返回该默认值。

信息

如果没有查询字符串,则返回一个空字符串

签名
func (c *Ctx) Query(key string, defaultValue ...string) string
示例
// 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"

// ...
})

返回值仅在处理器内部有效。请勿存储任何引用。请制作副本或改用 Immutable 设置。 阅读更多...

QueryBool

此属性是一个对象,包含路由中每个布尔查询参数的属性,您可以传递一个可选的默认值,如果查询键不存在,将返回该默认值。

注意

请注意,如果该参数不在请求中,将返回 false。如果该参数不是布尔值,仍会尝试转换并通常返回 false。

签名
func (c *Ctx) QueryBool(key string, defaultValue ...bool) bool
示例
// GET http://example.com/?name=alex&want_pizza=false&id=

app.Get("/", func(c *fiber.Ctx) error {
c.QueryBool("want_pizza") // false
c.QueryBool("want_pizza", true) // false
c.QueryBool("name") // false
c.QueryBool("name", true) // true
c.QueryBool("id") // false
c.QueryBool("id", true) // true

// ...
})

QueryFloat

此属性是一个对象,包含路由中每个 float64 查询参数的属性,您可以传递一个可选的默认值,如果查询键不存在,将返回该默认值。

注意

请注意,如果该参数不在请求中,将返回零。如果该参数不是数字,仍会尝试转换并通常返回 1。

信息

如果参数不存在,则默认为 float64 零(0)。

签名
func (c *Ctx) QueryFloat(key string, defaultValue ...float64) float64
示例
// GET http://example.com/?name=alex&amount=32.23&id=

app.Get("/", func(c *fiber.Ctx) error {
c.QueryFloat("amount") // 32.23
c.QueryFloat("amount", 3) // 32.23
c.QueryFloat("name", 1) // 1
c.QueryFloat("name") // 0
c.QueryFloat("id", 3) // 3

// ...
})

QueryInt

此属性是一个对象,包含路由中每个整数查询参数的属性,您可以传递一个可选的默认值,如果查询键不存在,将返回该默认值。

注意

请注意,如果该参数不在请求中,将返回零。如果该参数不是数字,仍会尝试转换并通常返回 1。

信息

如果参数不存在,则默认为整数零(0)。

签名
func (c *Ctx) QueryInt(key string, defaultValue ...int) int
示例
// GET http://example.com/?name=alex&wanna_cake=2&id=

app.Get("/", func(c *fiber.Ctx) error {
c.QueryInt("wanna_cake", 1) // 2
c.QueryInt("name", 1) // 1
c.QueryInt("id", 1) // 1
c.QueryInt("id") // 0

// ...
})

QueryParser

此方法类似于 BodyParser,但用于查询参数。重要的是使用结构体标签 "query"。例如,如果要解析一个包含名为 Pass 字段的查询参数,您将使用一个结构体字段 query:"pass"

签名
func (c *Ctx) QueryParser(out interface{}) error
示例
// Field names should start with an uppercase letter
type Person struct {
Name string `query:"name"`
Pass string `query:"pass"`
Products []string `query:"products"`
}

app.Get("/", func(c *fiber.Ctx) error {
p := new(Person)

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

log.Println(p.Name) // john
log.Println(p.Pass) // doe
// fiber.Config{EnableSplittingOnParsers: false} - default
log.Println(p.Products) // ["shoe,hat"]
// fiber.Config{EnableSplittingOnParsers: true}
// log.Println(p.Products) // ["shoe", "hat"]


// ...
})
// Run tests with the following curl command

// curl "http://localhost:3000/?name=john&pass=doe&products=shoe,hat"
信息

更多解析器设置请参阅 配置

Range

将返回一个包含类型和范围切片的结构体。

签名
func (c *Ctx) Range(size int) (Range, error)
示例
// Range: bytes=500-700, 700-900
app.Get("/", func(c *fiber.Ctx) error {
b := c.Range(1000)
if b.Type == "bytes" {
for r := range r.Ranges {
fmt.Println(r)
// [500, 700]
}
}
})

Redirect

重定向到由指定路径派生的 URL,并带有指定的 HTTP 状态码(一个正整数)。

信息

如果未指定,状态默认为 302 Found

注意

当重定向状态码为 302 Found 时,Web 浏览器可能会根据其实现更改 HTTP 方法(例如,将 POST 转换为 GET)。为了确保原始 HTTP 方法得到保留,特别是在需要非 GET 方法的情况下,您应该明确使用以下状态码之一

  • 303 See Other
  • 307 Temporary Redirect
  • 308 Permanent Redirect

例如,要保留 HTTP 方法,请使用

c.Redirect("/new-path", fiber.StatusSeeOther)

签名
func (c *Ctx) Redirect(location string, status ...int) error
示例
app.Get("/coffee", func(c *fiber.Ctx) error {
return c.Redirect("/teapot")
})

app.Get("/teapot", func(c *fiber.Ctx) error {
return c.Status(fiber.StatusTeapot).Send("🍵 short and stout 🍵")
})
更多示例
app.Get("/", func(c *fiber.Ctx) error {
return c.Redirect("/foo/bar")
return c.Redirect("../login")
return c.Redirect("http://example.com")
return c.Redirect("http://example.com", 301)
})

RedirectToRoute

重定向到特定路由并带上参数和指定的 HTTP 状态码(一个正整数)。

信息

如果未指定,状态默认为 302 Found

信息

如果要将查询发送到路由,必须向 params 添加类型为 map[string]string"queries" 键。

签名
func (c *Ctx) RedirectToRoute(routeName string, params fiber.Map, status ...int) error
示例
app.Get("/", func(c *fiber.Ctx) error {
// /user/fiber
return c.RedirectToRoute("user", fiber.Map{
"name": "fiber"
})
})

app.Get("/with-queries", func(c *fiber.Ctx) error {
// /user/fiber?data[0][name]=john&data[0][age]=10&test=doe
return c.RedirectToRoute("user", fiber.Map{
"name": "fiber",
"queries": map[string]string{"data[0][name]": "john", "data[0][age]": "10", "test": "doe"},
})
})

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

RedirectBack

重定向回引用 URL。如果 refer 头不存在,则重定向到备用 URL,并带有指定的 HTTP 状态码(一个正整数)。

信息

如果未指定,状态默认为 302 Found

签名
func (c *Ctx) RedirectBack(fallback string, status ...int) error
示例
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Home page")
})
app.Get("/test", func(c *fiber.Ctx) error {
c.Set("Content-Type", "text/html")
return c.SendString(`<a href="/back">Back</a>`)
})

app.Get("/back", func(c *fiber.Ctx) error {
return c.RedirectBack("/")
})

Render

使用数据渲染视图并发送 text/html 响应。默认情况下,Render 使用默认的 Go 模板引擎。如果想使用其他视图引擎,请查看我们的 模板中间件

签名
func (c *Ctx) Render(name string, bind interface{}, layouts ...string) error

Request

Request 返回 *fasthttp.Request 指针

签名
func (c *Ctx) Request() *fasthttp.Request
示例
app.Get("/", func(c *fiber.Ctx) error {
c.Request().Header.Method()
// => []byte("GET")
})

ReqHeaderParser

此方法类似于 BodyParser,但用于请求头。重要的是使用结构体标签 "reqHeader"。例如,如果要解析一个包含名为 Pass 字段的请求头,您将使用一个结构体字段 reqHeader:"pass"

签名
func (c *Ctx) ReqHeaderParser(out interface{}) error
示例
// Field names should start with an uppercase letter
type Person struct {
Name string `reqHeader:"name"`
Pass string `reqHeader:"pass"`
Products []string `reqHeader:"products"`
}

app.Get("/", func(c *fiber.Ctx) error {
p := new(Person)

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

log.Println(p.Name) // john
log.Println(p.Pass) // doe
log.Println(p.Products) // [shoe, hat]

// ...
})
// Run tests with the following curl command

// curl "http://localhost:3000/" -H "name: john" -H "pass: doe" -H "products: shoe,hat"

Response

Response 返回 *fasthttp.Response 指针

签名
func (c *Ctx) Response() *fasthttp.Response
示例
app.Get("/", func(c *fiber.Ctx) error {
c.Response().BodyWriter().Write([]byte("Hello, World!"))
// => "Hello, World!"
return nil
})

RestartRouting

调用 Next 时不是执行下一个方法,而是 RestartRouting 从匹配当前路由的第一个方法重新开始执行。这在覆盖路径后可能有用,例如内部重定向。请注意,处理器可能会再次执行,这可能导致无限循环。

签名
func (c *Ctx) RestartRouting() error
示例
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

返回匹配的 Route 结构体。

签名
func (c *Ctx) Route() *Route
示例
// 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]

// ...
})
注意

在调用 c.Next() 之前,不要在中间件中依赖 c.Route() - c.Route() 返回最后执行的路由

示例
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
}
}

SaveFile

此方法用于将任何 multipart 文件保存到磁盘。

签名
func (c *Ctx) SaveFile(fh *multipart.FileHeader, path string) error
示例
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

此方法用于将任何 multipart 文件保存到外部存储系统。

签名
func (c *Ctx) SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error
示例
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
}
})

Secure

如果建立了 TLS 连接,则此布尔属性为 true

签名
func (c *Ctx) Secure() bool
示例
// Secure() method is equivalent to:
c.Protocol() == "https"

Send

设置 HTTP 响应体。

签名
func (c *Ctx) Send(body []byte) error
示例
app.Get("/", func(c *fiber.Ctx) error {
return c.Send([]byte("Hello, World!")) // => "Hello, World!"
})

Fiber 还提供了用于原始输入的 SendStringSendStream 方法。

提示

如果不需要类型断言,请使用此方法,建议用于更快的性能。

签名
func (c *Ctx) SendString(body string) error
func (c *Ctx) SendStream(stream io.Reader, size ...int) error
示例
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
// => "Hello, World!"

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

SendFile

从给定路径传输文件。根据文件名的扩展名设置 Content-Type HTTP 响应头字段。

注意

此方法默认不使用 gzipping,将其设置为 true 即可启用。

签名
func (c *Ctx) SendFile(file string, compress ...bool) error
示例
app.Get("/not-found", func(c *fiber.Ctx) error {
return c.SendFile("./public/404.html");

// Disable compression
return c.SendFile("./static/index.html", false);
})
信息

如果文件包含特定于 URL 的字符,您必须在将文件路径传递给 sendFile 函数之前对其进行转义。

示例
app.Get("/file-with-url-chars", func(c *fiber.Ctx) error {
return c.SendFile(url.PathEscape("hash_sign_#.txt"))
})
信息

对于从嵌入式文件系统发送文件,可以使用此功能

SendStatus

如果响应体为,则设置状态码和体中的正确状态消息。

提示

您可以在这里找到所有使用的状态码和消息。

签名
func (c *Ctx) SendStatus(status int) error
示例
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!"
})

Set

将响应的 HTTP 头字段设置为指定的 keyvalue

签名
func (c *Ctx) Set(key string, val string)
示例
app.Get("/", func(c *fiber.Ctx) error {
c.Set("Content-Type", "text/plain")
// => "Content-type: text/plain"

// ...
})

SetParserDecoder

允许您配置 BodyParser/QueryParser 解码器,基于模式选项,提供了添加自定义解析类型的可能性。

签名
func SetParserDecoder(parserConfig fiber.ParserConfig{
IgnoreUnknownKeys bool,
ParserType []fiber.ParserType{
Customtype interface{},
Converter func(string) reflect.Value,
},
ZeroEmpty bool,
SetAliasTag string,
})
示例

type CustomTime time.Time

// String() returns the time in string
func (ct *CustomTime) String() string {
t := time.Time(*ct).String()
return t
}

// Register the converter for CustomTime type format as 2006-01-02
var timeConverter = func(value string) reflect.Value {
fmt.Println("timeConverter", value)
if v, err := time.Parse("2006-01-02", value); err == nil {
return reflect.ValueOf(v)
}
return reflect.Value{}
}

customTime := fiber.ParserType{
Customtype: CustomTime{},
Converter: timeConverter,
}

// Add setting to the Decoder
fiber.SetParserDecoder(fiber.ParserConfig{
IgnoreUnknownKeys: true,
ParserType: []fiber.ParserType{customTime},
ZeroEmpty: true,
})

// Example to use CustomType, you pause custom time format not in RFC3339
type Demo struct {
Date CustomTime `form:"date" query:"date"`
Title string `form:"title" query:"title"`
Body string `form:"body" query:"body"`
}

app.Post("/body", func(c *fiber.Ctx) error {
var d Demo
c.BodyParser(&d)
fmt.Println("d.Date", d.Date.String())
return c.JSON(d)
})

app.Get("/query", func(c *fiber.Ctx) error {
var d Demo
c.QueryParser(&d)
fmt.Println("d.Date", d.Date.String())
return c.JSON(d)
})

// curl -X POST -F title=title -F body=body -F date=2021-10-20 http://localhost:3000/body

// curl -X GET "http://localhost:3000/query?title=title&body=body&date=2021-10-20"

SetUserContext

为 context 接口设置用户指定的实现。

签名
func (c *Ctx) SetUserContext(ctx context.Context)
示例
app.Get("/", func(c *fiber.Ctx) error {
ctx := context.Background()
c.SetUserContext(ctx)
// Here ctx could be any context implementation

// ...
})

Stale

https://express.js.cn/en/4x/api.html#req.stale

签名
func (c *Ctx) Stale() bool

Status

设置响应的 HTTP 状态。

信息

此方法是链式的。

签名
func (c *Ctx) Status(status int) *Ctx
示例
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")
})

Subdomains

返回请求域名中的子域名字符串切片。

应用程序属性 subdomain offset(默认为 2)用于确定子域段的起始位置。

签名
func (c *Ctx) Subdomains(offset ...int) []string
示例
// Host: "tobi.ferrets.example.com"

app.Get("/", func(c *fiber.Ctx) error {
c.Subdomains() // ["ferrets", "tobi"]
c.Subdomains(1) // ["tobi"]

// ...
})

Type

Content-Type HTTP 头设置为由文件扩展名指定的 MIME 类型(可在这里找到列表)。

签名
func (c *Ctx) Type(ext string, charset ...string) *Ctx
示例
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"

// ...
})

UserContext

UserContext 返回用户之前设置的 context 实现,如果未设置,则返回一个非 nil 的空 context。

签名
func (c *Ctx) UserContext() context.Context
示例
app.Get("/", func(c *fiber.Ctx) error {
ctx := c.UserContext()
// ctx is context implementation set by user

// ...
})

Vary

将给定的头字段添加到 Vary 响应头中。如果头尚未列出,则会附加该头;否则,保留在当前位置列出。

信息

允许多个字段。

签名
func (c *Ctx) Vary(fields ...string)
示例
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

Write 实现了 Writer 接口

签名
func (c *Ctx) Write(p []byte) (n int, err error)
示例
app.Get("/", func(c *fiber.Ctx) error {
c.Write([]byte("Hello, World!")) // => "Hello, World!"

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

Writef

Writef 实现了带变量的字符串

签名
func (c *Ctx) Writef(f string, a ...interface{}) (n int, err error)
示例
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!Hello, World!"
})

WriteString

WriteString 实现了字符串

签名
func (c *Ctx) WriteString(s string) (n int, err error)
示例
app.Get("/", func(c *fiber.Ctx) error {
c.WriteString("Hello, World!") // => "Hello, World!"

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

XHR

一个布尔属性,如果请求的 X-Requested-With 头字段是 XMLHttpRequest,则为 true,表示该请求是由客户端库(例如 jQuery)发出的。

签名
func (c *Ctx) XHR() bool
示例
// X-Requested-With: XMLHttpRequest

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

// ...
})

XML

使用标准的 encoding/xml 包将任何 interfacestring 转换为 XML。

信息

XML 还会将内容头设置为 application/xml

签名
func (c *Ctx) XML(data interface{}) error
示例
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>
})