mirror of https://github.com/gofiber/fiber.git
Merge remote-tracking branch 'upstream/master'
commit
9125080df2
50
app_test.go
50
app_test.go
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -132,7 +133,9 @@ func Test_App_ServerErrorHandler_SmallReadBuffer(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_App_ErrorHandler(t *testing.T) {
|
||||
app := New()
|
||||
app := New(&Settings{
|
||||
BodyLimit: 4,
|
||||
})
|
||||
|
||||
app.Get("/", func(c *Ctx) {
|
||||
c.Next(errors.New("hi, i'm an error"))
|
||||
|
@ -146,6 +149,10 @@ func Test_App_ErrorHandler(t *testing.T) {
|
|||
utils.AssertEqual(t, nil, err)
|
||||
utils.AssertEqual(t, "hi, i'm an error", string(body))
|
||||
|
||||
_, err = app.Test(httptest.NewRequest("GET", "/", strings.NewReader("big body")))
|
||||
if err != nil {
|
||||
utils.AssertEqual(t, "body size exceeds the given limit", err.Error(), "app.Test(req)")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_App_ErrorHandler_Custom(t *testing.T) {
|
||||
|
@ -655,26 +662,28 @@ func Test_App_Listen(t *testing.T) {
|
|||
app := New(&Settings{
|
||||
DisableStartupMessage: true,
|
||||
})
|
||||
go func() {
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
utils.AssertEqual(t, nil, app.Shutdown())
|
||||
}()
|
||||
|
||||
utils.AssertEqual(t, nil, app.Listen("127.0.0.1:"))
|
||||
utils.AssertEqual(t, false, app.Listen(1.23) == nil)
|
||||
|
||||
go func() {
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
utils.AssertEqual(t, nil, app.Shutdown())
|
||||
}()
|
||||
|
||||
utils.AssertEqual(t, nil, app.Listen("127.0.0.1:"))
|
||||
utils.AssertEqual(t, nil, app.Listen(4003))
|
||||
|
||||
go func() {
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
utils.AssertEqual(t, nil, app.Shutdown())
|
||||
}()
|
||||
|
||||
utils.AssertEqual(t, nil, app.Listen("4010"))
|
||||
}
|
||||
|
||||
// go test -run Test_App_Listener
|
||||
func Test_App_Listener(t *testing.T) {
|
||||
app := New(&Settings{
|
||||
DisableStartupMessage: true,
|
||||
Prefork: true,
|
||||
Prefork: true,
|
||||
})
|
||||
|
||||
go func() {
|
||||
|
@ -716,3 +725,26 @@ func Test_NewError(t *testing.T) {
|
|||
utils.AssertEqual(t, StatusForbidden, e.Code)
|
||||
utils.AssertEqual(t, "permission denied", e.Message)
|
||||
}
|
||||
|
||||
func Test_Test_Timeout(t *testing.T) {
|
||||
app := New()
|
||||
app.Settings.DisableStartupMessage = true
|
||||
|
||||
app.Get("/", func(_ *Ctx) {})
|
||||
|
||||
resp, err := app.Test(httptest.NewRequest("GET", "/", nil), -1)
|
||||
utils.AssertEqual(t, nil, err, "app.Test(req)")
|
||||
utils.AssertEqual(t, 200, resp.StatusCode, "Status code")
|
||||
|
||||
app.Get("timeout", func(c *Ctx) {
|
||||
time.Sleep(55 * time.Millisecond)
|
||||
})
|
||||
|
||||
_, err = app.Test(httptest.NewRequest("GET", "/timeout", nil), 50)
|
||||
utils.AssertEqual(t, true, err != nil, "app.Test(req)")
|
||||
}
|
||||
|
||||
func Test_App_Handler(t *testing.T) {
|
||||
h := New().Handler()
|
||||
utils.AssertEqual(t, "fasthttp.RequestHandler", reflect.TypeOf(h).String())
|
||||
}
|
||||
|
|
38
ctx.go
38
ctx.go
|
@ -222,47 +222,45 @@ func (ctx *Ctx) Body() string {
|
|||
// application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data
|
||||
func (ctx *Ctx) BodyParser(out interface{}) error {
|
||||
// TODO: Create benchmark ( Probably need a sync pool )
|
||||
var schemaDecoderForm = schema.NewDecoder()
|
||||
var schemaDecoderQuery = schema.NewDecoder()
|
||||
schemaDecoderForm.SetAliasTag("form")
|
||||
schemaDecoderForm.IgnoreUnknownKeys(true)
|
||||
schemaDecoderQuery.SetAliasTag("query")
|
||||
schemaDecoderQuery.IgnoreUnknownKeys(true)
|
||||
var (
|
||||
schemaDecoder = schema.NewDecoder()
|
||||
ctype = getString(ctx.Fasthttp.Request.Header.ContentType())
|
||||
)
|
||||
schemaDecoder.IgnoreUnknownKeys(true)
|
||||
|
||||
// get content type
|
||||
ctype := getString(ctx.Fasthttp.Request.Header.ContentType())
|
||||
// application/json
|
||||
if strings.HasPrefix(ctype, MIMEApplicationJSON) {
|
||||
switch ctype {
|
||||
case MIMEApplicationJSON, MIMEApplicationJSONCharsetUTF8:
|
||||
return json.Unmarshal(ctx.Fasthttp.Request.Body(), out)
|
||||
}
|
||||
// application/xml text/xml
|
||||
if strings.HasPrefix(ctype, MIMEApplicationXML) || strings.HasPrefix(ctype, MIMETextXML) {
|
||||
case MIMETextXML, MIMETextXMLCharsetUTF8, MIMEApplicationXML, MIMEApplicationXMLCharsetUTF8:
|
||||
return xml.Unmarshal(ctx.Fasthttp.Request.Body(), out)
|
||||
}
|
||||
// application/x-www-form-urlencoded
|
||||
if strings.HasPrefix(ctype, MIMEApplicationForm) {
|
||||
case MIMEApplicationForm: // application/x-www-form-urlencoded
|
||||
schemaDecoder.SetAliasTag("form")
|
||||
data, err := url.ParseQuery(getString(ctx.Fasthttp.PostBody()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return schemaDecoderForm.Decode(out, data)
|
||||
return schemaDecoder.Decode(out, data)
|
||||
}
|
||||
// multipart/form-data
|
||||
|
||||
// this case is outside switch case because it can have info additional as `boundary=something` in content-type
|
||||
if strings.HasPrefix(ctype, MIMEMultipartForm) {
|
||||
schemaDecoder.SetAliasTag("form")
|
||||
data, err := ctx.Fasthttp.MultipartForm()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return schemaDecoderForm.Decode(out, data.Value)
|
||||
return schemaDecoder.Decode(out, data.Value)
|
||||
}
|
||||
|
||||
// query params
|
||||
if ctx.Fasthttp.QueryArgs().Len() > 0 {
|
||||
schemaDecoder.SetAliasTag("query")
|
||||
fmt.Println("Parsing query strings using `BodyParser` is deprecated since v1.12.7, please us `ctx.QueryParser` instead")
|
||||
data := make(map[string][]string)
|
||||
ctx.Fasthttp.QueryArgs().VisitAll(func(key []byte, val []byte) {
|
||||
data[getString(key)] = append(data[getString(key)], getString(val))
|
||||
})
|
||||
return schemaDecoderQuery.Decode(out, data)
|
||||
return schemaDecoder.Decode(out, data)
|
||||
}
|
||||
|
||||
return fmt.Errorf("bodyparser: cannot parse content-type: %v", ctype)
|
||||
|
|
24
prefork.go
24
prefork.go
|
@ -19,6 +19,8 @@ const (
|
|||
envPreforkChildVal = "1"
|
||||
)
|
||||
|
||||
var testPreforkMaster = false
|
||||
|
||||
// IsChild determines if the current process is a result of Prefork
|
||||
func (app *App) IsChild() bool {
|
||||
return os.Getenv(envPreforkChildKey) == envPreforkChildVal
|
||||
|
@ -45,11 +47,12 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) {
|
|||
|
||||
// kill child proc when master exits
|
||||
go func() {
|
||||
ppid, err := os.FindProcess(os.Getppid())
|
||||
p, err := os.FindProcess(os.Getppid())
|
||||
if err == nil {
|
||||
_, _ = ppid.Wait()
|
||||
_, _ = p.Wait()
|
||||
} else {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(1)
|
||||
}()
|
||||
// listen for incoming connections
|
||||
return app.server.Serve(ln)
|
||||
|
@ -73,12 +76,18 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) {
|
|||
}()
|
||||
|
||||
// collect child pids
|
||||
pids := []string{}
|
||||
var pids []string
|
||||
|
||||
// launch child procs
|
||||
for i := 0; i < max; i++ {
|
||||
/* #nosec G204 */
|
||||
cmd := exec.Command(os.Args[0], os.Args[1:]...)
|
||||
if testPreforkMaster {
|
||||
// When test prefork master,
|
||||
// just start the child process
|
||||
// a cmd on all os is best
|
||||
cmd = exec.Command("date")
|
||||
}
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
|
@ -91,12 +100,13 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) {
|
|||
}
|
||||
|
||||
// store child process
|
||||
childs[cmd.Process.Pid] = cmd
|
||||
pids = append(pids, strconv.Itoa(cmd.Process.Pid))
|
||||
pid := cmd.Process.Pid
|
||||
childs[pid] = cmd
|
||||
pids = append(pids, strconv.Itoa(pid))
|
||||
|
||||
// notify master if child crashes
|
||||
go func() {
|
||||
channel <- child{cmd.Process.Pid, cmd.Wait()}
|
||||
channel <- child{pid, cmd.Wait()}
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package fiber
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
utils "github.com/gofiber/utils"
|
||||
)
|
||||
|
||||
func Test_App_Prefork_Child_Process(t *testing.T) {
|
||||
utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal))
|
||||
defer os.Setenv(envPreforkChildKey, "")
|
||||
|
||||
app := New(&Settings{
|
||||
DisableStartupMessage: true,
|
||||
})
|
||||
app.init()
|
||||
|
||||
go func() {
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
utils.AssertEqual(t, nil, app.Shutdown())
|
||||
}()
|
||||
|
||||
utils.AssertEqual(t, nil, app.prefork("127.0.0.1:"))
|
||||
}
|
||||
|
||||
func Test_App_Prefork_Main_Process(t *testing.T) {
|
||||
testPreforkMaster = true
|
||||
|
||||
app := New(&Settings{
|
||||
DisableStartupMessage: true,
|
||||
})
|
||||
app.init()
|
||||
|
||||
go func() {
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
utils.AssertEqual(t, nil, app.Shutdown())
|
||||
}()
|
||||
|
||||
utils.AssertEqual(t, nil, app.prefork("127.0.0.1:"))
|
||||
}
|
|
@ -214,6 +214,21 @@ func Test_Ensure_Router_Interface_Implementation(t *testing.T) {
|
|||
utils.AssertEqual(t, true, ok)
|
||||
}
|
||||
|
||||
func Test_Router_Handler_SetETag(t *testing.T) {
|
||||
app := New()
|
||||
app.Settings.ETag = true
|
||||
|
||||
app.Get("/", func(c *Ctx) {
|
||||
c.Send("Hello, World!")
|
||||
})
|
||||
|
||||
c := &fasthttp.RequestCtx{}
|
||||
|
||||
app.handler(c)
|
||||
|
||||
utils.AssertEqual(t, `"13-1831710635"`, string(c.Response.Header.Peek(HeaderETag)))
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
///////////////// BENCHMARKS /////////////////
|
||||
//////////////////////////////////////////////
|
||||
|
|
1
utils.go
1
utils.go
|
@ -312,6 +312,7 @@ const (
|
|||
MIMETextHTMLCharsetUTF8 = "text/html; charset=utf-8"
|
||||
MIMETextPlainCharsetUTF8 = "text/plain; charset=utf-8"
|
||||
MIMEApplicationXMLCharsetUTF8 = "application/xml; charset=utf-8"
|
||||
MIMEApplicationJSONCharsetUTF8 = "application/json; charset=utf-8"
|
||||
MIMEApplicationJavaScriptCharsetUTF8 = "application/javascript; charset=utf-8"
|
||||
)
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ package fiber
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
utils "github.com/gofiber/utils"
|
||||
fasthttp "github.com/valyala/fasthttp"
|
||||
|
@ -150,3 +151,61 @@ func Benchmark_Utils_Unescape(b *testing.B) {
|
|||
|
||||
utils.AssertEqual(b, "/créer", unescaped)
|
||||
}
|
||||
|
||||
func Test_Utils_IPv6(t *testing.T) {
|
||||
testCases := []struct {
|
||||
string
|
||||
bool
|
||||
}{
|
||||
{"::FFFF:C0A8:1:3000", true},
|
||||
{"::FFFF:C0A8:0001:3000", true},
|
||||
{"0000:0000:0000:0000:0000:FFFF:C0A8:1:3000", true},
|
||||
{"::FFFF:C0A8:1%1:3000", true},
|
||||
{"::FFFF:192.168.0.1:3000", true},
|
||||
{"[::FFFF:C0A8:1]:3000", true},
|
||||
{"[::FFFF:C0A8:1%1]:3000", true},
|
||||
{":3000", false},
|
||||
{"127.0.0.1:3000", false},
|
||||
{"127.0.0.1:", false},
|
||||
{"0.0.0.0:3000", false},
|
||||
{"", false},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
utils.AssertEqual(t, c.bool, isIPv6(c.string))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Utils_Parse_Address(t *testing.T) {
|
||||
testCases := []struct {
|
||||
addr, host, port string
|
||||
}{
|
||||
{"[::]:3000", "[::]", "3000"},
|
||||
{"127.0.0.1:3000", "127.0.0.1", "3000"},
|
||||
{"/path/to/unix/socket", "/path/to/unix/socket", ""},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
host, port := parseAddr(c.addr)
|
||||
utils.AssertEqual(t, c.host, host, "addr host")
|
||||
utils.AssertEqual(t, c.port, port, "addr port")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Utils_GetOffset(t *testing.T) {
|
||||
utils.AssertEqual(t, "", getOffer("hello"))
|
||||
utils.AssertEqual(t, "1", getOffer("", "1"))
|
||||
utils.AssertEqual(t, "", getOffer("2", "1"))
|
||||
}
|
||||
|
||||
func Test_Utils_TestAddr_Network(t *testing.T) {
|
||||
var addr testAddr = "addr"
|
||||
utils.AssertEqual(t, "addr", addr.Network())
|
||||
}
|
||||
|
||||
func Test_Utils_TestConn_Deadline(t *testing.T) {
|
||||
conn := &testConn{}
|
||||
utils.AssertEqual(t, nil, conn.SetDeadline(time.Time{}))
|
||||
utils.AssertEqual(t, nil, conn.SetReadDeadline(time.Time{}))
|
||||
utils.AssertEqual(t, nil, conn.SetWriteDeadline(time.Time{}))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue