From 30a704b5f94fd8746cea60982fb7b395d9a82371 Mon Sep 17 00:00:00 2001 From: kiyon Date: Thu, 16 Jul 2020 16:42:36 +0800 Subject: [PATCH 01/36] =?UTF-8?q?=20=F0=9F=91=B7=20improve=20test=20covera?= =?UTF-8?q?ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app_test.go | 30 ++++++++++++++++++++++++++++++ ctx_test.go | 3 +++ prefork.go | 11 +++-------- prefork_dummy.go | 13 +++++++++++++ prefork_dummy_windows.go | 11 +++++++++++ prefork_test.go | 37 +++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 8 deletions(-) create mode 100644 prefork_dummy.go create mode 100644 prefork_dummy_windows.go diff --git a/app_test.go b/app_test.go index c7cd748e..c59d1fef 100644 --- a/app_test.go +++ b/app_test.go @@ -8,6 +8,7 @@ import ( "crypto/tls" "errors" "fmt" + "io" "io/ioutil" "net" "net/http/httptest" @@ -627,6 +628,15 @@ func Test_App_Mixed_Routes_WithSameLen(t *testing.T) { utils.AssertEqual(t, true, strings.HasPrefix(string(body), ""), "Response: "+string(body)) } +func Test_App_Group_Invalid(t *testing.T) { + defer func() { + if err := recover(); err != nil { + utils.AssertEqual(t, "use: invalid handler int\n", fmt.Sprintf("%v", err)) + } + }() + New().Group("/").Use(1) +} + func Test_App_Group(t *testing.T) { var dummyHandler = func(c *Ctx) {} @@ -725,6 +735,8 @@ func Test_App_Listen(t *testing.T) { utils.AssertEqual(t, false, app.Listen(1.23) == nil) + utils.AssertEqual(t, false, app.Listen(":1.23") == nil) + go func() { time.Sleep(1000 * time.Millisecond) utils.AssertEqual(t, nil, app.Shutdown()) @@ -808,3 +820,21 @@ func Test_App_Handler(t *testing.T) { h := New().Handler() utils.AssertEqual(t, "fasthttp.RequestHandler", reflect.TypeOf(h).String()) } + +type invalidView struct{} + +func (invalidView) Load() error { return errors.New("invalid view") } + +func (i invalidView) Render(io.Writer, string, interface{}, ...string) error { panic("implement me") } + +func Test_App_Init_Error_View(t *testing.T) { + app := New(&Settings{Views: invalidView{}}) + app.init() + + defer func() { + if err := recover(); err != nil { + utils.AssertEqual(t, "implement me", fmt.Sprintf("%v", err)) + } + }() + _ = app.Settings.Views.Render(nil, "", nil) +} diff --git a/ctx_test.go b/ctx_test.go index 1ce82c31..5b871816 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -1416,6 +1416,9 @@ func Test_Ctx_Render(t *testing.T) { }) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(ctx.Fasthttp.Response.Body())) + + err = ctx.Render("./.github/TEST_DATA/invalid.html", nil) + utils.AssertEqual(t, false, err == nil) } type testTemplateEngine struct { diff --git a/prefork.go b/prefork.go index c5afa5b8..cf4bb1c9 100644 --- a/prefork.go +++ b/prefork.go @@ -21,7 +21,6 @@ const ( var ( testPreforkMaster = false - dummyChildCmd = "go" ) // IsChild determines if the current process is a result of Prefork @@ -87,13 +86,9 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { 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 - if runtime.GOOS == "windows" { - cmd = exec.Command("cmd", "/C", dummyChildCmd, "version") - } else { - cmd = exec.Command(dummyChildCmd, "version") - } + // just start the child process with a dummy cmd, + // which will exit soon + cmd = dummyCmd() } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/prefork_dummy.go b/prefork_dummy.go new file mode 100644 index 00000000..afaaac4e --- /dev/null +++ b/prefork_dummy.go @@ -0,0 +1,13 @@ +// +build !windows + +package fiber + +import ( + "os/exec" +) + +var dummyChildCmd = "go" + +func dummyCmd() *exec.Cmd { + return exec.Command(dummyChildCmd, "version") +} diff --git a/prefork_dummy_windows.go b/prefork_dummy_windows.go new file mode 100644 index 00000000..6a13bb60 --- /dev/null +++ b/prefork_dummy_windows.go @@ -0,0 +1,11 @@ +package fiber + +import ( + "os/exec" +) + +var dummyChildCmd = "go" + +func dummyCmd() *exec.Cmd { + return exec.Command("cmd", "/C", dummyChildCmd, "version") +} diff --git a/prefork_test.go b/prefork_test.go index a904482b..02abf4a3 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -1,6 +1,8 @@ package fiber import ( + "crypto/tls" + "io/ioutil" "os" "testing" "time" @@ -24,6 +26,20 @@ func Test_App_Prefork_Child_Process(t *testing.T) { }() utils.AssertEqual(t, nil, app.prefork("127.0.0.1:")) + + // Create tls certificate + cer, err := tls.LoadX509KeyPair("./.github/TEST_DATA/ssl.pem", "./.github/TEST_DATA/ssl.key") + if err != nil { + utils.AssertEqual(t, nil, err) + } + config := &tls.Config{Certificates: []tls.Certificate{cer}} + + go func() { + time.Sleep(1000 * time.Millisecond) + utils.AssertEqual(t, nil, app.Shutdown()) + }() + + utils.AssertEqual(t, nil, app.prefork("127.0.0.1:", config)) } func Test_App_Prefork_Main_Process(t *testing.T) { @@ -57,3 +73,24 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { app.init() utils.AssertEqual(t, "listen: tcp6 is not supported when prefork is enabled", app.Listen(":3000").Error()) } + +func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { + utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) + defer os.Setenv(envPreforkChildKey, "") + + rescueStdout := os.Stdout + defer func() { os.Stdout = rescueStdout }() + + r, w, err := os.Pipe() + utils.AssertEqual(t, nil, err) + + os.Stdout = w + + New().startupMessage(":3000", false, "") + + utils.AssertEqual(t, nil, w.Close()) + + out, err := ioutil.ReadAll(r) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 0, len(out)) +} From 227c751abce707766286093884868b1b63288ff3 Mon Sep 17 00:00:00 2001 From: kiyon Date: Fri, 17 Jul 2020 06:51:57 +0800 Subject: [PATCH 02/36] =?UTF-8?q?=F0=9F=8C=BC=20separate=20different=20log?= =?UTF-8?q?ic=20on=20each=20OS=20for=20child=20process=20to=20watch=20if?= =?UTF-8?q?=20master=20process=20exits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork.go | 12 +++--------- prefork_dummy.go | 13 ------------- prefork_dummy_windows.go | 11 ----------- prefork_test.go | 2 +- prefork_utils.go | 28 ++++++++++++++++++++++++++++ prefork_utils_windows.go | 22 ++++++++++++++++++++++ 6 files changed, 54 insertions(+), 34 deletions(-) delete mode 100644 prefork_dummy.go delete mode 100644 prefork_dummy_windows.go create mode 100644 prefork_utils.go create mode 100644 prefork_utils_windows.go diff --git a/prefork.go b/prefork.go index cf4bb1c9..5a62a006 100644 --- a/prefork.go +++ b/prefork.go @@ -47,15 +47,9 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { ln = tls.NewListener(ln, tlsconfig[0]) } - // kill child proc when master exits - go func() { - p, err := os.FindProcess(os.Getppid()) - if err == nil { - _, _ = p.Wait() - } else { - os.Exit(1) - } - }() + // kill current child proc when master exits + go watchMaster() + // listen for incoming connections return app.server.Serve(ln) } diff --git a/prefork_dummy.go b/prefork_dummy.go deleted file mode 100644 index afaaac4e..00000000 --- a/prefork_dummy.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !windows - -package fiber - -import ( - "os/exec" -) - -var dummyChildCmd = "go" - -func dummyCmd() *exec.Cmd { - return exec.Command(dummyChildCmd, "version") -} diff --git a/prefork_dummy_windows.go b/prefork_dummy_windows.go deleted file mode 100644 index 6a13bb60..00000000 --- a/prefork_dummy_windows.go +++ /dev/null @@ -1,11 +0,0 @@ -package fiber - -import ( - "os/exec" -) - -var dummyChildCmd = "go" - -func dummyCmd() *exec.Cmd { - return exec.Command("cmd", "/C", dummyChildCmd, "version") -} diff --git a/prefork_test.go b/prefork_test.go index 02abf4a3..078d3624 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -42,7 +42,7 @@ func Test_App_Prefork_Child_Process(t *testing.T) { utils.AssertEqual(t, nil, app.prefork("127.0.0.1:", config)) } -func Test_App_Prefork_Main_Process(t *testing.T) { +func Test_App_Prefork_Master_Process(t *testing.T) { testPreforkMaster = true app := New() diff --git a/prefork_utils.go b/prefork_utils.go new file mode 100644 index 00000000..0e44e0c8 --- /dev/null +++ b/prefork_utils.go @@ -0,0 +1,28 @@ +// +build !windows + +package fiber + +import ( + "os" + "os/exec" + "time" +) + +var ( + dummyChildCmd = "go" +) + +func dummyCmd() *exec.Cmd { + return exec.Command(dummyChildCmd, "version") +} + +// watchMaster gets ppid regularly, +// if it is equal to 1 (init process ID), +// it indicates that the master process has exited +func watchMaster() { + for range time.NewTicker(time.Millisecond * 500).C { + if os.Getppid() == 1 { + os.Exit(1) + } + } +} diff --git a/prefork_utils_windows.go b/prefork_utils_windows.go new file mode 100644 index 00000000..66af4c4f --- /dev/null +++ b/prefork_utils_windows.go @@ -0,0 +1,22 @@ +package fiber + +import ( + "os" + "os/exec" +) + +var dummyChildCmd = "go" + +func dummyCmd() *exec.Cmd { + return exec.Command("cmd", "/C", dummyChildCmd, "version") +} + +// watchMaster finds parent process, +// and waits for it to exit +func watchMaster() { + p, err := os.FindProcess(os.Getppid()) + if err == nil { + _, _ = p.Wait() + } + os.Exit(1) +} From c89bfb36348518f64d3cb791e222af3984f1ca4b Mon Sep 17 00:00:00 2001 From: kiyon Date: Fri, 17 Jul 2020 09:34:27 +0800 Subject: [PATCH 03/36] =?UTF-8?q?=F0=9F=94=94=20fix=20ctx=20matched=20bug,?= =?UTF-8?q?=20it=20should=20be=20reset=20to=20false=20when=20acquired?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app_test.go | 7 ++++++- ctx.go | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app_test.go b/app_test.go index c59d1fef..ed213b08 100644 --- a/app_test.go +++ b/app_test.go @@ -40,7 +40,12 @@ func Test_App_MethodNotAllowed(t *testing.T) { app.Options("/", func(c *Ctx) {}) - resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + resp, err := app.Test(httptest.NewRequest("POST", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 200, resp.StatusCode) + utils.AssertEqual(t, "", resp.Header.Get(HeaderAllow)) + + resp, err = app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 405, resp.StatusCode) utils.AssertEqual(t, "POST, OPTIONS", resp.Header.Get(HeaderAllow)) diff --git a/ctx.go b/ctx.go index 5ab4c684..9077825e 100644 --- a/ctx.go +++ b/ctx.go @@ -87,6 +87,8 @@ func (app *App) AcquireCtx(fctx *fasthttp.RequestCtx) *Ctx { // Reset route and handler index ctx.indexRoute = -1 ctx.indexHandler = 0 + // Reset matched flag + ctx.matched = false // Set paths ctx.path = getString(fctx.URI().PathOriginal()) ctx.pathOriginal = ctx.path From 762b00f7d01437e39706e2f241281956cd30923c Mon Sep 17 00:00:00 2001 From: kiyon Date: Fri, 17 Jul 2020 10:05:01 +0800 Subject: [PATCH 04/36] =?UTF-8?q?=F0=9F=91=B7=20fixed=20#625?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctx.go b/ctx.go index 5ab4c684..ed77612d 100644 --- a/ctx.go +++ b/ctx.go @@ -833,7 +833,7 @@ func (ctx *Ctx) Render(name string, bind interface{}, layouts ...string) (err er // Set Content-Type to text/html ctx.Set(HeaderContentType, MIMETextHTMLCharsetUTF8) // Set rendered template to body - ctx.SendBytes(buf.Bytes()) + ctx.Fasthttp.Response.SetBody(buf.Bytes()) // Return err if exist return } From 35fdd375cdda29a31c7635b6cf5fba9c892885d0 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 00:47:18 +0200 Subject: [PATCH 05/36] =?UTF-8?q?=F0=9F=93=80=20Cores=20should=20be=20Thre?= =?UTF-8?q?ads?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app.go b/app.go index a57f37e6..3b76ec68 100644 --- a/app.go +++ b/app.go @@ -679,12 +679,12 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { host, port := parseAddr(addr) var ( - tlsStr = "FALSE" - routesLen = len(app.Routes()) - osName = utils.ToUpper(runtime.GOOS) - memTotal = utils.ByteSize(utils.MemoryTotal()) - cpuCores = runtime.NumCPU() - pid = os.Getpid() + tlsStr = "FALSE" + routesLen = len(app.Routes()) + osName = utils.ToUpper(runtime.GOOS) + memTotal = utils.ByteSize(utils.MemoryTotal()) + cpuThreads = runtime.NumCPU() + pid = os.Getpid() ) if host == "" { host = "0.0.0.0" @@ -708,10 +708,10 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { } // Build startup banner fmt.Fprintf(out, logo, cBlack, cBlack, - cCyan, cBlack, fmt.Sprintf(" HOST %s\tOS %s", cyan(host), cyan(osName)), - cCyan, cBlack, fmt.Sprintf(" PORT %s\tCORES %s", cyan(port), cyan(cpuCores)), - cCyan, cBlack, fmt.Sprintf(" TLS %s\tMEM %s", cyan(tlsStr), cyan(memTotal)), - cBlack, cyan(Version), fmt.Sprintf(" ROUTES %s\t\t\t PID %s%s%s\n", cyan(routesLen), cyan(pid), pids, cReset), + cCyan, cBlack, fmt.Sprintf(" HOST %s\tOS %s", cyan(host), cyan(osName)), + cCyan, cBlack, fmt.Sprintf(" PORT %s\tTHREADS %s", cyan(port), cyan(cpuThreads)), + cCyan, cBlack, fmt.Sprintf(" TLS %s\tMEM %s", cyan(tlsStr), cyan(memTotal)), + cBlack, cyan(Version), fmt.Sprintf(" ROUTES %s\t\t\t PID %s%s%s\n", cyan(routesLen), cyan(pid), pids, cReset), ) // Write to io.write _ = out.Flush() From 468404efe4512b00f01c41d64e8030cc08f541f7 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 00:57:43 +0200 Subject: [PATCH 06/36] =?UTF-8?q?=F0=9F=94=8C=20Support=20TCP6=20in=20Pref?= =?UTF-8?q?ork=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 3 --- prefork.go | 9 +++++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 3b76ec68..d41b0b0d 100644 --- a/app.go +++ b/app.go @@ -490,9 +490,6 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { app.init() // Start prefork if app.Settings.Prefork { - if app.Settings.Network == "tcp6" || isIPv6(addr) { - return fmt.Errorf("listen: tcp6 is not supported when prefork is enabled") - } return app.prefork(addr, tlsconfig...) } // Setup listener diff --git a/prefork.go b/prefork.go index 5a62a006..e955a110 100644 --- a/prefork.go +++ b/prefork.go @@ -35,8 +35,13 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { // use 1 cpu core per child process runtime.GOMAXPROCS(1) var ln net.Listener - // SO_REUSEPORT is not supported on Windows, use SO_REUSEADDR instead - if ln, err = reuseport.Listen("tcp4", addr); err != nil { + network := "tcp4" + if app.Settings.Network == "tcp6" { + network = app.Settings.Network + } + // Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR + // Only tcp4 or tcp6 is supported when preforking, both are not supported + if ln, err = reuseport.Listen(network, addr); err != nil { if !app.Settings.DisableStartupMessage { time.Sleep(100 * time.Millisecond) // avoid colliding with startup message } From 2893c13718b4402a5e590f9651f2700947db569a Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:03:14 +0200 Subject: [PATCH 07/36] =?UTF-8?q?=F0=9F=A7=B9=20Handle=20TCP6=20addr=20in?= =?UTF-8?q?=20Prefork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app.go b/app.go index d41b0b0d..c5b4dd79 100644 --- a/app.go +++ b/app.go @@ -490,6 +490,10 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { app.init() // Start prefork if app.Settings.Prefork { + // Prefork only supports tcp4 or tcp6, but not both + if isIPv6(addr) { + app.Settings.Network = "tcp6" + } return app.prefork(addr, tlsconfig...) } // Setup listener From 29c9a975561e2ac06bd15dfb987e60c45af835af Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:11:16 +0200 Subject: [PATCH 08/36] =?UTF-8?q?=F0=9F=A9=B9=20Update=20IPv6=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/prefork_test.go b/prefork_test.go index 078d3624..f7a1a705 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "io/ioutil" "os" + "strings" "testing" "time" @@ -67,11 +68,14 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { app.Settings.DisableStartupMessage = true app.init() - utils.AssertEqual(t, "listen: tcp6 is not supported when prefork is enabled", app.Listen("[::1]:3000").Error()) - app.Settings.Network = "tcp6" - app.init() - utils.AssertEqual(t, "listen: tcp6 is not supported when prefork is enabled", app.Listen(":3000").Error()) + go func() { + time.Sleep(1000 * time.Millisecond) + utils.AssertEqual(t, nil, app.Shutdown()) + }() + + err := app.Listen("[::1]:3200") + utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status")) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From a6b03415aaf2aa27e2260f0de7f5ad06ef0c667a Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:17:52 +0200 Subject: [PATCH 09/36] =?UTF-8?q?=F0=9F=94=8D=20Auto=20detect=20TCP=20prot?= =?UTF-8?q?ocol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 24 +++++++----------------- prefork.go | 6 +----- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/app.go b/app.go index c5b4dd79..3305f9b5 100644 --- a/app.go +++ b/app.go @@ -107,11 +107,6 @@ type Settings struct { // Default: false ETag bool `json:"etag"` - // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only) - // Prefork does not support the IPv6 network - // Default: "tcp" - Network string - // When set to true, this will spawn multiple Go processes listening on the same port. // Default: false Prefork bool `json:"prefork"` @@ -220,7 +215,6 @@ const ( defaultReadBufferSize = 4096 defaultWriteBufferSize = 4096 defaultCompressedFileSuffix = ".fiber.gz" - defaultNetwork = "tcp" ) var defaultErrorHandler = func(ctx *Ctx, err error) { @@ -277,9 +271,6 @@ func New(settings ...*Settings) *App { if app.Settings.ErrorHandler == nil { app.Settings.ErrorHandler = defaultErrorHandler } - if app.Settings.Network == "" { - app.Settings.Network = defaultNetwork - } if app.Settings.Immutable { getBytes, getString = getBytesImmutable, getStringImmutable } @@ -488,16 +479,17 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { } // Update fiber server settings app.init() + // Set correct network protocol + network := "tcp4" + if isIPv6(addr) { + network = "tcp6" + } // Start prefork if app.Settings.Prefork { - // Prefork only supports tcp4 or tcp6, but not both - if isIPv6(addr) { - app.Settings.Network = "tcp6" - } - return app.prefork(addr, tlsconfig...) + return app.prefork(network, addr, tlsconfig...) } // Setup listener - ln, err := net.Listen(app.Settings.Network, addr) + ln, err := net.Listen(network, addr) if err != nil { return err } @@ -610,8 +602,6 @@ func (app *App) init() *App { fmt.Printf("views: %v\n", err) } } - // TCP4 -> tcp4 - app.Settings.Network = utils.ToLower(app.Settings.Network) } if app.server == nil { app.server = &fasthttp.Server{ diff --git a/prefork.go b/prefork.go index e955a110..055f4df6 100644 --- a/prefork.go +++ b/prefork.go @@ -29,16 +29,12 @@ func (app *App) IsChild() bool { } // prefork manages child processes to make use of the OS REUSEPORT or REUSEADDR feature -func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { +func (app *App) prefork(network, addr string, tlsconfig ...*tls.Config) (err error) { // 👶 child process 👶 if app.IsChild() { // use 1 cpu core per child process runtime.GOMAXPROCS(1) var ln net.Listener - network := "tcp4" - if app.Settings.Network == "tcp6" { - network = app.Settings.Network - } // Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR // Only tcp4 or tcp6 is supported when preforking, both are not supported if ln, err = reuseport.Listen(network, addr); err != nil { From b8ae52c8353a57bcb5e26da468fdc822b3279380 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:19:45 +0200 Subject: [PATCH 10/36] =?UTF-8?q?=F0=9F=94=8D=20detect=20tcp=20proto=20by?= =?UTF-8?q?=20addr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 8 ++++---- prefork.go | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 3305f9b5..49006ec0 100644 --- a/app.go +++ b/app.go @@ -479,15 +479,15 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { } // Update fiber server settings app.init() + // Start prefork + if app.Settings.Prefork { + return app.prefork(addr, tlsconfig...) + } // Set correct network protocol network := "tcp4" if isIPv6(addr) { network = "tcp6" } - // Start prefork - if app.Settings.Prefork { - return app.prefork(network, addr, tlsconfig...) - } // Setup listener ln, err := net.Listen(network, addr) if err != nil { diff --git a/prefork.go b/prefork.go index 055f4df6..beb50f37 100644 --- a/prefork.go +++ b/prefork.go @@ -29,12 +29,17 @@ func (app *App) IsChild() bool { } // prefork manages child processes to make use of the OS REUSEPORT or REUSEADDR feature -func (app *App) prefork(network, addr string, tlsconfig ...*tls.Config) (err error) { +func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { // 👶 child process 👶 if app.IsChild() { // use 1 cpu core per child process runtime.GOMAXPROCS(1) var ln net.Listener + // Set correct network protocol + network := "tcp4" + if isIPv6(addr) { + network = "tcp6" + } // Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR // Only tcp4 or tcp6 is supported when preforking, both are not supported if ln, err = reuseport.Listen(network, addr); err != nil { From c9cb30766c34f864a08ed2ba500682a650664678 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:29:03 +0200 Subject: [PATCH 11/36] =?UTF-8?q?=F0=9F=A9=B9=20(=20=CD=A1=E2=86=91=20?= =?UTF-8?q?=CD=9C=CA=96=20=CD=A1=E2=86=91)=20Test=20is=20failing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prefork_test.go b/prefork_test.go index f7a1a705..fb273f9a 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -75,7 +75,7 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { }() err := app.Listen("[::1]:3200") - utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status")) + utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status"), err.Error()) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From d77c2691f6266bbbefa12abf2931c01f989f87f4 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:31:39 +0200 Subject: [PATCH 12/36] =?UTF-8?q?=F0=9F=A9=B9=20=E0=BC=BC=20=E0=B2=A5?= =?UTF-8?q?=D9=84=CD=9F=E0=B2=A5=20=E0=BC=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prefork_test.go b/prefork_test.go index fb273f9a..5dba04e2 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -12,6 +12,8 @@ import ( ) func Test_App_Prefork_Child_Process(t *testing.T) { + testPreforkMaster = false + utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) defer os.Setenv(envPreforkChildKey, "") @@ -63,6 +65,8 @@ func Test_App_Prefork_Master_Process(t *testing.T) { } func Test_App_Prefork_TCP6_Addr(t *testing.T) { + testPreforkMaster = false + app := New() app.Settings.Prefork = true app.Settings.DisableStartupMessage = true From 5218eb462d62afa85803a9ab5f3d4d2092b72107 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:36:56 +0200 Subject: [PATCH 13/36] =?UTF-8?q?=F0=9F=8D=A1=20o=CD=A1=CD=A1=CD=A1?= =?UTF-8?q?=E2=95=AE=E0=BC=BC=20=20=E0=B2=A0=D0=94=E0=B2=A0=20=E0=BC=BD?= =?UTF-8?q?=E2=95=ADo=CD=A1=CD=A1=CD=A1=E2=94=81=E2=98=86=EF=BE=9F.*?= =?UTF-8?q?=EF=BD=A5=EF=BD=A1=EF=BE=9F=20IPv6=20support=20for=20Prefork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/prefork_test.go b/prefork_test.go index 5dba04e2..2dd4adda 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -12,7 +12,8 @@ import ( ) func Test_App_Prefork_Child_Process(t *testing.T) { - testPreforkMaster = false + // Reset test var + testPreforkMaster = true utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) defer os.Setenv(envPreforkChildKey, "") @@ -46,6 +47,7 @@ func Test_App_Prefork_Child_Process(t *testing.T) { } func Test_App_Prefork_Master_Process(t *testing.T) { + // Reset test var testPreforkMaster = true app := New() @@ -65,7 +67,8 @@ func Test_App_Prefork_Master_Process(t *testing.T) { } func Test_App_Prefork_TCP6_Addr(t *testing.T) { - testPreforkMaster = false + // Reset test var + testPreforkMaster = true app := New() app.Settings.Prefork = true From 8a74cc3843e11eecb37d156a23015b9d6f495451 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:41:18 +0200 Subject: [PATCH 14/36] =?UTF-8?q?=F0=9F=A7=99=E2=80=8D=E2=99=82=EF=B8=8F?= =?UTF-8?q?=20Add=20IPv6=20support=20for=20Prefork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prefork_test.go b/prefork_test.go index 2dd4adda..628ef7a3 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -4,7 +4,6 @@ import ( "crypto/tls" "io/ioutil" "os" - "strings" "testing" "time" @@ -82,7 +81,7 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { }() err := app.Listen("[::1]:3200") - utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status"), err.Error()) + utils.AssertEqual(t, true, err == nil) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From f6b09e59b3ce39d2d05be73a3616435ee0a7a227 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:44:23 +0200 Subject: [PATCH 15/36] =?UTF-8?q?=F0=9F=A7=99=E2=80=8D=E2=99=82=EF=B8=8F?= =?UTF-8?q?=20Add=20IPv6=20Support=20in=20Prefork=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prefork_test.go b/prefork_test.go index 628ef7a3..201226a3 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -81,7 +81,7 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { }() err := app.Listen("[::1]:3200") - utils.AssertEqual(t, true, err == nil) + utils.AssertEqual(t, true, err != nil) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From 761532a3a5c565de3412b22f91b97cf3a2cb011c Mon Sep 17 00:00:00 2001 From: kiyon Date: Sat, 18 Jul 2020 08:44:32 +0800 Subject: [PATCH 16/36] =?UTF-8?q?=F0=9F=93=97=20improve=20ctx.Render=20tes?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctx_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ctx_test.go b/ctx_test.go index 5b871816..8939d40c 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -23,6 +23,8 @@ import ( "text/template" "time" + "github.com/valyala/bytebufferpool" + utils "github.com/gofiber/utils" fasthttp "github.com/valyala/fasthttp" ) @@ -1414,6 +1416,11 @@ func Test_Ctx_Render(t *testing.T) { err := ctx.Render("./.github/TEST_DATA/template.html", Map{ "Title": "Hello, World!", }) + + buf := bytebufferpool.Get() + _, _ = buf.WriteString("overwrite") + defer bytebufferpool.Put(buf) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(ctx.Fasthttp.Response.Body())) From 86af9e486c76600219129d3e83750afa25792d37 Mon Sep 17 00:00:00 2001 From: kiyon Date: Sat, 18 Jul 2020 10:42:22 +0800 Subject: [PATCH 17/36] =?UTF-8?q?=F0=9F=92=AF=20remain=20code=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app_test.go | 2 +- prefork_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app_test.go b/app_test.go index ed213b08..a221a117 100644 --- a/app_test.go +++ b/app_test.go @@ -754,7 +754,7 @@ func Test_App_Listen(t *testing.T) { utils.AssertEqual(t, nil, app.Shutdown()) }() - utils.AssertEqual(t, nil, app.Listen("4010")) + utils.AssertEqual(t, nil, app.Listen("[::]:4010")) } // go test -run Test_App_Listener diff --git a/prefork_test.go b/prefork_test.go index 201226a3..d9553c97 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -28,7 +28,7 @@ func Test_App_Prefork_Child_Process(t *testing.T) { utils.AssertEqual(t, nil, app.Shutdown()) }() - utils.AssertEqual(t, nil, app.prefork("127.0.0.1:")) + utils.AssertEqual(t, nil, app.prefork("[::]:")) // Create tls certificate cer, err := tls.LoadX509KeyPair("./.github/TEST_DATA/ssl.pem", "./.github/TEST_DATA/ssl.key") @@ -57,7 +57,7 @@ func Test_App_Prefork_Master_Process(t *testing.T) { utils.AssertEqual(t, nil, app.Shutdown()) }() - utils.AssertEqual(t, nil, app.prefork("127.0.0.1:")) + utils.AssertEqual(t, nil, app.prefork(":3000")) dummyChildCmd = "invalid" From f695e21b1e134f2cdc3273c615b39b71d32bd5b3 Mon Sep 17 00:00:00 2001 From: Hemanth Krishna Date: Sat, 18 Jul 2020 19:52:09 +0530 Subject: [PATCH 18/36] :pencil2: Fix typo for app and ctx warnings --- app.go | 2 +- ctx.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app.go b/app.go index 49006ec0..9abc4386 100644 --- a/app.go +++ b/app.go @@ -594,7 +594,7 @@ func (app *App) init() *App { if app.Settings != nil { // Templates is replaced by Views with layout support if app.Settings.Templates != nil { - fmt.Println("`Templates` are deprecated since v1.12.x, please us `Views` instead") + fmt.Println("`Templates` are deprecated since v1.12.x, please use `Views` instead") } // Only load templates if an view engine is specified if app.Settings.Views != nil { diff --git a/ctx.go b/ctx.go index a4e9749a..7c15a61d 100644 --- a/ctx.go +++ b/ctx.go @@ -261,7 +261,7 @@ func (ctx *Ctx) BodyParser(out interface{}) error { // 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") + fmt.Println("Parsing query strings using `BodyParser` is deprecated since v1.12.7, please use `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)) From 97c8b103c3b81831d39242dc39481402a611eb22 Mon Sep 17 00:00:00 2001 From: kiyon Date: Thu, 16 Jul 2020 16:42:36 +0800 Subject: [PATCH 19/36] =?UTF-8?q?=20=F0=9F=91=B7=20improve=20test=20covera?= =?UTF-8?q?ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app_test.go | 30 ++++++++++++++++++++++++++++++ ctx_test.go | 3 +++ prefork.go | 11 +++-------- prefork_dummy.go | 13 +++++++++++++ prefork_dummy_windows.go | 11 +++++++++++ prefork_test.go | 37 +++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 8 deletions(-) create mode 100644 prefork_dummy.go create mode 100644 prefork_dummy_windows.go diff --git a/app_test.go b/app_test.go index c7cd748e..c59d1fef 100644 --- a/app_test.go +++ b/app_test.go @@ -8,6 +8,7 @@ import ( "crypto/tls" "errors" "fmt" + "io" "io/ioutil" "net" "net/http/httptest" @@ -627,6 +628,15 @@ func Test_App_Mixed_Routes_WithSameLen(t *testing.T) { utils.AssertEqual(t, true, strings.HasPrefix(string(body), ""), "Response: "+string(body)) } +func Test_App_Group_Invalid(t *testing.T) { + defer func() { + if err := recover(); err != nil { + utils.AssertEqual(t, "use: invalid handler int\n", fmt.Sprintf("%v", err)) + } + }() + New().Group("/").Use(1) +} + func Test_App_Group(t *testing.T) { var dummyHandler = func(c *Ctx) {} @@ -725,6 +735,8 @@ func Test_App_Listen(t *testing.T) { utils.AssertEqual(t, false, app.Listen(1.23) == nil) + utils.AssertEqual(t, false, app.Listen(":1.23") == nil) + go func() { time.Sleep(1000 * time.Millisecond) utils.AssertEqual(t, nil, app.Shutdown()) @@ -808,3 +820,21 @@ func Test_App_Handler(t *testing.T) { h := New().Handler() utils.AssertEqual(t, "fasthttp.RequestHandler", reflect.TypeOf(h).String()) } + +type invalidView struct{} + +func (invalidView) Load() error { return errors.New("invalid view") } + +func (i invalidView) Render(io.Writer, string, interface{}, ...string) error { panic("implement me") } + +func Test_App_Init_Error_View(t *testing.T) { + app := New(&Settings{Views: invalidView{}}) + app.init() + + defer func() { + if err := recover(); err != nil { + utils.AssertEqual(t, "implement me", fmt.Sprintf("%v", err)) + } + }() + _ = app.Settings.Views.Render(nil, "", nil) +} diff --git a/ctx_test.go b/ctx_test.go index 1ce82c31..5b871816 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -1416,6 +1416,9 @@ func Test_Ctx_Render(t *testing.T) { }) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(ctx.Fasthttp.Response.Body())) + + err = ctx.Render("./.github/TEST_DATA/invalid.html", nil) + utils.AssertEqual(t, false, err == nil) } type testTemplateEngine struct { diff --git a/prefork.go b/prefork.go index c5afa5b8..cf4bb1c9 100644 --- a/prefork.go +++ b/prefork.go @@ -21,7 +21,6 @@ const ( var ( testPreforkMaster = false - dummyChildCmd = "go" ) // IsChild determines if the current process is a result of Prefork @@ -87,13 +86,9 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { 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 - if runtime.GOOS == "windows" { - cmd = exec.Command("cmd", "/C", dummyChildCmd, "version") - } else { - cmd = exec.Command(dummyChildCmd, "version") - } + // just start the child process with a dummy cmd, + // which will exit soon + cmd = dummyCmd() } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/prefork_dummy.go b/prefork_dummy.go new file mode 100644 index 00000000..afaaac4e --- /dev/null +++ b/prefork_dummy.go @@ -0,0 +1,13 @@ +// +build !windows + +package fiber + +import ( + "os/exec" +) + +var dummyChildCmd = "go" + +func dummyCmd() *exec.Cmd { + return exec.Command(dummyChildCmd, "version") +} diff --git a/prefork_dummy_windows.go b/prefork_dummy_windows.go new file mode 100644 index 00000000..6a13bb60 --- /dev/null +++ b/prefork_dummy_windows.go @@ -0,0 +1,11 @@ +package fiber + +import ( + "os/exec" +) + +var dummyChildCmd = "go" + +func dummyCmd() *exec.Cmd { + return exec.Command("cmd", "/C", dummyChildCmd, "version") +} diff --git a/prefork_test.go b/prefork_test.go index a904482b..02abf4a3 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -1,6 +1,8 @@ package fiber import ( + "crypto/tls" + "io/ioutil" "os" "testing" "time" @@ -24,6 +26,20 @@ func Test_App_Prefork_Child_Process(t *testing.T) { }() utils.AssertEqual(t, nil, app.prefork("127.0.0.1:")) + + // Create tls certificate + cer, err := tls.LoadX509KeyPair("./.github/TEST_DATA/ssl.pem", "./.github/TEST_DATA/ssl.key") + if err != nil { + utils.AssertEqual(t, nil, err) + } + config := &tls.Config{Certificates: []tls.Certificate{cer}} + + go func() { + time.Sleep(1000 * time.Millisecond) + utils.AssertEqual(t, nil, app.Shutdown()) + }() + + utils.AssertEqual(t, nil, app.prefork("127.0.0.1:", config)) } func Test_App_Prefork_Main_Process(t *testing.T) { @@ -57,3 +73,24 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { app.init() utils.AssertEqual(t, "listen: tcp6 is not supported when prefork is enabled", app.Listen(":3000").Error()) } + +func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { + utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) + defer os.Setenv(envPreforkChildKey, "") + + rescueStdout := os.Stdout + defer func() { os.Stdout = rescueStdout }() + + r, w, err := os.Pipe() + utils.AssertEqual(t, nil, err) + + os.Stdout = w + + New().startupMessage(":3000", false, "") + + utils.AssertEqual(t, nil, w.Close()) + + out, err := ioutil.ReadAll(r) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 0, len(out)) +} From 4f2d1f608a19e72a5a8ee2bf415e206b68564745 Mon Sep 17 00:00:00 2001 From: kiyon Date: Fri, 17 Jul 2020 06:51:57 +0800 Subject: [PATCH 20/36] =?UTF-8?q?=F0=9F=8C=BC=20separate=20different=20log?= =?UTF-8?q?ic=20on=20each=20OS=20for=20child=20process=20to=20watch=20if?= =?UTF-8?q?=20master=20process=20exits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork.go | 12 +++--------- prefork_dummy.go | 13 ------------- prefork_dummy_windows.go | 11 ----------- prefork_test.go | 2 +- prefork_utils.go | 28 ++++++++++++++++++++++++++++ prefork_utils_windows.go | 22 ++++++++++++++++++++++ 6 files changed, 54 insertions(+), 34 deletions(-) delete mode 100644 prefork_dummy.go delete mode 100644 prefork_dummy_windows.go create mode 100644 prefork_utils.go create mode 100644 prefork_utils_windows.go diff --git a/prefork.go b/prefork.go index cf4bb1c9..5a62a006 100644 --- a/prefork.go +++ b/prefork.go @@ -47,15 +47,9 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { ln = tls.NewListener(ln, tlsconfig[0]) } - // kill child proc when master exits - go func() { - p, err := os.FindProcess(os.Getppid()) - if err == nil { - _, _ = p.Wait() - } else { - os.Exit(1) - } - }() + // kill current child proc when master exits + go watchMaster() + // listen for incoming connections return app.server.Serve(ln) } diff --git a/prefork_dummy.go b/prefork_dummy.go deleted file mode 100644 index afaaac4e..00000000 --- a/prefork_dummy.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !windows - -package fiber - -import ( - "os/exec" -) - -var dummyChildCmd = "go" - -func dummyCmd() *exec.Cmd { - return exec.Command(dummyChildCmd, "version") -} diff --git a/prefork_dummy_windows.go b/prefork_dummy_windows.go deleted file mode 100644 index 6a13bb60..00000000 --- a/prefork_dummy_windows.go +++ /dev/null @@ -1,11 +0,0 @@ -package fiber - -import ( - "os/exec" -) - -var dummyChildCmd = "go" - -func dummyCmd() *exec.Cmd { - return exec.Command("cmd", "/C", dummyChildCmd, "version") -} diff --git a/prefork_test.go b/prefork_test.go index 02abf4a3..078d3624 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -42,7 +42,7 @@ func Test_App_Prefork_Child_Process(t *testing.T) { utils.AssertEqual(t, nil, app.prefork("127.0.0.1:", config)) } -func Test_App_Prefork_Main_Process(t *testing.T) { +func Test_App_Prefork_Master_Process(t *testing.T) { testPreforkMaster = true app := New() diff --git a/prefork_utils.go b/prefork_utils.go new file mode 100644 index 00000000..0e44e0c8 --- /dev/null +++ b/prefork_utils.go @@ -0,0 +1,28 @@ +// +build !windows + +package fiber + +import ( + "os" + "os/exec" + "time" +) + +var ( + dummyChildCmd = "go" +) + +func dummyCmd() *exec.Cmd { + return exec.Command(dummyChildCmd, "version") +} + +// watchMaster gets ppid regularly, +// if it is equal to 1 (init process ID), +// it indicates that the master process has exited +func watchMaster() { + for range time.NewTicker(time.Millisecond * 500).C { + if os.Getppid() == 1 { + os.Exit(1) + } + } +} diff --git a/prefork_utils_windows.go b/prefork_utils_windows.go new file mode 100644 index 00000000..66af4c4f --- /dev/null +++ b/prefork_utils_windows.go @@ -0,0 +1,22 @@ +package fiber + +import ( + "os" + "os/exec" +) + +var dummyChildCmd = "go" + +func dummyCmd() *exec.Cmd { + return exec.Command("cmd", "/C", dummyChildCmd, "version") +} + +// watchMaster finds parent process, +// and waits for it to exit +func watchMaster() { + p, err := os.FindProcess(os.Getppid()) + if err == nil { + _, _ = p.Wait() + } + os.Exit(1) +} From e2a614bcd608545086f7ff22c59ea8549e2f4daa Mon Sep 17 00:00:00 2001 From: kiyon Date: Fri, 17 Jul 2020 09:34:27 +0800 Subject: [PATCH 21/36] =?UTF-8?q?=F0=9F=94=94=20fix=20ctx=20matched=20bug,?= =?UTF-8?q?=20it=20should=20be=20reset=20to=20false=20when=20acquired?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app_test.go | 7 ++++++- ctx.go | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app_test.go b/app_test.go index c59d1fef..ed213b08 100644 --- a/app_test.go +++ b/app_test.go @@ -40,7 +40,12 @@ func Test_App_MethodNotAllowed(t *testing.T) { app.Options("/", func(c *Ctx) {}) - resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + resp, err := app.Test(httptest.NewRequest("POST", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 200, resp.StatusCode) + utils.AssertEqual(t, "", resp.Header.Get(HeaderAllow)) + + resp, err = app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 405, resp.StatusCode) utils.AssertEqual(t, "POST, OPTIONS", resp.Header.Get(HeaderAllow)) diff --git a/ctx.go b/ctx.go index 5ab4c684..9077825e 100644 --- a/ctx.go +++ b/ctx.go @@ -87,6 +87,8 @@ func (app *App) AcquireCtx(fctx *fasthttp.RequestCtx) *Ctx { // Reset route and handler index ctx.indexRoute = -1 ctx.indexHandler = 0 + // Reset matched flag + ctx.matched = false // Set paths ctx.path = getString(fctx.URI().PathOriginal()) ctx.pathOriginal = ctx.path From 1cb91ad1045068996760623fe0edf790644fe608 Mon Sep 17 00:00:00 2001 From: kiyon Date: Fri, 17 Jul 2020 10:05:01 +0800 Subject: [PATCH 22/36] =?UTF-8?q?=F0=9F=91=B7=20fixed=20#625?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctx.go b/ctx.go index 9077825e..a4e9749a 100644 --- a/ctx.go +++ b/ctx.go @@ -835,7 +835,7 @@ func (ctx *Ctx) Render(name string, bind interface{}, layouts ...string) (err er // Set Content-Type to text/html ctx.Set(HeaderContentType, MIMETextHTMLCharsetUTF8) // Set rendered template to body - ctx.SendBytes(buf.Bytes()) + ctx.Fasthttp.Response.SetBody(buf.Bytes()) // Return err if exist return } From 662b21b6f04518aae86f44f9c0d5838737fdb2d3 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 00:47:18 +0200 Subject: [PATCH 23/36] =?UTF-8?q?=F0=9F=93=80=20Cores=20should=20be=20Thre?= =?UTF-8?q?ads?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app.go b/app.go index a57f37e6..3b76ec68 100644 --- a/app.go +++ b/app.go @@ -679,12 +679,12 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { host, port := parseAddr(addr) var ( - tlsStr = "FALSE" - routesLen = len(app.Routes()) - osName = utils.ToUpper(runtime.GOOS) - memTotal = utils.ByteSize(utils.MemoryTotal()) - cpuCores = runtime.NumCPU() - pid = os.Getpid() + tlsStr = "FALSE" + routesLen = len(app.Routes()) + osName = utils.ToUpper(runtime.GOOS) + memTotal = utils.ByteSize(utils.MemoryTotal()) + cpuThreads = runtime.NumCPU() + pid = os.Getpid() ) if host == "" { host = "0.0.0.0" @@ -708,10 +708,10 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { } // Build startup banner fmt.Fprintf(out, logo, cBlack, cBlack, - cCyan, cBlack, fmt.Sprintf(" HOST %s\tOS %s", cyan(host), cyan(osName)), - cCyan, cBlack, fmt.Sprintf(" PORT %s\tCORES %s", cyan(port), cyan(cpuCores)), - cCyan, cBlack, fmt.Sprintf(" TLS %s\tMEM %s", cyan(tlsStr), cyan(memTotal)), - cBlack, cyan(Version), fmt.Sprintf(" ROUTES %s\t\t\t PID %s%s%s\n", cyan(routesLen), cyan(pid), pids, cReset), + cCyan, cBlack, fmt.Sprintf(" HOST %s\tOS %s", cyan(host), cyan(osName)), + cCyan, cBlack, fmt.Sprintf(" PORT %s\tTHREADS %s", cyan(port), cyan(cpuThreads)), + cCyan, cBlack, fmt.Sprintf(" TLS %s\tMEM %s", cyan(tlsStr), cyan(memTotal)), + cBlack, cyan(Version), fmt.Sprintf(" ROUTES %s\t\t\t PID %s%s%s\n", cyan(routesLen), cyan(pid), pids, cReset), ) // Write to io.write _ = out.Flush() From 1ae1e8c1a134965a18ac0c2a763792fdbe21a8dc Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 00:57:43 +0200 Subject: [PATCH 24/36] =?UTF-8?q?=F0=9F=94=8C=20Support=20TCP6=20in=20Pref?= =?UTF-8?q?ork=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 3 --- prefork.go | 9 +++++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 3b76ec68..d41b0b0d 100644 --- a/app.go +++ b/app.go @@ -490,9 +490,6 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { app.init() // Start prefork if app.Settings.Prefork { - if app.Settings.Network == "tcp6" || isIPv6(addr) { - return fmt.Errorf("listen: tcp6 is not supported when prefork is enabled") - } return app.prefork(addr, tlsconfig...) } // Setup listener diff --git a/prefork.go b/prefork.go index 5a62a006..e955a110 100644 --- a/prefork.go +++ b/prefork.go @@ -35,8 +35,13 @@ func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { // use 1 cpu core per child process runtime.GOMAXPROCS(1) var ln net.Listener - // SO_REUSEPORT is not supported on Windows, use SO_REUSEADDR instead - if ln, err = reuseport.Listen("tcp4", addr); err != nil { + network := "tcp4" + if app.Settings.Network == "tcp6" { + network = app.Settings.Network + } + // Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR + // Only tcp4 or tcp6 is supported when preforking, both are not supported + if ln, err = reuseport.Listen(network, addr); err != nil { if !app.Settings.DisableStartupMessage { time.Sleep(100 * time.Millisecond) // avoid colliding with startup message } From ac01a1717fb5ef7e25bc53fcea6f7d7dd49c21d5 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:03:14 +0200 Subject: [PATCH 25/36] =?UTF-8?q?=F0=9F=A7=B9=20Handle=20TCP6=20addr=20in?= =?UTF-8?q?=20Prefork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app.go b/app.go index d41b0b0d..c5b4dd79 100644 --- a/app.go +++ b/app.go @@ -490,6 +490,10 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { app.init() // Start prefork if app.Settings.Prefork { + // Prefork only supports tcp4 or tcp6, but not both + if isIPv6(addr) { + app.Settings.Network = "tcp6" + } return app.prefork(addr, tlsconfig...) } // Setup listener From 50c0da579d91e1ce63371b1359805c622881327e Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:11:16 +0200 Subject: [PATCH 26/36] =?UTF-8?q?=F0=9F=A9=B9=20Update=20IPv6=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/prefork_test.go b/prefork_test.go index 078d3624..f7a1a705 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "io/ioutil" "os" + "strings" "testing" "time" @@ -67,11 +68,14 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { app.Settings.DisableStartupMessage = true app.init() - utils.AssertEqual(t, "listen: tcp6 is not supported when prefork is enabled", app.Listen("[::1]:3000").Error()) - app.Settings.Network = "tcp6" - app.init() - utils.AssertEqual(t, "listen: tcp6 is not supported when prefork is enabled", app.Listen(":3000").Error()) + go func() { + time.Sleep(1000 * time.Millisecond) + utils.AssertEqual(t, nil, app.Shutdown()) + }() + + err := app.Listen("[::1]:3200") + utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status")) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From e15f77ecb8093cd5d11b52bfcc9bda8d34ca2e04 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:17:52 +0200 Subject: [PATCH 27/36] =?UTF-8?q?=F0=9F=94=8D=20Auto=20detect=20TCP=20prot?= =?UTF-8?q?ocol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 24 +++++++----------------- prefork.go | 6 +----- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/app.go b/app.go index c5b4dd79..3305f9b5 100644 --- a/app.go +++ b/app.go @@ -107,11 +107,6 @@ type Settings struct { // Default: false ETag bool `json:"etag"` - // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only) - // Prefork does not support the IPv6 network - // Default: "tcp" - Network string - // When set to true, this will spawn multiple Go processes listening on the same port. // Default: false Prefork bool `json:"prefork"` @@ -220,7 +215,6 @@ const ( defaultReadBufferSize = 4096 defaultWriteBufferSize = 4096 defaultCompressedFileSuffix = ".fiber.gz" - defaultNetwork = "tcp" ) var defaultErrorHandler = func(ctx *Ctx, err error) { @@ -277,9 +271,6 @@ func New(settings ...*Settings) *App { if app.Settings.ErrorHandler == nil { app.Settings.ErrorHandler = defaultErrorHandler } - if app.Settings.Network == "" { - app.Settings.Network = defaultNetwork - } if app.Settings.Immutable { getBytes, getString = getBytesImmutable, getStringImmutable } @@ -488,16 +479,17 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { } // Update fiber server settings app.init() + // Set correct network protocol + network := "tcp4" + if isIPv6(addr) { + network = "tcp6" + } // Start prefork if app.Settings.Prefork { - // Prefork only supports tcp4 or tcp6, but not both - if isIPv6(addr) { - app.Settings.Network = "tcp6" - } - return app.prefork(addr, tlsconfig...) + return app.prefork(network, addr, tlsconfig...) } // Setup listener - ln, err := net.Listen(app.Settings.Network, addr) + ln, err := net.Listen(network, addr) if err != nil { return err } @@ -610,8 +602,6 @@ func (app *App) init() *App { fmt.Printf("views: %v\n", err) } } - // TCP4 -> tcp4 - app.Settings.Network = utils.ToLower(app.Settings.Network) } if app.server == nil { app.server = &fasthttp.Server{ diff --git a/prefork.go b/prefork.go index e955a110..055f4df6 100644 --- a/prefork.go +++ b/prefork.go @@ -29,16 +29,12 @@ func (app *App) IsChild() bool { } // prefork manages child processes to make use of the OS REUSEPORT or REUSEADDR feature -func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { +func (app *App) prefork(network, addr string, tlsconfig ...*tls.Config) (err error) { // 👶 child process 👶 if app.IsChild() { // use 1 cpu core per child process runtime.GOMAXPROCS(1) var ln net.Listener - network := "tcp4" - if app.Settings.Network == "tcp6" { - network = app.Settings.Network - } // Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR // Only tcp4 or tcp6 is supported when preforking, both are not supported if ln, err = reuseport.Listen(network, addr); err != nil { From 4b2bbd9a94623a985a02ea28cabe26718df44e32 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:19:45 +0200 Subject: [PATCH 28/36] =?UTF-8?q?=F0=9F=94=8D=20detect=20tcp=20proto=20by?= =?UTF-8?q?=20addr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 8 ++++---- prefork.go | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 3305f9b5..49006ec0 100644 --- a/app.go +++ b/app.go @@ -479,15 +479,15 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { } // Update fiber server settings app.init() + // Start prefork + if app.Settings.Prefork { + return app.prefork(addr, tlsconfig...) + } // Set correct network protocol network := "tcp4" if isIPv6(addr) { network = "tcp6" } - // Start prefork - if app.Settings.Prefork { - return app.prefork(network, addr, tlsconfig...) - } // Setup listener ln, err := net.Listen(network, addr) if err != nil { diff --git a/prefork.go b/prefork.go index 055f4df6..beb50f37 100644 --- a/prefork.go +++ b/prefork.go @@ -29,12 +29,17 @@ func (app *App) IsChild() bool { } // prefork manages child processes to make use of the OS REUSEPORT or REUSEADDR feature -func (app *App) prefork(network, addr string, tlsconfig ...*tls.Config) (err error) { +func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) { // 👶 child process 👶 if app.IsChild() { // use 1 cpu core per child process runtime.GOMAXPROCS(1) var ln net.Listener + // Set correct network protocol + network := "tcp4" + if isIPv6(addr) { + network = "tcp6" + } // Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR // Only tcp4 or tcp6 is supported when preforking, both are not supported if ln, err = reuseport.Listen(network, addr); err != nil { From fb9516e4009ba18507e05b29699641f39a621c1b Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:29:03 +0200 Subject: [PATCH 29/36] =?UTF-8?q?=F0=9F=A9=B9=20(=20=CD=A1=E2=86=91=20?= =?UTF-8?q?=CD=9C=CA=96=20=CD=A1=E2=86=91)=20Test=20is=20failing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prefork_test.go b/prefork_test.go index f7a1a705..fb273f9a 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -75,7 +75,7 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { }() err := app.Listen("[::1]:3200") - utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status")) + utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status"), err.Error()) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From 1f35688ef0ed314bedccfcb3aa1fa043d1c17a90 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:31:39 +0200 Subject: [PATCH 30/36] =?UTF-8?q?=F0=9F=A9=B9=20=E0=BC=BC=20=E0=B2=A5?= =?UTF-8?q?=D9=84=CD=9F=E0=B2=A5=20=E0=BC=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prefork_test.go b/prefork_test.go index fb273f9a..5dba04e2 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -12,6 +12,8 @@ import ( ) func Test_App_Prefork_Child_Process(t *testing.T) { + testPreforkMaster = false + utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) defer os.Setenv(envPreforkChildKey, "") @@ -63,6 +65,8 @@ func Test_App_Prefork_Master_Process(t *testing.T) { } func Test_App_Prefork_TCP6_Addr(t *testing.T) { + testPreforkMaster = false + app := New() app.Settings.Prefork = true app.Settings.DisableStartupMessage = true From b608948edc965ee75615ead7b7be79f67e48c66c Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:36:56 +0200 Subject: [PATCH 31/36] =?UTF-8?q?=F0=9F=8D=A1=20o=CD=A1=CD=A1=CD=A1?= =?UTF-8?q?=E2=95=AE=E0=BC=BC=20=20=E0=B2=A0=D0=94=E0=B2=A0=20=E0=BC=BD?= =?UTF-8?q?=E2=95=ADo=CD=A1=CD=A1=CD=A1=E2=94=81=E2=98=86=EF=BE=9F.*?= =?UTF-8?q?=EF=BD=A5=EF=BD=A1=EF=BE=9F=20IPv6=20support=20for=20Prefork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/prefork_test.go b/prefork_test.go index 5dba04e2..2dd4adda 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -12,7 +12,8 @@ import ( ) func Test_App_Prefork_Child_Process(t *testing.T) { - testPreforkMaster = false + // Reset test var + testPreforkMaster = true utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) defer os.Setenv(envPreforkChildKey, "") @@ -46,6 +47,7 @@ func Test_App_Prefork_Child_Process(t *testing.T) { } func Test_App_Prefork_Master_Process(t *testing.T) { + // Reset test var testPreforkMaster = true app := New() @@ -65,7 +67,8 @@ func Test_App_Prefork_Master_Process(t *testing.T) { } func Test_App_Prefork_TCP6_Addr(t *testing.T) { - testPreforkMaster = false + // Reset test var + testPreforkMaster = true app := New() app.Settings.Prefork = true From 460ab2a630320f6e4ab3dc3a6a5e1d27fa923c41 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:41:18 +0200 Subject: [PATCH 32/36] =?UTF-8?q?=F0=9F=A7=99=E2=80=8D=E2=99=82=EF=B8=8F?= =?UTF-8?q?=20Add=20IPv6=20support=20for=20Prefork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prefork_test.go b/prefork_test.go index 2dd4adda..628ef7a3 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -4,7 +4,6 @@ import ( "crypto/tls" "io/ioutil" "os" - "strings" "testing" "time" @@ -82,7 +81,7 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { }() err := app.Listen("[::1]:3200") - utils.AssertEqual(t, true, strings.Contains(err.Error(), "exit status"), err.Error()) + utils.AssertEqual(t, true, err == nil) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From 8a61775f00d643e3ebf40bf9eb4e206f0a404245 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Sat, 18 Jul 2020 01:44:23 +0200 Subject: [PATCH 33/36] =?UTF-8?q?=F0=9F=A7=99=E2=80=8D=E2=99=82=EF=B8=8F?= =?UTF-8?q?=20Add=20IPv6=20Support=20in=20Prefork=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefork_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prefork_test.go b/prefork_test.go index 628ef7a3..201226a3 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -81,7 +81,7 @@ func Test_App_Prefork_TCP6_Addr(t *testing.T) { }() err := app.Listen("[::1]:3200") - utils.AssertEqual(t, true, err == nil) + utils.AssertEqual(t, true, err != nil) } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { From c3b5de6b79cd4058802fdf8d450cced1255c06a1 Mon Sep 17 00:00:00 2001 From: kiyon Date: Sat, 18 Jul 2020 08:44:32 +0800 Subject: [PATCH 34/36] =?UTF-8?q?=F0=9F=93=97=20improve=20ctx.Render=20tes?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctx_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ctx_test.go b/ctx_test.go index 5b871816..8939d40c 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -23,6 +23,8 @@ import ( "text/template" "time" + "github.com/valyala/bytebufferpool" + utils "github.com/gofiber/utils" fasthttp "github.com/valyala/fasthttp" ) @@ -1414,6 +1416,11 @@ func Test_Ctx_Render(t *testing.T) { err := ctx.Render("./.github/TEST_DATA/template.html", Map{ "Title": "Hello, World!", }) + + buf := bytebufferpool.Get() + _, _ = buf.WriteString("overwrite") + defer bytebufferpool.Put(buf) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(ctx.Fasthttp.Response.Body())) From 79981c5d38f20ae55707925108f1fdbaf4d3e66c Mon Sep 17 00:00:00 2001 From: kiyon Date: Sat, 18 Jul 2020 10:42:22 +0800 Subject: [PATCH 35/36] =?UTF-8?q?=F0=9F=92=AF=20remain=20code=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app_test.go | 2 +- prefork_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app_test.go b/app_test.go index ed213b08..a221a117 100644 --- a/app_test.go +++ b/app_test.go @@ -754,7 +754,7 @@ func Test_App_Listen(t *testing.T) { utils.AssertEqual(t, nil, app.Shutdown()) }() - utils.AssertEqual(t, nil, app.Listen("4010")) + utils.AssertEqual(t, nil, app.Listen("[::]:4010")) } // go test -run Test_App_Listener diff --git a/prefork_test.go b/prefork_test.go index 201226a3..d9553c97 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -28,7 +28,7 @@ func Test_App_Prefork_Child_Process(t *testing.T) { utils.AssertEqual(t, nil, app.Shutdown()) }() - utils.AssertEqual(t, nil, app.prefork("127.0.0.1:")) + utils.AssertEqual(t, nil, app.prefork("[::]:")) // Create tls certificate cer, err := tls.LoadX509KeyPair("./.github/TEST_DATA/ssl.pem", "./.github/TEST_DATA/ssl.key") @@ -57,7 +57,7 @@ func Test_App_Prefork_Master_Process(t *testing.T) { utils.AssertEqual(t, nil, app.Shutdown()) }() - utils.AssertEqual(t, nil, app.prefork("127.0.0.1:")) + utils.AssertEqual(t, nil, app.prefork(":3000")) dummyChildCmd = "invalid" From 53c7cdffd30c9494b4919eac879f5c700d7f2211 Mon Sep 17 00:00:00 2001 From: Hemanth Krishna Date: Sat, 18 Jul 2020 19:52:09 +0530 Subject: [PATCH 36/36] :pencil2: Fix typo for app and ctx warnings --- app.go | 2 +- ctx.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app.go b/app.go index 49006ec0..9abc4386 100644 --- a/app.go +++ b/app.go @@ -594,7 +594,7 @@ func (app *App) init() *App { if app.Settings != nil { // Templates is replaced by Views with layout support if app.Settings.Templates != nil { - fmt.Println("`Templates` are deprecated since v1.12.x, please us `Views` instead") + fmt.Println("`Templates` are deprecated since v1.12.x, please use `Views` instead") } // Only load templates if an view engine is specified if app.Settings.Views != nil { diff --git a/ctx.go b/ctx.go index a4e9749a..7c15a61d 100644 --- a/ctx.go +++ b/ctx.go @@ -261,7 +261,7 @@ func (ctx *Ctx) BodyParser(out interface{}) error { // 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") + fmt.Println("Parsing query strings using `BodyParser` is deprecated since v1.12.7, please use `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))