Skip to content

Commit

Permalink
🧹 PR for 1.9.3 (#321)
Browse files Browse the repository at this point in the history
* Add crowdin

* Update media links

* Update README_de.md

* Update README_de.md

* Update README_de.md

* Add crowdin link

* Print addr when listening

* Print addr on listening

* Add DisableStartupMessage

* Fix typo

* Update Test_BodyParser

* Support ETags

* v1.9.3
  • Loading branch information
Fenny authored Apr 28, 2020
1 parent 86a9b05 commit 0419d08
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 52 deletions.
2 changes: 0 additions & 2 deletions .github/.gitpod.yml

This file was deleted.

1 change: 0 additions & 1 deletion .github/CNAME

This file was deleted.

44 changes: 24 additions & 20 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

// Version of current package
const Version = "1.9.2"
const Version = "1.9.3"

// Map is a shortcut for map[string]interface{}
type Map map[string]interface{}
Expand All @@ -48,6 +48,10 @@ type Settings struct {
ServerHeader string // default: ""
// Enables handler values to be immutable even if you return from handler
Immutable bool // default: false
// Enable or disable ETag header generation, since both weak and strong etags are generated
// using the same hashing method (CRC-32). Weak ETags are the default when enabled.
// Optional. Default value false
ETag bool
// Max body size that the server accepts
BodyLimit int // default: 4 * 1024 * 1024
// Maximum number of concurrent connections.
Expand Down Expand Up @@ -80,6 +84,25 @@ type Group struct {
app *App
}

// Static struct
type Static struct {
// Transparently compresses responses if set to true
// This works differently than the github.com/gofiber/compression middleware
// The server tries minimizing CPU usage by caching compressed files.
// It adds ".fiber.gz" suffix to the original file name.
// Optional. Default value false
Compress bool
// Enables byte range requests if set to true.
// Optional. Default value false
ByteRange bool
// Enable directory browsing.
// Optional. Default value false.
Browse bool
// Index file for serving a directory.
// Optional. Default value "index.html".
Index string
}

// New creates a new Fiber named instance.
// You can pass optional settings when creating a new instance.
func New(settings ...*Settings) *App {
Expand Down Expand Up @@ -125,25 +148,6 @@ func (app *App) Group(prefix string, handlers ...func(*Ctx)) *Group {
}
}

// Static struct
type Static struct {
// Transparently compresses responses if set to true
// This works differently than the github.com/gofiber/compression middleware
// The server tries minimizing CPU usage by caching compressed files.
// It adds ".fiber.gz" suffix to the original file name.
// Optional. Default value false
Compress bool
// Enables byte range requests if set to true.
// Optional. Default value false
ByteRange bool
// Enable directory browsing.
// Optional. Default value false.
Browse bool
// Index file for serving a directory.
// Optional. Default value "index.html".
Index string
}

// Static registers a new route with path prefix to serve static files from the provided root directory.
func (app *App) Static(prefix, root string, config ...Static) *App {
app.registerStatic(prefix, root, config...)
Expand Down
25 changes: 18 additions & 7 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ func is200(t *testing.T, app *App, url string, m ...string) {
}
}
func Test_Methods(t *testing.T) {
app := New()
app := New(&Settings{
DisableStartupMessage: true,
})

app.Connect("/:john?/:doe?", handler)
is200(t, app, "/", "CONNECT")
Expand Down Expand Up @@ -83,14 +85,18 @@ func Test_New(t *testing.T) {
}

func Test_Shutdown(t *testing.T) {
app := New()
app := New(&Settings{
DisableStartupMessage: true,
})
_ = app.Shutdown()
}

func Test_Static(t *testing.T) {
app := New()
app := New(&Settings{
DisableStartupMessage: true,
})
grp := app.Group("/v1")
grp.Static("/v2", ".travis.yml")
grp.Static("/v2", ".github/auth_assign.yml")
app.Static("/*", ".github/FUNDING.yml")
app.Static("/john", "./.github")
req, _ := http.NewRequest("GET", "/john/stale.yml", nil)
Expand Down Expand Up @@ -140,7 +146,9 @@ func Test_Static(t *testing.T) {
}

func Test_Group(t *testing.T) {
app := New()
app := New(&Settings{
DisableStartupMessage: true,
})

grp := app.Group("/test")
grp.Get("/", handler)
Expand Down Expand Up @@ -188,7 +196,9 @@ func Test_Group(t *testing.T) {
}

func Test_Listen(t *testing.T) {
app := New()
app := New(&Settings{
DisableStartupMessage: true,
})
go func() {
time.Sleep(500 * time.Millisecond)
_ = app.Shutdown()
Expand All @@ -203,7 +213,8 @@ func Test_Listen(t *testing.T) {

func Test_Serve(t *testing.T) {
app := New(&Settings{
Prefork: true,
DisableStartupMessage: true,
Prefork: true,
})
ln, err := net.Listen("tcp4", ":3004")
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,11 @@ func (ctx *Ctx) FormValue(key string) (value string) {
return getString(ctx.Fasthttp.FormValue(key))
}

// Fresh is not implemented yet, pull requests are welcome!
// Fresh When the response is still “fresh” in the client’s cache true is returned,
// otherwise false is returned to indicate that the client cache is now stale
// and the full response should be sent.
// When a client sends the Cache-Control: no-cache request header to indicate an end-to-end
// reload request, this module will return false to make handling these requests transparent.
// https://github.com/jshttp/fresh/blob/10e0471669dbbfbfd8de65bc6efac2ddd0bfa057/index.js#L33
func (ctx *Ctx) Fresh() bool {
// fields
Expand Down Expand Up @@ -545,7 +549,6 @@ func (ctx *Ctx) JSONP(data interface{}, callback ...string) error {
ctx.Set(HeaderXContentTypeOptions, "nosniff")
ctx.Fasthttp.Response.Header.SetContentType(MIMEApplicationJavaScript)
ctx.Fasthttp.Response.SetBodyString(str)

return nil
}

Expand Down
46 changes: 26 additions & 20 deletions ctx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import (
)

func Test_Accepts(t *testing.T) {
app := New()
app := New(&Settings{
DisableStartupMessage: true,
})
app.Get("/test", func(c *Ctx) {
expect := ""
result := c.Accepts(expect)
Expand Down Expand Up @@ -155,16 +157,33 @@ func Test_BodyParser(t *testing.T) {
type Demo struct {
Name string `json:"name" xml:"name" form:"name" query:"name"`
}
type Query struct {
ID int
Name string
Hobby []string
}
app.Post("/test", func(c *Ctx) {
d := new(Demo)
err := c.BodyParser(d)
if err != nil {
t.Fatalf(`%s: BodyParser %v`, t.Name(), err)
}
if d.Name != "john" {
t.Fatalf(`%s: Expect %s got %s`, t.Name(), "john", d)
t.Fatalf(`%s: Expect %s got %v`, t.Name(), "john", d)
}
})

app.Get("/query", func(c *Ctx) {
d := new(Query)
err := c.BodyParser(d)
if err != nil {
t.Fatalf(`%s: BodyParser %v`, t.Name(), err)
}
if len(d.Hobby) != 2 {
t.Fatalf(`%s: Expect length %d got %v`, t.Name(), 2, d)
}
})

req := httptest.NewRequest("POST", "/test", bytes.NewBuffer([]byte(`{"name":"john"}`)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Content-Length", strconv.Itoa(len([]byte(`{"name":"john"}`))))
Expand All @@ -174,25 +193,12 @@ func Test_BodyParser(t *testing.T) {
t.Fatalf(`%s: %s`, t.Name(), err)
}

// data := url.Values{}
// data.Set("name", "john")
// req = httptest.NewRequest("POST", "/test", strings.NewReader(data.Encode()))
// req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
// req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

// _, err = app.Test(req)
// if err != nil {
// t.Fatalf(`%s: %s`, t.Name(), err)
// }
req = httptest.NewRequest("GET", "/query?id=1&name=tom&hobby=basketball&hobby=football", nil)

// req = httptest.NewRequest("POST", "/test", bytes.NewBuffer([]byte(`<name>john</name>`)))
// req.Header.Set("Content-Type", "application/xml")
// req.Header.Set("Content-Length", strconv.Itoa(len([]byte(`<name>john</name>`))))

// _, err = app.Test(req)
// if err != nil {
// t.Fatalf(`%s: %s`, t.Name(), err)
// }
_, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
}
func Test_Cookies(t *testing.T) {
app := New()
Expand Down
5 changes: 5 additions & 0 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@ func (app *App) nextRoute(ctx *Ctx) {
ctx.route = route
ctx.values = values
route.Handler(ctx)
// Generate ETag if enabled / found
if app.Settings.ETag {
setETag(ctx, ctx.Fasthttp.Response.Body(), false)
}
return
}
}
// Send a 404
if len(ctx.Fasthttp.Response.Body()) == 0 {
ctx.SendStatus(404)
}
Expand Down
42 changes: 42 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package fiber
import (
"bytes"
"fmt"
"hash/crc32"
"net"
"os"
"path/filepath"
Expand All @@ -16,6 +17,47 @@ import (
"unsafe"
)

// Document elke line gelijk even
func setETag(ctx *Ctx, body []byte, weak bool) {
// Skips ETag if no response body is present
if len(body) <= 0 {
return
}
// Get ETag header from request
clientEtag := ctx.Get("If-None-Match")

// Generate ETag for response
crc32q := crc32.MakeTable(0xD5828281)
etag := fmt.Sprintf("\"%d-%v\"", len(body), crc32.Checksum(body, crc32q))

// Enable weak tag
if weak {
etag = "W/" + "\"" + etag + "\""
}

// Check if client's ETag is weak
if strings.HasPrefix(clientEtag, "W/") {
// Check if server's ETag is weak
if clientEtag[2:] == etag || clientEtag[2:] == etag[2:] {
// W/1 == 1 || W/1 == W/1
ctx.SendStatus(304)
ctx.Fasthttp.ResetBody()
return
}
// W/1 != W/2 || W/1 != 2
ctx.Set("ETag", etag)
return
}
if strings.Contains(clientEtag, etag) {
// 1 == 1
ctx.SendStatus(304)
ctx.Fasthttp.ResetBody()
return
}
// 1 != 2
ctx.Set("ETag", etag)
}

func groupPaths(prefix, path string) string {
if path == "/" {
path = ""
Expand Down

0 comments on commit 0419d08

Please sign in to comment.