diff --git a/application.go b/application.go index 3bc3d493..6abf8c92 100644 --- a/application.go +++ b/application.go @@ -10,6 +10,8 @@ package fiber import ( "flag" "time" + + "github.com/valyala/fasthttp" ) const ( @@ -33,7 +35,8 @@ var ( // Fiber structure type Fiber struct { // Server name header - Server string + Server string + httpServer *fasthttp.Server // Show fiber banner Banner bool // https://github.com/valyala/fasthttp/blob/master/server.go#L150 diff --git a/listen.go b/listen.go index 8d465840..2d04b490 100644 --- a/listen.go +++ b/listen.go @@ -21,6 +21,11 @@ import ( "github.com/valyala/fasthttp/reuseport" ) +// Shutdown server gracefully +func (r *Fiber) Shutdown() error { + return r.httpServer.Shutdown() +} + // Listen : https://gofiber.github.io/fiber/#/application?id=listen func (r *Fiber) Listen(address interface{}, tls ...string) { host := "" @@ -36,7 +41,7 @@ func (r *Fiber) Listen(address interface{}, tls ...string) { log.Fatal("Listen: Host must be an INT port or STRING address") } // Create fasthttp server - server := r.setupServer() + r.httpServer = r.setupServer() // Prefork enabled if r.Prefork && runtime.NumCPU() > 1 { @@ -44,7 +49,7 @@ func (r *Fiber) Listen(address interface{}, tls ...string) { cores := fmt.Sprintf("%s\x1b[1;30m %v cores", host, runtime.NumCPU()) fmt.Printf(banner, Version, " prefork", "Express on steroids", cores) } - r.prefork(server, host, tls...) + r.prefork(host, tls...) } // Prefork disabled @@ -59,18 +64,18 @@ func (r *Fiber) Listen(address interface{}, tls ...string) { // enable TLS/HTTPS if len(tls) > 1 { - if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil { + if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil { log.Fatal("Listen: ", err) } } - if err := server.Serve(ln); err != nil { + if err := r.httpServer.Serve(ln); err != nil { log.Fatal("Listen: ", err) } } // https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ -func (r *Fiber) prefork(server *fasthttp.Server, host string, tls ...string) { +func (r *Fiber) prefork(host string, tls ...string) { // Master proc if !r.child { // Create babies @@ -106,12 +111,12 @@ func (r *Fiber) prefork(server *fasthttp.Server, host string, tls ...string) { // enable TLS/HTTPS if len(tls) > 1 { - if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil { + if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil { log.Fatal("Listen-prefork: ", err) } } - if err := server.Serve(ln); err != nil { + if err := r.httpServer.Serve(ln); err != nil { log.Fatal("Listen-prefork: ", err) } } diff --git a/listen_test.go b/listen_test.go new file mode 100644 index 00000000..63d784da --- /dev/null +++ b/listen_test.go @@ -0,0 +1,23 @@ +package fiber + +import ( + "testing" + "time" +) + +func Test_Connect(t *testing.T) { + app := New() + app.Banner = false + app.Get("/", func(c *Ctx) { + + }) + go func() { + app.Listen(":8085") + }() + time.Sleep(1 * time.Second) + err := app.Shutdown() + if err != nil { + t.Fatalf(`%s: Failed to shutdown server %v`, t.Name(), err) + } + return +} diff --git a/methods_test.go b/methods_test.go new file mode 100644 index 00000000..6d8f32db --- /dev/null +++ b/methods_test.go @@ -0,0 +1,109 @@ +package fiber + +import ( + "net/http" + "testing" +) + +func Test_Methods(t *testing.T) { + app := New() + app.Connect(func(c *Ctx) {}) + app.Put(func(c *Ctx) {}) + app.Post(func(c *Ctx) {}) + app.Delete(func(c *Ctx) {}) + app.Head(func(c *Ctx) {}) + app.Patch(func(c *Ctx) {}) + app.Options(func(c *Ctx) {}) + app.Trace(func(c *Ctx) {}) + app.Get(func(c *Ctx) {}) + app.All("/special", func(c *Ctx) {}) + app.Use("/special/john", func(c *Ctx) {}) + req, _ := http.NewRequest("CONNECT", "/", 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) + } + req, _ = http.NewRequest("PUT", "/", 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) + } + req, _ = http.NewRequest("POST", "/", 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) + } + req, _ = http.NewRequest("DELETE", "/", 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) + } + req, _ = http.NewRequest("HEAD", "/", 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) + } + req, _ = http.NewRequest("PATCH", "/", 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) + } + req, _ = http.NewRequest("OPTIONS", "/", 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) + } + req, _ = http.NewRequest("TRACE", "/", 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) + } + req, _ = http.NewRequest("GET", "/", 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) + } + req, _ = http.NewRequest("GET", "/special", 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) + } + req, _ = http.NewRequest("GET", "/special/john", 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) + } +} diff --git a/request_test.go b/request_test.go index 84280a91..45f09c2f 100644 --- a/request_test.go +++ b/request_test.go @@ -270,13 +270,7 @@ func Test_Get(t *testing.T) { if result != expect { t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result) } - expect = "Hello, World!" - c.Set("Accept-Charset", expect) - result = c.Get("Accept-Charset") - if result != expect { - t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result) - } - expect = "Cookie" + expect = "Monster" result = c.Get("referrer") if result != expect { t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result) @@ -284,7 +278,7 @@ func Test_Get(t *testing.T) { }) req, _ := http.NewRequest("GET", "/test", nil) req.Header.Set("Accept-Charset", "utf-8, iso-8859-1;q=0.5") - req.Header.Set("Referer", "Cookie") + req.Header.Set("Referer", "Monster") resp, err := app.Test(req) if err != nil { t.Fatalf(`%s: %s`, t.Name(), err) diff --git a/response.go b/response.go index 06d49663..4a71839f 100644 --- a/response.go +++ b/response.go @@ -24,7 +24,7 @@ func (ctx *Ctx) Append(field string, values ...string) { if len(values) == 0 { return } - h := ctx.Get(field) + h := getString(ctx.Fasthttp.Response.Header.Peek(field)) for i := range values { if h == "" { h += values[i] @@ -50,11 +50,12 @@ func (ctx *Ctx) Attachment(name ...string) { func (ctx *Ctx) ClearCookie(name ...string) { if len(name) > 0 { for i := range name { + //ctx.Fasthttp.Request.Header.DelAllCookies() ctx.Fasthttp.Response.Header.DelClientCookie(name[i]) } return } - + //ctx.Fasthttp.Response.Header.DelAllCookies() ctx.Fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) { ctx.Fasthttp.Response.Header.DelClientCookie(getString(k)) }) @@ -330,7 +331,6 @@ func (ctx *Ctx) SendString(body string) { // Set : https://gofiber.github.io/fiber/#/context?id=set func (ctx *Ctx) Set(key string, val string) { - ctx.Fasthttp.Request.Header.SetCanonical(getBytes(key), getBytes(val)) ctx.Fasthttp.Response.Header.SetCanonical(getBytes(key), getBytes(val)) } @@ -352,14 +352,16 @@ func (ctx *Ctx) Vary(fields ...string) { return } - vary := ctx.Get(fasthttp.HeaderVary) - for _, field := range fields { - if !strings.Contains(vary, field) { - vary += ", " + field + h := getString(ctx.Fasthttp.Response.Header.Peek(fasthttp.HeaderVary)) + for i := range fields { + if h == "" { + h += fields[i] + } else { + h += ", " + fields[i] } } - ctx.Set(fasthttp.HeaderVary, vary) + ctx.Set(fasthttp.HeaderVary, h) } // Write : https://gofiber.github.io/fiber/#/context?id=write diff --git a/response_test.go b/response_test.go index d677455e..abf1cc88 100644 --- a/response_test.go +++ b/response_test.go @@ -1,7 +1,9 @@ package fiber import ( + "io/ioutil" "net/http" + "strings" "testing" ) @@ -23,5 +25,543 @@ func Test_Append(t *testing.T) { t.Fatalf(`%s: Expecting %s`, t.Name(), "X-Test: hel, lo, world") } } +func Test_Attachment(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Attachment("./static/img/logo.png") + }) + 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) + } + if resp.Header.Get("Content-Disposition") != `attachment; filename="logo.png"` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `attachment; filename="logo.png"`) + } + if resp.Header.Get("Content-Type") != "image/png" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "image/png") + } +} +func Test_ClearCookie(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.ClearCookie() + }) + app.Get("/test2", func(c *Ctx) { + c.ClearCookie("john") + }) + req, _ := http.NewRequest("GET", "/test", nil) + req.AddCookie(&http.Cookie{Name: "john", Value: "doe"}) + 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) + } + if !strings.Contains(resp.Header.Get("Set-Cookie"), "expires=") { + t.Fatalf(`%s: Expecting %s`, t.Name(), "expires=") + } + req, _ = http.NewRequest("GET", "/test2", nil) + req.AddCookie(&http.Cookie{Name: "john", Value: "doe"}) + 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) + } + if !strings.Contains(resp.Header.Get("Set-Cookie"), "expires=") { + t.Fatalf(`%s: Expecting %s`, t.Name(), "expires=") + } +} +func Test_Cookie(t *testing.T) { + app := New() + 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) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + 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") + } +} +func Test_Download(t *testing.T) { + // TODO +} +func Test_Format(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Format("Hello, World!") + }) + app.Get("/test2", func(c *Ctx) { + c.Format("Hello, World!") + }) + req, _ := http.NewRequest("GET", "http://example.com/test", nil) + req.Header.Set("Accept", "text/html") + 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) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != "

Hello, World!

" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "

Hello, World!

") + } -// TODO: add all functions from response.go + req, _ = http.NewRequest("GET", "http://example.com/test2", nil) + req.Header.Set("Accept", "application/json") + 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) + } + body, err = ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `"Hello, World!"` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `"Hello, World!"`) + } +} +func Test_HeadersSent(t *testing.T) { + // TODO +} +func Test_JSON(t *testing.T) { + type SomeStruct struct { + Name string + Age uint8 + } + app := New() + app.Get("/test", func(c *Ctx) { + c.Json("") + data := SomeStruct{ + Name: "Grame", + Age: 20, + } + c.JSON(data) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Content-Type") != "application/json" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "application/json") + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `{"Name":"Grame","Age":20}` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `{"Name":"Grame","Age":20}`) + } +} +func Test_JSONBytes(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.JsonBytes([]byte("")) + c.JSONBytes([]byte(`{"Name":"Grame","Age":20}`)) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Content-Type") != "application/json" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "application/json") + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `{"Name":"Grame","Age":20}` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `{"Name":"Grame","Age":20}`) + } +} +func Test_JSONP(t *testing.T) { + type SomeStruct struct { + Name string + Age uint8 + } + app := New() + app.Get("/test", func(c *Ctx) { + c.Jsonp("") + data := SomeStruct{ + Name: "Grame", + Age: 20, + } + c.JSONP(data, "alwaysjohn") + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Content-Type") != "application/javascript" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "application/javascript") + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `alwaysjohn({"Name":"Grame","Age":20});` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `alwaysjohn({"Name":"Grame","Age":20});`) + } +} +func Test_JSONString(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.JsonString("") + c.JSONString(`{"Name":"Grame","Age":20}`) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Content-Type") != "application/json" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "application/json") + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `{"Name":"Grame","Age":20}` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `{"Name":"Grame","Age":20}`) + } +} +func Test_Links(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Links( + "http://api.example.com/users?page=2", "next", + "http://api.example.com/users?page=5", "last", + ) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Link") != `; rel="next",; rel="last"` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `Link: ; rel="next",; rel="last"`) + } +} +func Test_Location(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Location("http://example.com") + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Location") != "http://example.com" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "http://example.com") + } +} +func Test_Next(t *testing.T) { + app := New() + app.Use("/", func(c *Ctx) { + c.Next() + }) + app.Get("/test", func(c *Ctx) { + c.Set("X-Next-Result", "Works") + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("X-Next-Result") != "Works" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "X-Next-Results: Works") + } +} +func Test_Redirect(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Redirect("http://example.com", 301) + }) + req, _ := http.NewRequest("GET", "http://example.com/test", nil) + resp, err := app.Test(req) + if err != nil { + t.Fatalf(`%s: %s`, t.Name(), err) + } + if resp.StatusCode != 301 { + t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode) + } + if resp.Header.Get("Location") != "http://example.com" { + t.Fatalf(`%s: Expecting %s`, t.Name(), "Location: http://example.com") + } +} +func Test_Render(t *testing.T) { + // TODO +} +func Test_Send(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Send([]byte("Hello, World")) + c.Send("Don't crash please") + c.Send(1337) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `1337` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `1337`) + } +} +func Test_SendBytes(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.SendBytes([]byte("Hello, World")) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `Hello, World` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `Hello, World`) + } +} +func Test_SendStatus(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.SendStatus(415) + }) + req, _ := http.NewRequest("GET", "http://example.com/test", nil) + resp, err := app.Test(req) + if err != nil { + t.Fatalf(`%s: %s`, t.Name(), err) + } + if resp.StatusCode != 415 { + t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `Unsupported Media Type` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `Unsupported Media Type`) + } +} +func Test_SendString(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.SendString("Don't crash please") + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `Don't crash please` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `Don't crash please`) + } +} +func Test_Set(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Set("X-1", "1") + c.Set("X-2", "2") + c.Set("X-3", "3") + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("X-1") != "1" { + t.Fatalf(`%s: Expected %v`, t.Name(), "X-1: 1") + } + if resp.Header.Get("X-2") != "2" { + t.Fatalf(`%s: Expected %v`, t.Name(), "X-2: 2") + } + if resp.Header.Get("X-3") != "3" { + t.Fatalf(`%s: Expected %v`, t.Name(), "X-3: 3") + } +} +func Test_Status(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Status(400) + c.Status(415).Send("Hello, World") + }) + req, _ := http.NewRequest("GET", "http://example.com/test", nil) + resp, err := app.Test(req) + if err != nil { + t.Fatalf(`%s: %s`, t.Name(), err) + } + if resp.StatusCode != 415 { + t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `Hello, World` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `Hello, World`) + } +} +func Test_Type(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Type(".json") + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Content-Type") != "application/json" { + t.Fatalf(`%s: Expected %v`, t.Name(), `Content-Type: application/json`) + } +} +func Test_Vary(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Vary("Origin") + c.Vary("User-Agent") + c.Vary("Accept-Encoding", "Accept") + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Vary") != "Origin, User-Agent, Accept-Encoding, Accept" { + t.Fatalf(`%s: Expected %v`, t.Name(), `Vary: Origin, User-Agent, Accept-Encoding, Accept`) + } +} +func Test_Write(t *testing.T) { + app := New() + app.Get("/test", func(c *Ctx) { + c.Write("Hello, ") + c.Write([]byte("World! ")) + c.Write(123) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `Hello, World! 123` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `Hello, World! 123`) + } +} +func Test_XML(t *testing.T) { + type person struct { + Name string `xml:"name"` + Stars int `xml:"stars"` + } + app := New() + app.Get("/test", func(c *Ctx) { + c.Xml("") + c.XML(person{"John", 50}) + }) + req, _ := http.NewRequest("GET", "http://example.com/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) + } + if resp.Header.Get("Content-Type") != "application/xml" { + t.Fatalf(`%s: Expected %v`, t.Name(), "application/xml") + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != `John50` { + t.Fatalf(`%s: Expecting %s`, t.Name(), `John50`) + } +} diff --git a/static_test.go b/static_test.go new file mode 100644 index 00000000..1d674faa --- /dev/null +++ b/static_test.go @@ -0,0 +1,35 @@ +package fiber + +import ( + "net/http" + "testing" +) + +func Test_Static(t *testing.T) { + app := New() + app.Static("./middleware") + app.Static("/john", "./middleware") + app.Static("*", "./middleware/cors.go") + req, _ := http.NewRequest("GET", "/cors.go", 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) + } + if resp.Header.Get("Content-Length") == "" { + t.Fatalf(`%s: Missing Content-Length`, t.Name()) + } + req, _ = http.NewRequest("GET", "/john/cors.go", 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) + } + if resp.Header.Get("Content-Length") == "" { + t.Fatalf(`%s: Missing Content-Length`, t.Name()) + } +} diff --git a/utils.go b/utils.go index aa084385..3ac0f0e0 100644 --- a/utils.go +++ b/utils.go @@ -120,7 +120,7 @@ func (r *Fiber) Test(req *http.Request) (*http.Response, error) { return nil, err } // Setup a fiber server struct - server := r.setupServer() + r.httpServer = r.setupServer() // Create fake connection conn := &conn{} // Pass HTTP request to conn @@ -128,7 +128,7 @@ func (r *Fiber) Test(req *http.Request) (*http.Response, error) { // Serve conn to server channel := make(chan error) go func() { - channel <- server.ServeConn(conn) + channel <- r.httpServer.ServeConn(conn) }() // Wait for callback select { @@ -137,7 +137,7 @@ func (r *Fiber) Test(req *http.Request) (*http.Response, error) { return nil, err } // Throw timeout error after 200ms - case <-time.After(200 * time.Millisecond): + case <-time.After(500 * time.Millisecond): return nil, fmt.Errorf("Timeout") } // Get raw HTTP response