1
0
mirror of https://github.com/gofiber/fiber.git synced 2025-02-23 09:23:39 +00:00
fiber/request.go

443 lines
10 KiB
Go
Raw Normal View History

2020-02-08 01:05:13 +01:00
// 🚀 Fiber is an Express.js inspired web framework written in Go with 💖
2020-01-22 05:42:37 +01:00
// 📌 Please open an issue if you got suggestions or found a bug!
2020-02-08 01:05:13 +01:00
// 🖥 Links: https://github.com/gofiber/fiber, https://fiber.wiki
2020-01-20 04:33:55 +01:00
// 🦸 Not all heroes wear capes, thank you to some amazing people
2020-02-08 01:05:13 +01:00
// 💖 @valyala, @erikdubbelboer, @savsgio, @julienschmidt, @koddr
2020-01-20 04:33:55 +01:00
package fiber
import (
"encoding/base64"
2020-02-07 17:47:09 +01:00
"encoding/xml"
"fmt"
2020-01-20 04:33:55 +01:00
"mime"
"mime/multipart"
2020-02-13 06:48:14 +01:00
"net/url"
2020-01-20 04:33:55 +01:00
"strings"
2020-01-21 08:58:11 +01:00
2020-02-07 17:47:09 +01:00
jsoniter "github.com/json-iterator/go"
2020-02-16 18:00:14 +01:00
fasthttp "github.com/valyala/fasthttp"
2020-01-20 04:33:55 +01:00
)
2020-02-08 04:56:57 +01:00
// Accepts : https://fiber.wiki/context#accepts
2020-01-21 10:46:39 +01:00
func (ctx *Ctx) Accepts(offers ...string) string {
if len(offers) == 0 {
2020-02-05 02:53:07 +01:00
return ""
2020-01-20 04:33:55 +01:00
}
2020-01-30 23:17:25 -05:00
h := ctx.Get(fasthttp.HeaderAccept)
2020-01-21 08:58:11 +01:00
if h == "" {
2020-01-21 10:46:39 +01:00
return offers[0]
2020-01-21 08:58:11 +01:00
}
2020-01-21 10:46:39 +01:00
specs := strings.Split(h, ",")
for _, offer := range offers {
2020-01-30 23:17:25 -05:00
mimetype := getType(offer)
// if mimetype != "" {
// mimetype = strings.Split(mimetype, ";")[0]
// } else {
// mimetype = offer
// }
2020-01-21 10:46:39 +01:00
for _, spec := range specs {
spec = strings.TrimSpace(spec)
if strings.HasPrefix(spec, "*/*") {
return offer
}
2020-01-21 10:46:39 +01:00
if strings.HasPrefix(spec, mimetype) {
return offer
}
2020-01-21 10:46:39 +01:00
if strings.Contains(spec, "/*") {
if strings.HasPrefix(spec, strings.Split(mimetype, "/")[0]) {
return offer
}
}
2020-01-21 08:58:11 +01:00
}
}
return ""
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// AcceptsCharsets : https://fiber.wiki/context#acceptscharsets
2020-01-21 10:46:39 +01:00
func (ctx *Ctx) AcceptsCharsets(offers ...string) string {
if len(offers) == 0 {
2020-02-05 02:53:07 +01:00
return ""
2020-01-20 04:33:55 +01:00
}
2020-01-30 23:17:25 -05:00
h := ctx.Get(fasthttp.HeaderAcceptCharset)
2020-01-21 10:46:39 +01:00
if h == "" {
return offers[0]
}
2020-01-21 10:46:39 +01:00
specs := strings.Split(h, ",")
for _, offer := range offers {
for _, spec := range specs {
spec = strings.TrimSpace(spec)
if strings.HasPrefix(spec, "*") {
return offer
}
if strings.HasPrefix(spec, offer) {
return offer
}
}
}
return ""
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// AcceptsEncodings : https://fiber.wiki/context#acceptsencodings
2020-01-21 10:46:39 +01:00
func (ctx *Ctx) AcceptsEncodings(offers ...string) string {
if len(offers) == 0 {
2020-02-05 02:53:07 +01:00
return ""
2020-01-20 04:33:55 +01:00
}
2020-01-30 23:17:25 -05:00
h := ctx.Get(fasthttp.HeaderAcceptEncoding)
2020-01-21 10:46:39 +01:00
if h == "" {
return offers[0]
}
2020-01-21 10:46:39 +01:00
specs := strings.Split(h, ",")
for _, offer := range offers {
for _, spec := range specs {
spec = strings.TrimSpace(spec)
if strings.HasPrefix(spec, "*") {
return offer
}
if strings.HasPrefix(spec, offer) {
return offer
}
}
}
return ""
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// AcceptsLanguages : https://fiber.wiki/context#acceptslanguages
2020-01-21 10:46:39 +01:00
func (ctx *Ctx) AcceptsLanguages(offers ...string) string {
if len(offers) == 0 {
2020-02-05 02:53:07 +01:00
return ""
2020-01-20 04:33:55 +01:00
}
2020-01-30 23:17:25 -05:00
h := ctx.Get(fasthttp.HeaderAcceptLanguage)
2020-01-21 10:46:39 +01:00
if h == "" {
return offers[0]
}
2020-01-21 10:46:39 +01:00
specs := strings.Split(h, ",")
for _, offer := range offers {
for _, spec := range specs {
spec = strings.TrimSpace(spec)
if strings.HasPrefix(spec, "*") {
return offer
}
if strings.HasPrefix(spec, offer) {
return offer
}
}
}
return ""
2020-01-20 04:33:55 +01:00
}
2020-02-16 18:00:14 +01:00
// BaseUrl will be removed in v2
2020-02-06 16:24:09 +01:00
func (ctx *Ctx) BaseUrl() string {
fmt.Println("Fiber deprecated c.BaseUrl(), this will be removed in v2: Use c.BaseURL() instead")
return ctx.BaseURL()
}
2020-02-08 04:56:57 +01:00
// BaseURL : https://fiber.wiki/context#baseurl
func (ctx *Ctx) BaseURL() string {
2020-01-20 04:33:55 +01:00
return ctx.Protocol() + "://" + ctx.Hostname()
}
2020-02-08 04:56:57 +01:00
// BasicAuth : https://fiber.wiki/context#basicauth
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) BasicAuth() (user, pass string, ok bool) {
2020-02-16 18:00:14 +01:00
fmt.Println("Fiber deprecated c.BasicAuth(), this will be removed in v2 and be available as a separate middleware")
2020-01-30 23:17:25 -05:00
auth := ctx.Get(fasthttp.HeaderAuthorization)
2020-01-20 04:33:55 +01:00
if auth == "" {
return
}
2020-01-20 04:33:55 +01:00
const prefix = "Basic "
2020-01-20 04:33:55 +01:00
// Case insensitive prefix match.
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
return
}
2020-01-20 04:33:55 +01:00
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
if err != nil {
return
}
2020-01-30 23:17:25 -05:00
cs := getString(c)
2020-01-20 04:33:55 +01:00
s := strings.IndexByte(cs, ':')
if s < 0 {
return
}
2020-01-20 04:33:55 +01:00
return cs[:s], cs[s+1:], true
}
2020-02-08 04:56:57 +01:00
// Body : https://fiber.wiki/context#body
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Body(args ...interface{}) string {
if len(args) == 0 {
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.Request.Body())
2020-01-20 04:33:55 +01:00
}
2020-01-20 04:33:55 +01:00
if len(args) == 1 {
switch arg := args[0].(type) {
case string:
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.Request.PostArgs().Peek(arg))
2020-02-06 16:06:35 +01:00
case []byte:
return getString(ctx.Fasthttp.Request.PostArgs().PeekBytes(arg))
2020-01-20 04:33:55 +01:00
case func(string, string):
ctx.Fasthttp.Request.PostArgs().VisitAll(func(k []byte, v []byte) {
2020-01-30 23:17:25 -05:00
arg(getString(k), getString(v))
2020-01-20 04:33:55 +01:00
})
default:
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.Request.Body())
2020-01-20 04:33:55 +01:00
}
}
return ""
}
2020-02-08 04:56:57 +01:00
// BodyParser : https://fiber.wiki/context#bodyparser
2020-02-07 17:47:09 +01:00
func (ctx *Ctx) BodyParser(v interface{}) error {
2020-02-13 06:48:14 +01:00
ctype := getString(ctx.Fasthttp.Request.Header.ContentType())
// application/json
if strings.HasPrefix(ctype, mimeApplicationJSON) {
return jsoniter.Unmarshal(ctx.Fasthttp.Request.Body(), v)
}
// application/xml text/xml
if strings.HasPrefix(ctype, mimeApplicationXML) || strings.HasPrefix(ctype, mimeTextXML) {
return xml.Unmarshal(ctx.Fasthttp.Request.Body(), v)
}
// application/x-www-form-urlencoded
if strings.HasPrefix(ctype, mimeApplicationForm) {
data, err := url.ParseQuery(getString(ctx.Fasthttp.PostBody()))
if err != nil {
return err
}
return schemaDecoder.Decode(v, data)
}
// multipart/form-data
if strings.HasPrefix(ctype, mimeMultipartForm) {
data, err := ctx.Fasthttp.MultipartForm()
if err != nil {
return err
}
return schemaDecoder.Decode(v, data.Value)
2020-02-07 17:47:09 +01:00
}
2020-02-13 06:48:14 +01:00
return fmt.Errorf("cannot parse content-type: %v", ctype)
2020-02-07 17:47:09 +01:00
}
2020-02-08 04:56:57 +01:00
// Cookies : https://fiber.wiki/context#cookies
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Cookies(args ...interface{}) string {
if len(args) == 0 {
2020-01-30 23:17:25 -05:00
return ctx.Get(fasthttp.HeaderCookie)
2020-01-20 04:33:55 +01:00
}
2020-01-20 04:33:55 +01:00
switch arg := args[0].(type) {
case string:
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.Request.Header.Cookie(arg))
case []byte:
return getString(ctx.Fasthttp.Request.Header.CookieBytes(arg))
2020-01-20 04:33:55 +01:00
case func(string, string):
ctx.Fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) {
2020-01-30 23:17:25 -05:00
arg(getString(k), getString(v))
2020-01-20 04:33:55 +01:00
})
default:
2020-01-30 23:17:25 -05:00
return ctx.Get(fasthttp.HeaderCookie)
2020-01-20 04:33:55 +01:00
}
2020-01-20 04:33:55 +01:00
return ""
}
2020-02-12 13:23:47 -05:00
// Error returns err that is passed via Next(err)
func (ctx *Ctx) Error() error {
return ctx.error
}
2020-02-08 04:56:57 +01:00
// FormFile : https://fiber.wiki/context#formfile
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) FormFile(key string) (*multipart.FileHeader, error) {
return ctx.Fasthttp.FormFile(key)
}
2020-02-08 04:56:57 +01:00
// FormValue : https://fiber.wiki/context#formvalue
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) FormValue(key string) string {
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.FormValue(key))
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Fresh : https://fiber.wiki/context#fresh
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Fresh() bool {
2020-02-12 07:04:57 +01:00
return false
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Get : https://fiber.wiki/context#get
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Get(key string) string {
if key == "referrer" {
key = "referer"
}
2020-02-06 14:35:27 +01:00
return getString(ctx.Fasthttp.Request.Header.Peek(key))
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Hostname : https://fiber.wiki/context#hostname
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Hostname() string {
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.URI().Host())
2020-01-20 04:33:55 +01:00
}
2020-02-16 18:00:14 +01:00
// Ip will be removed in v2
2020-02-03 16:32:31 +01:00
func (ctx *Ctx) Ip() string {
fmt.Println("Fiber deprecated c.Ip(), this will be removed in v2: Use c.IP() instead")
return ctx.IP()
}
2020-02-08 04:56:57 +01:00
// IP : https://fiber.wiki/context#Ip
func (ctx *Ctx) IP() string {
2020-01-20 04:33:55 +01:00
return ctx.Fasthttp.RemoteIP().String()
}
2020-02-16 18:00:14 +01:00
// Ips will be removed in v2
func (ctx *Ctx) Ips() []string { // NOLINT
2020-02-03 16:32:31 +01:00
fmt.Println("Fiber deprecated c.Ips(), this will be removed in v2: Use c.IPs() instead")
return ctx.IPs()
}
2020-02-08 04:56:57 +01:00
// IPs : https://fiber.wiki/context#ips
func (ctx *Ctx) IPs() []string {
2020-01-30 23:17:25 -05:00
ips := strings.Split(ctx.Get(fasthttp.HeaderXForwardedFor), ",")
2020-01-20 04:33:55 +01:00
for i := range ips {
ips[i] = strings.TrimSpace(ips[i])
}
return ips
}
2020-02-08 04:56:57 +01:00
// Is : https://fiber.wiki/context#is
2020-02-16 18:00:14 +01:00
func (ctx *Ctx) IS(ext string) bool {
2020-01-20 04:33:55 +01:00
if ext[0] != '.' {
ext = "." + ext
}
2020-01-30 23:17:25 -05:00
exts, _ := mime.ExtensionsByType(ctx.Get(fasthttp.HeaderContentType))
2020-01-20 04:33:55 +01:00
if len(exts) > 0 {
for _, item := range exts {
if item == ext {
return true
}
}
}
return false
}
2020-02-08 04:56:57 +01:00
// Locals : https://fiber.wiki/context#locals
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Locals(key string, val ...interface{}) interface{} {
if len(val) == 0 {
return ctx.Fasthttp.UserValue(key)
}
ctx.Fasthttp.SetUserValue(key, val[0])
2020-01-20 04:33:55 +01:00
return nil
}
2020-02-08 04:56:57 +01:00
// Method : https://fiber.wiki/context#method
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Method() string {
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.Request.Header.Method())
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// MultipartForm : https://fiber.wiki/context#multipartform
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) MultipartForm() (*multipart.Form, error) {
return ctx.Fasthttp.MultipartForm()
}
2020-02-16 18:00:14 +01:00
// OriginalUrl will be removed in v2
func (ctx *Ctx) OriginalUrl() string {
2020-02-03 16:32:31 +01:00
fmt.Println("Fiber deprecated c.OriginalUrl(), this will be removed in v2: Use c.OriginalURL() instead")
return ctx.OriginalURL()
}
2020-02-08 04:56:57 +01:00
// OriginalURL : https://fiber.wiki/context#originalurl
func (ctx *Ctx) OriginalURL() string {
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.Request.Header.RequestURI())
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Params : https://fiber.wiki/context#params
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Params(key string) string {
for i := 0; i < len(*ctx.params); i++ {
if (*ctx.params)[i] == key {
return ctx.values[i]
}
}
return ""
}
2020-02-08 04:56:57 +01:00
// Path : https://fiber.wiki/context#path
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Path() string {
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.URI().Path())
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Protocol : https://fiber.wiki/context#protocol
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Protocol() string {
if ctx.Fasthttp.IsTLS() {
return "https"
}
return "http"
}
2020-02-08 04:56:57 +01:00
// Query : https://fiber.wiki/context#query
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Query(key string) string {
2020-01-30 23:17:25 -05:00
return getString(ctx.Fasthttp.QueryArgs().Peek(key))
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Range : https://fiber.wiki/context#range
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Range() {
2020-02-12 07:04:57 +01:00
// https://expressjs.com/en/api.html#req.range
// https://github.com/jshttp/range-parser/blob/master/index.js
// r := ctx.Fasthttp.Request.Header.Peek(fasthttp.HeaderRange)
// *magic*
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Route : https://fiber.wiki/context#route
func (ctx *Ctx) Route() *Route {
2020-01-28 14:28:09 -05:00
return ctx.route
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// SaveFile : https://fiber.wiki/context#secure
2020-02-05 02:53:07 +01:00
func (ctx *Ctx) SaveFile(fh *multipart.FileHeader, path string) error {
return fasthttp.SaveMultipartFile(fh, path)
2020-01-21 08:58:11 +01:00
}
2020-02-08 04:56:57 +01:00
// Secure : https://fiber.wiki/context#secure
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Secure() bool {
return ctx.Fasthttp.IsTLS()
}
2020-02-08 04:56:57 +01:00
// SignedCookies : https://fiber.wiki/context#signedcookies
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) SignedCookies() {
}
2020-02-08 04:56:57 +01:00
// Stale : https://fiber.wiki/context#stale
2020-01-20 04:33:55 +01:00
func (ctx *Ctx) Stale() bool {
2020-02-12 07:04:57 +01:00
return !ctx.Fresh()
2020-01-20 04:33:55 +01:00
}
2020-02-08 04:56:57 +01:00
// Subdomains : https://fiber.wiki/context#subdomains
2020-02-08 02:34:28 +01:00
func (ctx *Ctx) Subdomains(offset ...int) (subs []string) {
o := 2
if len(offset) > 0 {
o = offset[0]
}
2020-01-20 04:33:55 +01:00
subs = strings.Split(ctx.Hostname(), ".")
2020-02-08 02:34:28 +01:00
subs = subs[:len(subs)-o]
2020-01-20 04:33:55 +01:00
return subs
}
2020-02-16 18:00:14 +01:00
// Xhr will be removed in v2
func (ctx *Ctx) Xhr() bool {
2020-02-03 16:32:31 +01:00
fmt.Println("Fiber deprecated c.Xhr(), this will be removed in v2: Use c.XHR() instead")
return ctx.XHR()
}
2020-02-08 04:56:57 +01:00
// XHR : https://fiber.wiki/context#xhr
func (ctx *Ctx) XHR() bool {
2020-02-05 02:53:07 +01:00
return ctx.Get(fasthttp.HeaderXRequestedWith) == "XMLHttpRequest"
2020-01-20 04:33:55 +01:00
}