From 2eeb40273c463820bb155622961cbbccac9b801a Mon Sep 17 00:00:00 2001 From: Fenny Date: Wed, 26 Feb 2020 19:31:43 -0500 Subject: [PATCH] v1.8.0 --- app.go | 122 +++++++++------- context.go | 368 +++++++++++++++++------------------------------- context_test.go | 69 ++------- go.mod | 3 +- go.sum | 15 +- group.go | 83 +++++------ router.go | 6 +- utils.go | 34 ++--- 8 files changed, 287 insertions(+), 413 deletions(-) diff --git a/app.go b/app.go index 2f858f53..3a5f1484 100644 --- a/app.go +++ b/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 diff --git a/context.go b/context.go index 5b03c02d..af9531b1 100644 --- a/context.go +++ b/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("

" + body + "

") - 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("

" + b + "

") + 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: diff --git a/context_test.go b/context_test.go index 616fa594..be026e64 100644 --- a/context_test.go +++ b/context_test.go @@ -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) { diff --git a/go.mod b/go.mod index f64820a7..e4cc4b33 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index 9822852a..ae4af774 100644 --- a/go.sum +++ b/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= diff --git a/group.go b/group.go index d6b86f32..0ebfb16b 100644 --- a/group.go +++ b/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 diff --git a/router.go b/router.go index 273c31ad..d1e06489 100644 --- a/router.go +++ b/router.go @@ -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) } }() diff --git a/utils.go b/utils.go index 595b09c1..4d8a641b 100644 --- a/utils.go +++ b/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",