mirror of https://github.com/gofiber/fiber.git
v1.8.0
parent
63353cac7b
commit
2eeb40273c
122
app.go
122
app.go
|
@ -23,7 +23,7 @@ import (
|
|||
)
|
||||
|
||||
// Version of Fiber
|
||||
const Version = "1.7.1"
|
||||
const Version = "1.8.0"
|
||||
|
||||
type (
|
||||
// App denotes the Fiber application.
|
||||
|
@ -46,6 +46,8 @@ type (
|
|||
CaseSensitive bool `default:"false"`
|
||||
// Enables the "Server: value" HTTP header.
|
||||
ServerHeader string `default:""`
|
||||
// Enables handler values to be immutable even if you return from handler
|
||||
Immutable bool `default:"false"`
|
||||
// fasthttp settings
|
||||
GETOnly bool `default:"false"`
|
||||
IdleTimeout time.Duration `default:"0"`
|
||||
|
@ -72,19 +74,34 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
var prefork = flag.Bool("fiber-prefork", false, "use prefork")
|
||||
var child = flag.Bool("fiber-child", false, "is child process")
|
||||
func init() {
|
||||
flag.Bool("prefork", false, "Use prefork")
|
||||
flag.Bool("child", false, "Is a child process")
|
||||
}
|
||||
|
||||
// New ...
|
||||
// New : https://fiber.wiki/application#new
|
||||
func New(settings ...*Settings) (app *App) {
|
||||
flag.Parse()
|
||||
var prefork bool
|
||||
var child bool
|
||||
for _, arg := range os.Args[1:] {
|
||||
if arg == "-prefork" {
|
||||
prefork = true
|
||||
} else if arg == "-child" {
|
||||
child = true
|
||||
}
|
||||
}
|
||||
app = &App{
|
||||
child: *child,
|
||||
child: child,
|
||||
}
|
||||
if len(settings) > 0 {
|
||||
opt := settings[0]
|
||||
if !opt.Prefork {
|
||||
opt.Prefork = *prefork
|
||||
opt.Prefork = prefork
|
||||
}
|
||||
if opt.Immutable {
|
||||
getString = func(b []byte) string {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
if opt.Concurrency == 0 {
|
||||
opt.Concurrency = 256 * 1024
|
||||
|
@ -102,7 +119,7 @@ func New(settings ...*Settings) (app *App) {
|
|||
return
|
||||
}
|
||||
app.Settings = &Settings{
|
||||
Prefork: *prefork,
|
||||
Prefork: prefork,
|
||||
Concurrency: 256 * 1024,
|
||||
ReadBufferSize: 4096,
|
||||
WriteBufferSize: 4096,
|
||||
|
@ -111,89 +128,89 @@ func New(settings ...*Settings) (app *App) {
|
|||
return
|
||||
}
|
||||
|
||||
// Recover
|
||||
func (app *App) Recover(cb func(*Ctx)) {
|
||||
app.recover = cb
|
||||
// Recover : https://fiber.wiki/application#recover
|
||||
func (app *App) Recover(callback func(*Ctx)) {
|
||||
app.recover = callback
|
||||
}
|
||||
|
||||
// Recover
|
||||
func (grp *Group) Recover(cb func(*Ctx)) {
|
||||
grp.app.recover = cb
|
||||
// Recover : https://fiber.wiki/application#recover
|
||||
func (grp *Group) Recover(callback func(*Ctx)) {
|
||||
grp.app.recover = callback
|
||||
}
|
||||
|
||||
// Static ...
|
||||
// Static : https://fiber.wiki/application#static
|
||||
func (app *App) Static(args ...string) *App {
|
||||
app.registerStatic("/", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// WebSocket ...
|
||||
// WebSocket : https://fiber.wiki/application#websocket
|
||||
func (app *App) WebSocket(args ...interface{}) *App {
|
||||
app.register("GET", "", args...)
|
||||
app.register(http.MethodGet, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Connect ...
|
||||
// Connect : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Connect(args ...interface{}) *App {
|
||||
app.register("CONNECT", "", args...)
|
||||
app.register(http.MethodConnect, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Put ...
|
||||
// Put : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Put(args ...interface{}) *App {
|
||||
app.register("PUT", "", args...)
|
||||
app.register(http.MethodPut, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Post ...
|
||||
// Post : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Post(args ...interface{}) *App {
|
||||
app.register("POST", "", args...)
|
||||
app.register(http.MethodPost, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
// Delete : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Delete(args ...interface{}) *App {
|
||||
app.register("DELETE", "", args...)
|
||||
app.register(http.MethodDelete, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Head ...
|
||||
// Head : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Head(args ...interface{}) *App {
|
||||
app.register("HEAD", "", args...)
|
||||
app.register(http.MethodHead, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Patch ...
|
||||
// Patch : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Patch(args ...interface{}) *App {
|
||||
app.register("PATCH", "", args...)
|
||||
app.register(http.MethodPatch, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Options ...
|
||||
// Options : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Options(args ...interface{}) *App {
|
||||
app.register("OPTIONS", "", args...)
|
||||
app.register(http.MethodOptions, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Trace ...
|
||||
// Trace : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Trace(args ...interface{}) *App {
|
||||
app.register("TRACE", "", args...)
|
||||
app.register(http.MethodOptions, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Get ...
|
||||
// Get : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Get(args ...interface{}) *App {
|
||||
app.register("GET", "", args...)
|
||||
app.register(http.MethodGet, "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// All ...
|
||||
// All : https://fiber.wiki/application#http-methods
|
||||
func (app *App) All(args ...interface{}) *App {
|
||||
app.register("ALL", "", args...)
|
||||
return app
|
||||
}
|
||||
|
||||
// Use ...
|
||||
// Use : https://fiber.wiki/application#http-methods
|
||||
func (app *App) Use(args ...interface{}) *App {
|
||||
app.register("USE", "", args...)
|
||||
return app
|
||||
|
@ -214,10 +231,10 @@ func (app *App) Listen(address interface{}, tls ...string) error {
|
|||
}
|
||||
// Create fasthttp server
|
||||
app.server = app.newServer()
|
||||
// Print banner
|
||||
// if app.Settings.Banner && !app.child {
|
||||
// fmt.Printf("Fiber-%s is listening on %s\n", Version, addr)
|
||||
// }
|
||||
// Print listening message
|
||||
if !app.child {
|
||||
fmt.Printf("Fiber v%s listening on %s\n", Version, addr)
|
||||
}
|
||||
var ln net.Listener
|
||||
var err error
|
||||
// Prefork enabled
|
||||
|
@ -238,7 +255,8 @@ func (app *App) Listen(address interface{}, tls ...string) error {
|
|||
return app.server.Serve(ln)
|
||||
}
|
||||
|
||||
// Shutdown server gracefully
|
||||
// Shutdown : TODO: Docs
|
||||
// Shutsdown the server gracefully
|
||||
func (app *App) Shutdown() error {
|
||||
if app.server == nil {
|
||||
return fmt.Errorf("Server is not running")
|
||||
|
@ -246,11 +264,10 @@ func (app *App) Shutdown() error {
|
|||
return app.server.Shutdown()
|
||||
}
|
||||
|
||||
// Test takes a http.Request and execute a fake connection to the application
|
||||
// It returns a http.Response when the connection was successful
|
||||
func (app *App) Test(req *http.Request) (*http.Response, error) {
|
||||
// Test : https://fiber.wiki/application#test
|
||||
func (app *App) Test(request *http.Request) (*http.Response, error) {
|
||||
// Get raw http request
|
||||
reqRaw, err := httputil.DumpRequest(req, true)
|
||||
reqRaw, err := httputil.DumpRequest(request, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -287,7 +304,7 @@ func (app *App) Test(req *http.Request) (*http.Response, error) {
|
|||
reader := strings.NewReader(getString(respRaw))
|
||||
buffer := bufio.NewReader(reader)
|
||||
// Convert raw HTTP response to http.Response
|
||||
resp, err := http.ReadResponse(buffer, req)
|
||||
resp, err := http.ReadResponse(buffer, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -299,11 +316,11 @@ func (app *App) Test(req *http.Request) (*http.Response, error) {
|
|||
func (app *App) prefork(address string) (ln net.Listener, err error) {
|
||||
// Master proc
|
||||
if !app.child {
|
||||
addr, err := net.ResolveTCPAddr("tcp", address)
|
||||
addr, err := net.ResolveTCPAddr("tcp4", address)
|
||||
if err != nil {
|
||||
return ln, err
|
||||
}
|
||||
tcplistener, err := net.ListenTCP("tcp", addr)
|
||||
tcplistener, err := net.ListenTCP("tcp4", addr)
|
||||
if err != nil {
|
||||
return ln, err
|
||||
}
|
||||
|
@ -311,14 +328,14 @@ func (app *App) prefork(address string) (ln net.Listener, err error) {
|
|||
if err != nil {
|
||||
return ln, err
|
||||
}
|
||||
files := []*os.File{fl}
|
||||
childs := make([]*exec.Cmd, runtime.NumCPU()/2)
|
||||
|
||||
// #nosec G204
|
||||
for i := range childs {
|
||||
childs[i] = exec.Command(os.Args[0], "-fiber-prefork", "-fiber-child")
|
||||
childs[i] = exec.Command(os.Args[0], append(os.Args[1:], "-prefork", "-child")...)
|
||||
childs[i].Stdout = os.Stdout
|
||||
childs[i].Stderr = os.Stderr
|
||||
childs[i].ExtraFiles = []*os.File{fl}
|
||||
childs[i].ExtraFiles = files
|
||||
if err := childs[i].Start(); err != nil {
|
||||
return ln, err
|
||||
}
|
||||
|
@ -331,6 +348,7 @@ func (app *App) prefork(address string) (ln net.Listener, err error) {
|
|||
}
|
||||
os.Exit(0)
|
||||
} else {
|
||||
runtime.GOMAXPROCS(1)
|
||||
ln, err = net.FileListener(os.NewFile(3, ""))
|
||||
}
|
||||
return ln, err
|
||||
|
|
368
context.go
368
context.go
|
@ -5,10 +5,8 @@
|
|||
package fiber
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime"
|
||||
|
@ -19,14 +17,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
// templates
|
||||
pug "github.com/Joker/jade"
|
||||
handlebars "github.com/aymerick/raymond"
|
||||
mustache "github.com/cbroglie/mustache"
|
||||
amber "github.com/eknkc/amber"
|
||||
|
||||
// core
|
||||
websocket "github.com/fasthttp/websocket"
|
||||
template "github.com/gofiber/template"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
fasthttp "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
@ -42,7 +34,6 @@ type Ctx struct {
|
|||
params *[]string
|
||||
values []string
|
||||
Fasthttp *fasthttp.RequestCtx
|
||||
Socket *websocket.Conn
|
||||
}
|
||||
|
||||
// Ctx pool
|
||||
|
@ -67,7 +58,6 @@ func releaseCtx(ctx *Ctx) {
|
|||
ctx.params = nil
|
||||
ctx.values = nil
|
||||
ctx.Fasthttp = nil
|
||||
ctx.Socket = nil
|
||||
poolCtx.Put(ctx)
|
||||
}
|
||||
|
||||
|
@ -115,18 +105,17 @@ func releaseConn(conn *Conn) {
|
|||
|
||||
// Cookie : struct
|
||||
type Cookie struct {
|
||||
Expire int // time.Unix(1578981376, 0)
|
||||
MaxAge int
|
||||
Domain string
|
||||
Path string
|
||||
|
||||
HTTPOnly bool
|
||||
Name string
|
||||
Value string
|
||||
Path string
|
||||
Domain string
|
||||
Expires time.Time
|
||||
Secure bool
|
||||
SameSite string
|
||||
HTTPOnly bool
|
||||
}
|
||||
|
||||
// Accepts : https://fiber.wiki/context#accepts
|
||||
func (ctx *Ctx) Accepts(offers ...string) string {
|
||||
func (ctx *Ctx) Accepts(offers ...string) (offer string) {
|
||||
if len(offers) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
@ -136,8 +125,8 @@ func (ctx *Ctx) Accepts(offers ...string) string {
|
|||
}
|
||||
|
||||
specs := strings.Split(h, ",")
|
||||
for _, offer := range offers {
|
||||
mimetype := getType(offer)
|
||||
for _, value := range offers {
|
||||
mimetype := getType(value)
|
||||
// if mimetype != "" {
|
||||
// mimetype = strings.Split(mimetype, ";")[0]
|
||||
// } else {
|
||||
|
@ -146,16 +135,16 @@ func (ctx *Ctx) Accepts(offers ...string) string {
|
|||
for _, spec := range specs {
|
||||
spec = strings.TrimSpace(spec)
|
||||
if strings.HasPrefix(spec, "*/*") {
|
||||
return offer
|
||||
return value
|
||||
}
|
||||
|
||||
if strings.HasPrefix(spec, mimetype) {
|
||||
return offer
|
||||
return value
|
||||
}
|
||||
|
||||
if strings.Contains(spec, "/*") {
|
||||
if strings.HasPrefix(spec, strings.Split(mimetype, "/")[0]) {
|
||||
return offer
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +153,7 @@ func (ctx *Ctx) Accepts(offers ...string) string {
|
|||
}
|
||||
|
||||
// AcceptsCharsets : https://fiber.wiki/context#acceptscharsets
|
||||
func (ctx *Ctx) AcceptsCharsets(offers ...string) string {
|
||||
func (ctx *Ctx) AcceptsCharsets(offers ...string) (offer string) {
|
||||
if len(offers) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
@ -175,14 +164,14 @@ func (ctx *Ctx) AcceptsCharsets(offers ...string) string {
|
|||
}
|
||||
|
||||
specs := strings.Split(h, ",")
|
||||
for _, offer := range offers {
|
||||
for _, value := range offers {
|
||||
for _, spec := range specs {
|
||||
spec = strings.TrimSpace(spec)
|
||||
if strings.HasPrefix(spec, "*") {
|
||||
return offer
|
||||
return value
|
||||
}
|
||||
if strings.HasPrefix(spec, offer) {
|
||||
return offer
|
||||
if strings.HasPrefix(spec, value) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +179,7 @@ func (ctx *Ctx) AcceptsCharsets(offers ...string) string {
|
|||
}
|
||||
|
||||
// AcceptsEncodings : https://fiber.wiki/context#acceptsencodings
|
||||
func (ctx *Ctx) AcceptsEncodings(offers ...string) string {
|
||||
func (ctx *Ctx) AcceptsEncodings(offers ...string) (offer string) {
|
||||
if len(offers) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
@ -201,14 +190,14 @@ func (ctx *Ctx) AcceptsEncodings(offers ...string) string {
|
|||
}
|
||||
|
||||
specs := strings.Split(h, ",")
|
||||
for _, offer := range offers {
|
||||
for _, value := range offers {
|
||||
for _, spec := range specs {
|
||||
spec = strings.TrimSpace(spec)
|
||||
if strings.HasPrefix(spec, "*") {
|
||||
return offer
|
||||
return value
|
||||
}
|
||||
if strings.HasPrefix(spec, offer) {
|
||||
return offer
|
||||
if strings.HasPrefix(spec, value) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +205,7 @@ func (ctx *Ctx) AcceptsEncodings(offers ...string) string {
|
|||
}
|
||||
|
||||
// AcceptsLanguages : https://fiber.wiki/context#acceptslanguages
|
||||
func (ctx *Ctx) AcceptsLanguages(offers ...string) string {
|
||||
func (ctx *Ctx) AcceptsLanguages(offers ...string) (offer string) {
|
||||
if len(offers) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
@ -226,14 +215,14 @@ func (ctx *Ctx) AcceptsLanguages(offers ...string) string {
|
|||
}
|
||||
|
||||
specs := strings.Split(h, ",")
|
||||
for _, offer := range offers {
|
||||
for _, value := range offers {
|
||||
for _, spec := range specs {
|
||||
spec = strings.TrimSpace(spec)
|
||||
if strings.HasPrefix(spec, "*") {
|
||||
return offer
|
||||
return value
|
||||
}
|
||||
if strings.HasPrefix(spec, offer) {
|
||||
return offer
|
||||
if strings.HasPrefix(spec, value) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,38 +262,29 @@ func (ctx *Ctx) BaseURL() string {
|
|||
}
|
||||
|
||||
// Body : https://fiber.wiki/context#body
|
||||
func (ctx *Ctx) Body(args ...interface{}) string {
|
||||
if len(args) == 0 {
|
||||
func (ctx *Ctx) Body(key ...string) string {
|
||||
// Return request body
|
||||
if len(key) == 0 {
|
||||
return getString(ctx.Fasthttp.Request.Body())
|
||||
}
|
||||
|
||||
if len(args) == 1 {
|
||||
switch arg := args[0].(type) {
|
||||
case string:
|
||||
return getString(ctx.Fasthttp.Request.PostArgs().Peek(arg))
|
||||
case []byte:
|
||||
return getString(ctx.Fasthttp.Request.PostArgs().PeekBytes(arg))
|
||||
case func(string, string):
|
||||
ctx.Fasthttp.Request.PostArgs().VisitAll(func(k []byte, v []byte) {
|
||||
arg(getString(k), getString(v))
|
||||
})
|
||||
default:
|
||||
return getString(ctx.Fasthttp.Request.Body())
|
||||
}
|
||||
// Return post value by key
|
||||
if len(key) > 0 {
|
||||
return getString(ctx.Fasthttp.Request.PostArgs().Peek(key[0]))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// BodyParser : https://fiber.wiki/context#bodyparser
|
||||
func (ctx *Ctx) BodyParser(v interface{}) error {
|
||||
func (ctx *Ctx) BodyParser(out interface{}) error {
|
||||
// TODO : Query Params
|
||||
ctype := getString(ctx.Fasthttp.Request.Header.ContentType())
|
||||
// application/json
|
||||
if strings.HasPrefix(ctype, MIMEApplicationJSON) {
|
||||
return jsoniter.Unmarshal(ctx.Fasthttp.Request.Body(), v)
|
||||
return jsoniter.Unmarshal(ctx.Fasthttp.Request.Body(), out)
|
||||
}
|
||||
// application/xml text/xml
|
||||
if strings.HasPrefix(ctype, MIMEApplicationXML) || strings.HasPrefix(ctype, MIMETextXML) {
|
||||
return xml.Unmarshal(ctx.Fasthttp.Request.Body(), v)
|
||||
return xml.Unmarshal(ctx.Fasthttp.Request.Body(), out)
|
||||
}
|
||||
// application/x-www-form-urlencoded
|
||||
if strings.HasPrefix(ctype, MIMEApplicationForm) {
|
||||
|
@ -312,7 +292,7 @@ func (ctx *Ctx) BodyParser(v interface{}) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return schemaDecoder.Decode(v, data)
|
||||
return schemaDecoder.Decode(out, data)
|
||||
}
|
||||
// multipart/form-data
|
||||
if strings.HasPrefix(ctype, MIMEMultipartForm) {
|
||||
|
@ -320,18 +300,18 @@ func (ctx *Ctx) BodyParser(v interface{}) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return schemaDecoder.Decode(v, data.Value)
|
||||
return schemaDecoder.Decode(out, data.Value)
|
||||
|
||||
}
|
||||
return fmt.Errorf("cannot parse content-type: %v", ctype)
|
||||
return fmt.Errorf("BodyParser: cannot parse content-type: %v", ctype)
|
||||
}
|
||||
|
||||
// ClearCookie : https://fiber.wiki/context#clearcookie
|
||||
func (ctx *Ctx) ClearCookie(name ...string) {
|
||||
if len(name) > 0 {
|
||||
for i := range name {
|
||||
func (ctx *Ctx) ClearCookie(key ...string) {
|
||||
if len(key) > 0 {
|
||||
for i := range key {
|
||||
//ctx.Fasthttp.Request.Header.DelAllCookies()
|
||||
ctx.Fasthttp.Response.Header.DelClientCookie(name[i])
|
||||
ctx.Fasthttp.Response.Header.DelClientCookie(key[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -342,75 +322,24 @@ func (ctx *Ctx) ClearCookie(name ...string) {
|
|||
}
|
||||
|
||||
// Cookie : https://fiber.wiki/context#cookie
|
||||
func (ctx *Ctx) Cookie(key, value string, options ...interface{}) {
|
||||
cook := &fasthttp.Cookie{}
|
||||
|
||||
cook.SetKey(key)
|
||||
cook.SetValue(value)
|
||||
|
||||
if len(options) > 0 {
|
||||
switch opt := options[0].(type) {
|
||||
case *Cookie:
|
||||
if opt.Expire > 0 {
|
||||
cook.SetExpire(time.Unix(int64(opt.Expire), 0))
|
||||
}
|
||||
if opt.MaxAge > 0 {
|
||||
cook.SetMaxAge(opt.MaxAge)
|
||||
}
|
||||
if opt.Domain != "" {
|
||||
cook.SetDomain(opt.Domain)
|
||||
}
|
||||
if opt.Path != "" {
|
||||
cook.SetPath(opt.Path)
|
||||
}
|
||||
if opt.HTTPOnly {
|
||||
cook.SetHTTPOnly(opt.HTTPOnly)
|
||||
}
|
||||
if opt.Secure {
|
||||
cook.SetSecure(opt.Secure)
|
||||
}
|
||||
if opt.SameSite != "" {
|
||||
sameSite := fasthttp.CookieSameSiteDefaultMode
|
||||
if strings.EqualFold(opt.SameSite, "lax") {
|
||||
sameSite = fasthttp.CookieSameSiteLaxMode
|
||||
} else if strings.EqualFold(opt.SameSite, "strict") {
|
||||
sameSite = fasthttp.CookieSameSiteStrictMode
|
||||
} else if strings.EqualFold(opt.SameSite, "none") {
|
||||
sameSite = fasthttp.CookieSameSiteNoneMode
|
||||
}
|
||||
// } else {
|
||||
// sameSite = fasthttp.CookieSameSiteDisabled
|
||||
// }
|
||||
cook.SetSameSite(sameSite)
|
||||
}
|
||||
default:
|
||||
log.Println("Cookie: Invalid &Cookie{} struct")
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Fasthttp.Response.Header.SetCookie(cook)
|
||||
func (ctx *Ctx) Cookie(cookie *Cookie) {
|
||||
fcookie := &fasthttp.Cookie{}
|
||||
fcookie.SetKey(cookie.Name)
|
||||
fcookie.SetValue(cookie.Value)
|
||||
fcookie.SetPath(cookie.Path)
|
||||
fcookie.SetDomain(cookie.Domain)
|
||||
fcookie.SetExpire(cookie.Expires)
|
||||
fcookie.SetSecure(cookie.Secure)
|
||||
fcookie.SetHTTPOnly(cookie.HTTPOnly)
|
||||
ctx.Fasthttp.Response.Header.SetCookie(fcookie)
|
||||
}
|
||||
|
||||
// Cookies : https://fiber.wiki/context#cookies
|
||||
func (ctx *Ctx) Cookies(args ...interface{}) string {
|
||||
if len(args) == 0 {
|
||||
func (ctx *Ctx) Cookies(key ...string) (value string) {
|
||||
if len(key) == 0 {
|
||||
return ctx.Get(fasthttp.HeaderCookie)
|
||||
}
|
||||
|
||||
switch arg := args[0].(type) {
|
||||
case string:
|
||||
return getString(ctx.Fasthttp.Request.Header.Cookie(arg))
|
||||
case []byte:
|
||||
return getString(ctx.Fasthttp.Request.Header.CookieBytes(arg))
|
||||
case func(string, string):
|
||||
ctx.Fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) {
|
||||
arg(getString(k), getString(v))
|
||||
})
|
||||
default:
|
||||
return ctx.Get(fasthttp.HeaderCookie)
|
||||
}
|
||||
|
||||
return ""
|
||||
return getString(ctx.Fasthttp.Request.Header.Cookie(key[0]))
|
||||
}
|
||||
|
||||
// Download : https://fiber.wiki/context#download
|
||||
|
@ -431,30 +360,27 @@ func (ctx *Ctx) Error() error {
|
|||
}
|
||||
|
||||
// Format : https://fiber.wiki/context#format
|
||||
func (ctx *Ctx) Format(args ...interface{}) {
|
||||
var body string
|
||||
|
||||
func (ctx *Ctx) Format(body interface{}) {
|
||||
var b string
|
||||
accept := ctx.Accepts("html", "json")
|
||||
|
||||
for i := range args {
|
||||
switch arg := args[i].(type) {
|
||||
case string:
|
||||
body = arg
|
||||
case []byte:
|
||||
body = getString(arg)
|
||||
default:
|
||||
body = fmt.Sprintf("%v", arg)
|
||||
}
|
||||
switch accept {
|
||||
case "html":
|
||||
ctx.SendString("<p>" + body + "</p>")
|
||||
case "json":
|
||||
if err := ctx.JSON(body); err != nil {
|
||||
log.Println("Format: error serializing json ", err)
|
||||
}
|
||||
default:
|
||||
ctx.SendString(body)
|
||||
switch val := body.(type) {
|
||||
case string:
|
||||
b = val
|
||||
case []byte:
|
||||
b = getString(val)
|
||||
default:
|
||||
b = fmt.Sprintf("%v", val)
|
||||
}
|
||||
switch accept {
|
||||
case "html":
|
||||
ctx.SendString("<p>" + b + "</p>")
|
||||
case "json":
|
||||
if err := ctx.JSON(body); err != nil {
|
||||
log.Println("Format: error serializing json ", err)
|
||||
}
|
||||
default:
|
||||
ctx.SendString(b)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,7 +390,7 @@ func (ctx *Ctx) FormFile(key string) (*multipart.FileHeader, error) {
|
|||
}
|
||||
|
||||
// FormValue : https://fiber.wiki/context#formvalue
|
||||
func (ctx *Ctx) FormValue(key string) string {
|
||||
func (ctx *Ctx) FormValue(key string) (value string) {
|
||||
return getString(ctx.Fasthttp.FormValue(key))
|
||||
}
|
||||
|
||||
|
@ -474,7 +400,7 @@ func (ctx *Ctx) Fresh() bool {
|
|||
}
|
||||
|
||||
// Get : https://fiber.wiki/context#get
|
||||
func (ctx *Ctx) Get(key string) string {
|
||||
func (ctx *Ctx) Get(key string) (value string) {
|
||||
if key == "referrer" {
|
||||
key = "referer"
|
||||
}
|
||||
|
@ -501,26 +427,26 @@ func (ctx *Ctx) IPs() []string {
|
|||
}
|
||||
|
||||
// Is : https://fiber.wiki/context#is
|
||||
func (ctx *Ctx) Is(ext string) bool {
|
||||
if ext[0] != '.' {
|
||||
ext = "." + ext
|
||||
func (ctx *Ctx) Is(extension string) (match bool) {
|
||||
if extension[0] != '.' {
|
||||
extension = "." + extension
|
||||
}
|
||||
|
||||
exts, _ := mime.ExtensionsByType(ctx.Get(fasthttp.HeaderContentType))
|
||||
if len(exts) > 0 {
|
||||
for _, item := range exts {
|
||||
if item == ext {
|
||||
if item == extension {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
// JSON : https://fiber.wiki/context#json
|
||||
func (ctx *Ctx) JSON(v interface{}) error {
|
||||
func (ctx *Ctx) JSON(json interface{}) error {
|
||||
ctx.Fasthttp.Response.Header.SetContentType(MIMEApplicationJSON)
|
||||
raw, err := jsoniter.Marshal(&v)
|
||||
raw, err := jsoniter.Marshal(&json)
|
||||
if err != nil {
|
||||
ctx.Fasthttp.Response.SetBodyString("")
|
||||
return err
|
||||
|
@ -531,15 +457,15 @@ func (ctx *Ctx) JSON(v interface{}) error {
|
|||
}
|
||||
|
||||
// JSONP : https://fiber.wiki/context#jsonp
|
||||
func (ctx *Ctx) JSONP(v interface{}, cb ...string) error {
|
||||
raw, err := jsoniter.Marshal(&v)
|
||||
func (ctx *Ctx) JSONP(json interface{}, callback ...string) error {
|
||||
raw, err := jsoniter.Marshal(&json)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
str := "callback("
|
||||
if len(cb) > 0 {
|
||||
str = cb[0] + "("
|
||||
if len(callback) > 0 {
|
||||
str = callback[0] + "("
|
||||
}
|
||||
str += getString(raw) + ");"
|
||||
|
||||
|
@ -568,12 +494,12 @@ func (ctx *Ctx) Links(link ...string) {
|
|||
}
|
||||
|
||||
// Locals : https://fiber.wiki/context#locals
|
||||
func (ctx *Ctx) Locals(key string, val ...interface{}) interface{} {
|
||||
if len(val) == 0 {
|
||||
func (ctx *Ctx) Locals(key string, value ...interface{}) (val interface{}) {
|
||||
if len(value) == 0 {
|
||||
return ctx.Fasthttp.UserValue(key)
|
||||
}
|
||||
ctx.Fasthttp.SetUserValue(key, val[0])
|
||||
return nil
|
||||
ctx.Fasthttp.SetUserValue(key, value[0])
|
||||
return value[0]
|
||||
}
|
||||
|
||||
// Location : https://fiber.wiki/context#location
|
||||
|
@ -608,16 +534,16 @@ func (ctx *Ctx) OriginalURL() string {
|
|||
}
|
||||
|
||||
// Params : https://fiber.wiki/context#params
|
||||
func (ctx *Ctx) Params(key string) string {
|
||||
func (ctx *Ctx) Params(key string) (value string) {
|
||||
if ctx.params == nil {
|
||||
return ""
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(*ctx.params); i++ {
|
||||
if (*ctx.params)[i] == key {
|
||||
return ctx.values[i]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return
|
||||
}
|
||||
|
||||
// Path : https://fiber.wiki/context#path
|
||||
|
@ -634,7 +560,7 @@ func (ctx *Ctx) Protocol() string {
|
|||
}
|
||||
|
||||
// Query : https://fiber.wiki/context#query
|
||||
func (ctx *Ctx) Query(key string) string {
|
||||
func (ctx *Ctx) Query(key string) (value string) {
|
||||
return getString(ctx.Fasthttp.QueryArgs().Peek(key))
|
||||
}
|
||||
|
||||
|
@ -642,7 +568,7 @@ func (ctx *Ctx) Query(key string) string {
|
|||
func (ctx *Ctx) Range() {
|
||||
// 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)
|
||||
// r := ctx.Fasthttp.Request.Header.Peek(HeaderRange)
|
||||
// *magic*
|
||||
}
|
||||
|
||||
|
@ -658,18 +584,18 @@ func (ctx *Ctx) Redirect(path string, status ...int) {
|
|||
}
|
||||
|
||||
// Render : https://fiber.wiki/context#render
|
||||
func (ctx *Ctx) Render(file string, data interface{}, e ...string) error {
|
||||
func (ctx *Ctx) Render(file string, bind interface{}, engine ...string) error {
|
||||
var err error
|
||||
var raw []byte
|
||||
var html string
|
||||
var engine string
|
||||
var e string
|
||||
|
||||
if len(e) > 0 {
|
||||
engine = e[0]
|
||||
if len(engine) > 0 {
|
||||
e = engine[0]
|
||||
} else if ctx.app.Settings.ViewEngine != "" {
|
||||
engine = ctx.app.Settings.ViewEngine
|
||||
e = ctx.app.Settings.ViewEngine
|
||||
} else {
|
||||
engine = filepath.Ext(file)[1:]
|
||||
e = filepath.Ext(file)[1:]
|
||||
}
|
||||
if ctx.app.Settings.ViewFolder != "" {
|
||||
file = filepath.Join(ctx.app.Settings.ViewFolder, file)
|
||||
|
@ -681,53 +607,27 @@ func (ctx *Ctx) Render(file string, data interface{}, e ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
switch engine {
|
||||
switch e {
|
||||
case "amber": // https://github.com/eknkc/amber
|
||||
var buf bytes.Buffer
|
||||
var tmpl *template.Template
|
||||
|
||||
if tmpl, err = amber.Compile(getString(raw), amber.DefaultOptions); err != nil {
|
||||
if html, err = template.Amber(getString(raw), bind); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = tmpl.Execute(&buf, data); err != nil {
|
||||
return err
|
||||
}
|
||||
html = buf.String()
|
||||
|
||||
case "handlebars": // https://github.com/aymerick/raymond
|
||||
if html, err = handlebars.Render(getString(raw), data); err != nil {
|
||||
if html, err = template.Handlebars(getString(raw), bind); err != nil {
|
||||
return err
|
||||
}
|
||||
case "mustache": // https://github.com/cbroglie/mustache
|
||||
if html, err = mustache.Render(getString(raw), data); err != nil {
|
||||
if html, err = template.Mustache(getString(raw), bind); err != nil {
|
||||
return err
|
||||
}
|
||||
case "pug": // https://github.com/Joker/jade
|
||||
var parsed string
|
||||
var buf bytes.Buffer
|
||||
var tmpl *template.Template
|
||||
if parsed, err = pug.Parse("", raw); err != nil {
|
||||
if html, err = template.Pug(getString(raw), bind); err != nil {
|
||||
return err
|
||||
}
|
||||
if tmpl, err = template.New("").Parse(parsed); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = tmpl.Execute(&buf, data); err != nil {
|
||||
return err
|
||||
}
|
||||
html = buf.String()
|
||||
|
||||
default: // https://golang.org/pkg/text/template/
|
||||
var buf bytes.Buffer
|
||||
var tmpl *template.Template
|
||||
|
||||
if tmpl, err = template.New("").Parse(getString(raw)); err != nil {
|
||||
if html, err = template.HTML(getString(raw), bind); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = tmpl.Execute(&buf, data); err != nil {
|
||||
return err
|
||||
}
|
||||
html = buf.String()
|
||||
}
|
||||
ctx.Set("Content-Type", "text/html")
|
||||
ctx.SendString(html)
|
||||
|
@ -740,8 +640,8 @@ func (ctx *Ctx) Route() *Route {
|
|||
}
|
||||
|
||||
// SaveFile : https://fiber.wiki/context#secure
|
||||
func (ctx *Ctx) SaveFile(fh *multipart.FileHeader, path string) error {
|
||||
return fasthttp.SaveMultipartFile(fh, path)
|
||||
func (ctx *Ctx) SaveFile(fileheader *multipart.FileHeader, path string) error {
|
||||
return fasthttp.SaveMultipartFile(fileheader, path)
|
||||
}
|
||||
|
||||
// Secure : https://fiber.wiki/context#secure
|
||||
|
@ -750,18 +650,19 @@ func (ctx *Ctx) Secure() bool {
|
|||
}
|
||||
|
||||
// Send : https://fiber.wiki/context#send
|
||||
func (ctx *Ctx) Send(args ...interface{}) {
|
||||
if len(args) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
switch body := args[0].(type) {
|
||||
case string:
|
||||
ctx.Fasthttp.Response.SetBodyString(body)
|
||||
case []byte:
|
||||
ctx.Fasthttp.Response.SetBodyString(getString(body))
|
||||
default:
|
||||
ctx.Fasthttp.Response.SetBodyString(fmt.Sprintf("%v", body))
|
||||
func (ctx *Ctx) Send(bodies ...interface{}) {
|
||||
// if len(bodies) > 0 {
|
||||
// ctx.Fasthttp.Response.SetBodyString("")
|
||||
// }
|
||||
for i := range bodies {
|
||||
switch body := bodies[i].(type) {
|
||||
case string:
|
||||
ctx.Fasthttp.Response.AppendBodyString(body)
|
||||
case []byte:
|
||||
ctx.Fasthttp.Response.AppendBodyString(getString(body))
|
||||
default:
|
||||
ctx.Fasthttp.Response.AppendBodyString(fmt.Sprintf("%v", body))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -803,19 +704,14 @@ func (ctx *Ctx) Set(key string, val string) {
|
|||
}
|
||||
|
||||
// Subdomains : https://fiber.wiki/context#subdomains
|
||||
func (ctx *Ctx) Subdomains(offset ...int) (subs []string) {
|
||||
func (ctx *Ctx) Subdomains(offset ...int) []string {
|
||||
o := 2
|
||||
if len(offset) > 0 {
|
||||
o = offset[0]
|
||||
}
|
||||
subs = strings.Split(ctx.Hostname(), ".")
|
||||
subs = subs[:len(subs)-o]
|
||||
return subs
|
||||
}
|
||||
|
||||
// SignedCookies : https://fiber.wiki/context#signedcookies
|
||||
func (ctx *Ctx) SignedCookies() {
|
||||
|
||||
subdomains := strings.Split(ctx.Hostname(), ".")
|
||||
subdomains = subdomains[:len(subdomains)-o]
|
||||
return subdomains
|
||||
}
|
||||
|
||||
// Stale : https://fiber.wiki/context#stale
|
||||
|
@ -854,9 +750,9 @@ func (ctx *Ctx) Vary(fields ...string) {
|
|||
}
|
||||
|
||||
// Write : https://fiber.wiki/context#write
|
||||
func (ctx *Ctx) Write(args ...interface{}) {
|
||||
for i := range args {
|
||||
switch body := args[i].(type) {
|
||||
func (ctx *Ctx) Write(bodies ...interface{}) {
|
||||
for i := range bodies {
|
||||
switch body := bodies[i].(type) {
|
||||
case string:
|
||||
ctx.Fasthttp.Response.AppendBodyString(body)
|
||||
case []byte:
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_Accepts(t *testing.T) {
|
||||
|
@ -129,7 +130,6 @@ func Test_BaseURL(t *testing.T) {
|
|||
func Test_Body(t *testing.T) {
|
||||
app := New()
|
||||
app.Post("/test", func(c *Ctx) {
|
||||
c.Body(1)
|
||||
expect := "john=doe"
|
||||
result := c.Body()
|
||||
if result != expect {
|
||||
|
@ -140,21 +140,6 @@ func Test_Body(t *testing.T) {
|
|||
if result != expect {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
|
||||
}
|
||||
expect = "doe"
|
||||
result = c.Body([]byte("john"))
|
||||
if result != expect {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
|
||||
}
|
||||
c.Body(func(k, v string) {
|
||||
expect = "john"
|
||||
if k != "john" {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, k)
|
||||
}
|
||||
expect = "doe"
|
||||
if v != "doe" {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, v)
|
||||
}
|
||||
})
|
||||
})
|
||||
data := url.Values{}
|
||||
data.Set("john", "doe")
|
||||
|
@ -196,7 +181,6 @@ func Test_BodyParser(t *testing.T) {
|
|||
func Test_Cookies(t *testing.T) {
|
||||
app := New()
|
||||
app.Get("/test", func(c *Ctx) {
|
||||
c.Cookies(1)
|
||||
expect := "john=doe"
|
||||
result := c.Cookies()
|
||||
if result != expect {
|
||||
|
@ -207,21 +191,6 @@ func Test_Cookies(t *testing.T) {
|
|||
if result != expect {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
|
||||
}
|
||||
expect = "doe"
|
||||
result = c.Cookies([]byte("john"))
|
||||
if result != expect {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
|
||||
}
|
||||
c.Cookies(func(k, v string) {
|
||||
expect = "john"
|
||||
if k != "john" {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, k)
|
||||
}
|
||||
expect = "doe"
|
||||
if v != "doe" {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, v)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
req, _ := http.NewRequest("GET", "/test", nil)
|
||||
|
@ -621,20 +590,6 @@ func Test_Secure(t *testing.T) {
|
|||
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
|
||||
}
|
||||
}
|
||||
func Test_SignedCookies(t *testing.T) {
|
||||
app := New()
|
||||
app.Get("/test", func(c *Ctx) {
|
||||
c.SignedCookies()
|
||||
})
|
||||
req, _ := http.NewRequest("GET", "/test", nil)
|
||||
resp, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf(`%s: %s`, t.Name(), err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
|
||||
}
|
||||
}
|
||||
func Test_Stale(t *testing.T) {
|
||||
app := New()
|
||||
app.Get("/test", func(c *Ctx) {
|
||||
|
@ -758,16 +713,16 @@ func Test_ClearCookie(t *testing.T) {
|
|||
}
|
||||
func Test_Cookie(t *testing.T) {
|
||||
app := New()
|
||||
expire := time.Now().Add(24 * time.Hour)
|
||||
var dst []byte
|
||||
dst = expire.In(time.UTC).AppendFormat(dst, time.RFC1123)
|
||||
httpdate := strings.Replace(string(dst), "UTC", "GMT", -1)
|
||||
app.Get("/test", func(c *Ctx) {
|
||||
options := &Cookie{
|
||||
MaxAge: 60,
|
||||
Domain: "example.com",
|
||||
Path: "/",
|
||||
HTTPOnly: true,
|
||||
Secure: false,
|
||||
SameSite: "lax",
|
||||
}
|
||||
c.Cookie("name", "john", options)
|
||||
cookie := new(Cookie)
|
||||
cookie.Name = "username"
|
||||
cookie.Value = "jon"
|
||||
cookie.Expires = expire
|
||||
c.Cookie(cookie)
|
||||
})
|
||||
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
|
||||
resp, err := app.Test(req)
|
||||
|
@ -777,8 +732,8 @@ func Test_Cookie(t *testing.T) {
|
|||
if resp.StatusCode != 200 {
|
||||
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
|
||||
}
|
||||
if !strings.Contains(resp.Header.Get("Set-Cookie"), "name=john; max-age=60; domain=example.com; path=/; HttpOnly; SameSite=Lax") {
|
||||
t.Fatalf(`%s: Expecting %s`, t.Name(), "name=john; max-age=60; domain=example.com; path=/; HttpOnly; SameSite=Lax")
|
||||
if !strings.Contains(resp.Header.Get("Set-Cookie"), "username=jon; expires="+string(httpdate)+"; path=/") {
|
||||
t.Fatalf(`%s: Expecting %s`, t.Name(), "username=jon; expires="+string(httpdate)+"; path=/")
|
||||
}
|
||||
}
|
||||
func Test_Download(t *testing.T) {
|
||||
|
|
3
go.mod
3
go.mod
|
@ -3,8 +3,9 @@ module github.com/gofiber/fiber
|
|||
go 1.11
|
||||
|
||||
require (
|
||||
github.com/fasthttp/websocket v1.4.1
|
||||
github.com/gorilla/schema v1.1.0
|
||||
github.com/gofiber/template v1.0.0
|
||||
github.com/json-iterator/go v1.1.9
|
||||
github.com/valyala/fasthttp v1.9.0
|
||||
github.com/fasthttp/websocket v1.4.2
|
||||
)
|
||||
|
|
15
go.sum
15
go.sum
|
@ -1,7 +1,6 @@
|
|||
github.com/Joker/hpp v0.0.0-20180418125244-6893e659854a/go.mod h1:MzD2WMdSxvbHw5fM/OXOFily/lipJWRc9C1px0Mt0ZE=
|
||||
github.com/Joker/jade v1.0.0 h1:lOCEPvTAtWfLpSZYMOv/g44MGQFAolbKh2khHHGu0Kc=
|
||||
github.com/Joker/jade v1.0.0/go.mod h1:efZIdO0py/LtcJRSa/j2WEklMSAw84WV0zZVMxNToB8=
|
||||
github.com/aymerick/raymond v1.1.0 h1:phuNN2s67eI/HtO8CrvqFcdR2JP+BtkGJZ9n692Hr2Y=
|
||||
github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0=
|
||||
github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||
github.com/cbroglie/mustache v1.0.1 h1:ivMg8MguXq/rrz2eu3tw6g3b16+PQhoTn6EZAhst2mw=
|
||||
|
@ -10,17 +9,17 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/fasthttp/websocket v1.4.1 h1:fisgNMCNCbIPM5GRRRTAckRrynbSzf76fevcJYJYnSM=
|
||||
github.com/fasthttp/websocket v1.4.1/go.mod h1:toetUvZ3KISxtZERe0wzPPpnaN8GZCKHCowWctwA50o=
|
||||
github.com/fasthttp/websocket v1.4.2 h1:AU/zSiIIAuJjBMf5o+vO0syGOnEfvZRu40xIhW/3RuM=
|
||||
github.com/fasthttp/websocket v1.4.2/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y=
|
||||
github.com/gofiber/template v1.0.0 h1:Vf4Fby9zUWVQyY2y69KKyRHsEYlIE+Pxb25M+jiaEL0=
|
||||
github.com/gofiber/template v1.0.0/go.mod h1:+bij+R0NI6urTg2jtQvPj5wb2uWMxW9eYGsAN3QhnP0=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
|
||||
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs=
|
||||
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
|
@ -28,18 +27,16 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
|||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/savsgio/gotils v0.0.0-20190714152828-365999d0a274 h1:F52t1X2ziOrMcQMVHo8ZxwOrDTMAq6MrlKtL1Atu2wU=
|
||||
github.com/savsgio/gotils v0.0.0-20190714152828-365999d0a274/go.mod h1:w803/Fg1m0hrp1ZT9KNfQe4E4+WOMMFLcgzPvOcye10=
|
||||
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY=
|
||||
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.4.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
||||
github.com/valyala/fasthttp v1.9.0 h1:hNpmUdy/+ZXYpGy0OBfm7K0UQTzb73W0T0U4iJIVrMw=
|
||||
github.com/valyala/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
83
group.go
83
group.go
|
@ -4,7 +4,10 @@
|
|||
|
||||
package fiber
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Group ...
|
||||
type Group struct {
|
||||
|
@ -12,10 +15,10 @@ type Group struct {
|
|||
app *App
|
||||
}
|
||||
|
||||
// Group ...
|
||||
func (app *App) Group(prefix string, args ...interface{}) *Group {
|
||||
if len(args) > 0 {
|
||||
app.register("USE", prefix, args...)
|
||||
// Group : https://fiber.wiki/application#group
|
||||
func (app *App) Group(prefix string, handlers ...interface{}) *Group {
|
||||
if len(handlers) > 0 {
|
||||
app.register("USE", prefix, handlers...)
|
||||
}
|
||||
return &Group{
|
||||
prefix: prefix,
|
||||
|
@ -23,102 +26,102 @@ func (app *App) Group(prefix string, args ...interface{}) *Group {
|
|||
}
|
||||
}
|
||||
|
||||
// Group ...
|
||||
func (grp *Group) Group(newPrfx string, args ...interface{}) *Group {
|
||||
var prefix = grp.prefix
|
||||
if len(newPrfx) > 0 && newPrfx[0] != '/' && newPrfx[0] != '*' {
|
||||
newPrfx = "/" + newPrfx
|
||||
// Group : https://fiber.wiki/application#group
|
||||
func (grp *Group) Group(prefix string, handlers ...interface{}) *Group {
|
||||
var oldPrefix = grp.prefix
|
||||
if len(prefix) > 0 && prefix[0] != '/' && prefix[0] != '*' {
|
||||
prefix = "/" + prefix
|
||||
}
|
||||
// When grouping, always remove single slash
|
||||
if len(prefix) > 0 && newPrfx == "/" {
|
||||
newPrfx = ""
|
||||
if len(oldPrefix) > 0 && prefix == "/" {
|
||||
prefix = ""
|
||||
}
|
||||
// Prepent group prefix if exist
|
||||
prefix = prefix + newPrfx
|
||||
newPrefix := oldPrefix + prefix
|
||||
// Clean path by removing double "//" => "/"
|
||||
prefix = strings.Replace(prefix, "//", "/", -1)
|
||||
if len(args) > 0 {
|
||||
grp.app.register("USE", prefix, args...)
|
||||
newPrefix = strings.Replace(newPrefix, "//", "/", -1)
|
||||
if len(handlers) > 0 {
|
||||
grp.app.register("USE", newPrefix, handlers...)
|
||||
}
|
||||
return &Group{
|
||||
prefix: prefix,
|
||||
prefix: newPrefix,
|
||||
app: grp.app,
|
||||
}
|
||||
}
|
||||
|
||||
// Static ...
|
||||
// Static : https://fiber.wiki/application#static
|
||||
func (grp *Group) Static(args ...string) *Group {
|
||||
grp.app.registerStatic(grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// WebSocket ...
|
||||
// WebSocket : https://fiber.wiki/application#websocket
|
||||
func (grp *Group) WebSocket(args ...interface{}) *Group {
|
||||
grp.app.register("GET", grp.prefix, args...)
|
||||
grp.app.register(http.MethodGet, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Connect ...
|
||||
// Connect : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Connect(args ...interface{}) *Group {
|
||||
grp.app.register("CONNECT", grp.prefix, args...)
|
||||
grp.app.register(http.MethodConnect, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Put ...
|
||||
// Put : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Put(args ...interface{}) *Group {
|
||||
grp.app.register("PUT", grp.prefix, args...)
|
||||
grp.app.register(http.MethodPut, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Post ...
|
||||
// Post : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Post(args ...interface{}) *Group {
|
||||
grp.app.register("POST", grp.prefix, args...)
|
||||
grp.app.register(http.MethodPost, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
// Delete : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Delete(args ...interface{}) *Group {
|
||||
grp.app.register("DELETE", grp.prefix, args...)
|
||||
grp.app.register(http.MethodDelete, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Head ...
|
||||
// Head : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Head(args ...interface{}) *Group {
|
||||
grp.app.register("HEAD", grp.prefix, args...)
|
||||
grp.app.register(http.MethodHead, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Patch ...
|
||||
// Patch : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Patch(args ...interface{}) *Group {
|
||||
grp.app.register("PATCH", grp.prefix, args...)
|
||||
grp.app.register(http.MethodPatch, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Options ...
|
||||
// Options : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Options(args ...interface{}) *Group {
|
||||
grp.app.register("OPTIONS", grp.prefix, args...)
|
||||
grp.app.register(http.MethodOptions, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Trace ...
|
||||
// Trace : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Trace(args ...interface{}) *Group {
|
||||
grp.app.register("TRACE", grp.prefix, args...)
|
||||
grp.app.register(http.MethodTrace, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Get ...
|
||||
// Get : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Get(args ...interface{}) *Group {
|
||||
grp.app.register("GET", grp.prefix, args...)
|
||||
grp.app.register(http.MethodGet, grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// All ...
|
||||
// All : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) All(args ...interface{}) *Group {
|
||||
grp.app.register("ALL", grp.prefix, args...)
|
||||
return grp
|
||||
}
|
||||
|
||||
// Use ...
|
||||
// Use : https://fiber.wiki/application#http-methods
|
||||
func (grp *Group) Use(args ...interface{}) *Group {
|
||||
grp.app.register("USE", grp.prefix, args...)
|
||||
return grp
|
||||
|
|
|
@ -278,7 +278,11 @@ func (app *App) handler(fctx *fasthttp.RequestCtx) {
|
|||
if app.recover != nil {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ctx.error = fmt.Errorf("panic: %v", r)
|
||||
err, ok := r.(error)
|
||||
if !ok {
|
||||
err = fmt.Errorf("%v", r)
|
||||
}
|
||||
ctx.error = err
|
||||
app.recover(ctx)
|
||||
}
|
||||
}()
|
||||
|
|
34
utils.go
34
utils.go
|
@ -29,21 +29,6 @@ var socketUpgrade = websocket.FastHTTPUpgrader{
|
|||
},
|
||||
}
|
||||
|
||||
// MIME types
|
||||
const (
|
||||
MIMEApplicationJSON = "application/json"
|
||||
MIMEApplicationJavaScript = "application/javascript"
|
||||
MIMEApplicationXML = "application/xml"
|
||||
MIMETextXML = "text/xml"
|
||||
MIMEApplicationForm = "application/x-www-form-urlencoded"
|
||||
MIMEApplicationProtobuf = "application/protobuf"
|
||||
MIMEApplicationMsgpack = "application/msgpack"
|
||||
MIMETextHTML = "text/html"
|
||||
MIMETextPlain = "text/plain"
|
||||
MIMEMultipartForm = "multipart/form-data"
|
||||
MIMEOctetStream = "application/octet-stream"
|
||||
)
|
||||
|
||||
func getParams(path string) (params []string) {
|
||||
if len(path) < 1 {
|
||||
return
|
||||
|
@ -125,7 +110,7 @@ func getStatus(status int) (msg string) {
|
|||
// #nosec G103
|
||||
// getString converts byte slice to a string without memory allocation.
|
||||
// See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
|
||||
func getString(b []byte) string {
|
||||
var getString = func(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
|
@ -157,6 +142,21 @@ func (c *testConn) SetDeadline(t time.Time) error { return nil }
|
|||
func (c *testConn) SetReadDeadline(t time.Time) error { return nil }
|
||||
func (c *testConn) SetWriteDeadline(t time.Time) error { return nil }
|
||||
|
||||
// MIME types
|
||||
const (
|
||||
MIMEApplicationJSON = "application/json"
|
||||
MIMEApplicationJavaScript = "application/javascript"
|
||||
MIMEApplicationXML = "application/xml"
|
||||
MIMETextXML = "text/xml"
|
||||
MIMEApplicationForm = "application/x-www-form-urlencoded"
|
||||
MIMEApplicationProtobuf = "application/protobuf"
|
||||
MIMEApplicationMsgpack = "application/msgpack"
|
||||
MIMETextHTML = "text/html"
|
||||
MIMETextPlain = "text/plain"
|
||||
MIMEMultipartForm = "multipart/form-data"
|
||||
MIMEOctetStream = "application/octet-stream"
|
||||
)
|
||||
|
||||
// HTTP status codes
|
||||
var statusMessage = map[int]string{
|
||||
100: "Continue",
|
||||
|
@ -221,7 +221,7 @@ var statusMessage = map[int]string{
|
|||
511: "Network Authentication Required",
|
||||
}
|
||||
|
||||
// MIME types for file extensions
|
||||
// File extensions MIME types
|
||||
var extensionMIME = map[string]string{
|
||||
"html": "text/html",
|
||||
"htm": "text/html",
|
||||
|
|
Loading…
Reference in New Issue