Skip to content

Commit 0419d08

Browse files
authored
🧹 PR for 1.9.3 (#321)
* 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
1 parent 86a9b05 commit 0419d08

File tree

8 files changed

+120
-52
lines changed

8 files changed

+120
-52
lines changed

.github/.gitpod.yml

-2
This file was deleted.

.github/CNAME

-1
This file was deleted.

app.go

+24-20
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
)
2525

2626
// Version of current package
27-
const Version = "1.9.2"
27+
const Version = "1.9.3"
2828

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

87+
// Static struct
88+
type Static struct {
89+
// Transparently compresses responses if set to true
90+
// This works differently than the github.com/gofiber/compression middleware
91+
// The server tries minimizing CPU usage by caching compressed files.
92+
// It adds ".fiber.gz" suffix to the original file name.
93+
// Optional. Default value false
94+
Compress bool
95+
// Enables byte range requests if set to true.
96+
// Optional. Default value false
97+
ByteRange bool
98+
// Enable directory browsing.
99+
// Optional. Default value false.
100+
Browse bool
101+
// Index file for serving a directory.
102+
// Optional. Default value "index.html".
103+
Index string
104+
}
105+
83106
// New creates a new Fiber named instance.
84107
// You can pass optional settings when creating a new instance.
85108
func New(settings ...*Settings) *App {
@@ -125,25 +148,6 @@ func (app *App) Group(prefix string, handlers ...func(*Ctx)) *Group {
125148
}
126149
}
127150

128-
// Static struct
129-
type Static struct {
130-
// Transparently compresses responses if set to true
131-
// This works differently than the github.com/gofiber/compression middleware
132-
// The server tries minimizing CPU usage by caching compressed files.
133-
// It adds ".fiber.gz" suffix to the original file name.
134-
// Optional. Default value false
135-
Compress bool
136-
// Enables byte range requests if set to true.
137-
// Optional. Default value false
138-
ByteRange bool
139-
// Enable directory browsing.
140-
// Optional. Default value false.
141-
Browse bool
142-
// Index file for serving a directory.
143-
// Optional. Default value "index.html".
144-
Index string
145-
}
146-
147151
// Static registers a new route with path prefix to serve static files from the provided root directory.
148152
func (app *App) Static(prefix, root string, config ...Static) *App {
149153
app.registerStatic(prefix, root, config...)

app_test.go

+18-7
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ func is200(t *testing.T, app *App, url string, m ...string) {
3333
}
3434
}
3535
func Test_Methods(t *testing.T) {
36-
app := New()
36+
app := New(&Settings{
37+
DisableStartupMessage: true,
38+
})
3739

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

8587
func Test_Shutdown(t *testing.T) {
86-
app := New()
88+
app := New(&Settings{
89+
DisableStartupMessage: true,
90+
})
8791
_ = app.Shutdown()
8892
}
8993

9094
func Test_Static(t *testing.T) {
91-
app := New()
95+
app := New(&Settings{
96+
DisableStartupMessage: true,
97+
})
9298
grp := app.Group("/v1")
93-
grp.Static("/v2", ".travis.yml")
99+
grp.Static("/v2", ".github/auth_assign.yml")
94100
app.Static("/*", ".github/FUNDING.yml")
95101
app.Static("/john", "./.github")
96102
req, _ := http.NewRequest("GET", "/john/stale.yml", nil)
@@ -140,7 +146,9 @@ func Test_Static(t *testing.T) {
140146
}
141147

142148
func Test_Group(t *testing.T) {
143-
app := New()
149+
app := New(&Settings{
150+
DisableStartupMessage: true,
151+
})
144152

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

190198
func Test_Listen(t *testing.T) {
191-
app := New()
199+
app := New(&Settings{
200+
DisableStartupMessage: true,
201+
})
192202
go func() {
193203
time.Sleep(500 * time.Millisecond)
194204
_ = app.Shutdown()
@@ -203,7 +213,8 @@ func Test_Listen(t *testing.T) {
203213

204214
func Test_Serve(t *testing.T) {
205215
app := New(&Settings{
206-
Prefork: true,
216+
DisableStartupMessage: true,
217+
Prefork: true,
207218
})
208219
ln, err := net.Listen("tcp4", ":3004")
209220
if err != nil {

ctx.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,11 @@ func (ctx *Ctx) FormValue(key string) (value string) {
409409
return getString(ctx.Fasthttp.FormValue(key))
410410
}
411411

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

ctx_test.go

+26-20
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
)
2222

2323
func Test_Accepts(t *testing.T) {
24-
app := New()
24+
app := New(&Settings{
25+
DisableStartupMessage: true,
26+
})
2527
app.Get("/test", func(c *Ctx) {
2628
expect := ""
2729
result := c.Accepts(expect)
@@ -155,16 +157,33 @@ func Test_BodyParser(t *testing.T) {
155157
type Demo struct {
156158
Name string `json:"name" xml:"name" form:"name" query:"name"`
157159
}
160+
type Query struct {
161+
ID int
162+
Name string
163+
Hobby []string
164+
}
158165
app.Post("/test", func(c *Ctx) {
159166
d := new(Demo)
160167
err := c.BodyParser(d)
161168
if err != nil {
162169
t.Fatalf(`%s: BodyParser %v`, t.Name(), err)
163170
}
164171
if d.Name != "john" {
165-
t.Fatalf(`%s: Expect %s got %s`, t.Name(), "john", d)
172+
t.Fatalf(`%s: Expect %s got %v`, t.Name(), "john", d)
173+
}
174+
})
175+
176+
app.Get("/query", func(c *Ctx) {
177+
d := new(Query)
178+
err := c.BodyParser(d)
179+
if err != nil {
180+
t.Fatalf(`%s: BodyParser %v`, t.Name(), err)
181+
}
182+
if len(d.Hobby) != 2 {
183+
t.Fatalf(`%s: Expect length %d got %v`, t.Name(), 2, d)
166184
}
167185
})
186+
168187
req := httptest.NewRequest("POST", "/test", bytes.NewBuffer([]byte(`{"name":"john"}`)))
169188
req.Header.Set("Content-Type", "application/json")
170189
req.Header.Set("Content-Length", strconv.Itoa(len([]byte(`{"name":"john"}`))))
@@ -174,25 +193,12 @@ func Test_BodyParser(t *testing.T) {
174193
t.Fatalf(`%s: %s`, t.Name(), err)
175194
}
176195

177-
// data := url.Values{}
178-
// data.Set("name", "john")
179-
// req = httptest.NewRequest("POST", "/test", strings.NewReader(data.Encode()))
180-
// req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
181-
// req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
182-
183-
// _, err = app.Test(req)
184-
// if err != nil {
185-
// t.Fatalf(`%s: %s`, t.Name(), err)
186-
// }
196+
req = httptest.NewRequest("GET", "/query?id=1&name=tom&hobby=basketball&hobby=football", nil)
187197

188-
// req = httptest.NewRequest("POST", "/test", bytes.NewBuffer([]byte(`<name>john</name>`)))
189-
// req.Header.Set("Content-Type", "application/xml")
190-
// req.Header.Set("Content-Length", strconv.Itoa(len([]byte(`<name>john</name>`))))
191-
192-
// _, err = app.Test(req)
193-
// if err != nil {
194-
// t.Fatalf(`%s: %s`, t.Name(), err)
195-
// }
198+
_, err = app.Test(req)
199+
if err != nil {
200+
t.Fatalf(`%s: %s`, t.Name(), err)
201+
}
196202
}
197203
func Test_Cookies(t *testing.T) {
198204
app := New()

router.go

+5
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@ func (app *App) nextRoute(ctx *Ctx) {
4242
ctx.route = route
4343
ctx.values = values
4444
route.Handler(ctx)
45+
// Generate ETag if enabled / found
46+
if app.Settings.ETag {
47+
setETag(ctx, ctx.Fasthttp.Response.Body(), false)
48+
}
4549
return
4650
}
4751
}
52+
// Send a 404
4853
if len(ctx.Fasthttp.Response.Body()) == 0 {
4954
ctx.SendStatus(404)
5055
}

utils.go

+42
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package fiber
77
import (
88
"bytes"
99
"fmt"
10+
"hash/crc32"
1011
"net"
1112
"os"
1213
"path/filepath"
@@ -16,6 +17,47 @@ import (
1617
"unsafe"
1718
)
1819

20+
// Document elke line gelijk even
21+
func setETag(ctx *Ctx, body []byte, weak bool) {
22+
// Skips ETag if no response body is present
23+
if len(body) <= 0 {
24+
return
25+
}
26+
// Get ETag header from request
27+
clientEtag := ctx.Get("If-None-Match")
28+
29+
// Generate ETag for response
30+
crc32q := crc32.MakeTable(0xD5828281)
31+
etag := fmt.Sprintf("\"%d-%v\"", len(body), crc32.Checksum(body, crc32q))
32+
33+
// Enable weak tag
34+
if weak {
35+
etag = "W/" + "\"" + etag + "\""
36+
}
37+
38+
// Check if client's ETag is weak
39+
if strings.HasPrefix(clientEtag, "W/") {
40+
// Check if server's ETag is weak
41+
if clientEtag[2:] == etag || clientEtag[2:] == etag[2:] {
42+
// W/1 == 1 || W/1 == W/1
43+
ctx.SendStatus(304)
44+
ctx.Fasthttp.ResetBody()
45+
return
46+
}
47+
// W/1 != W/2 || W/1 != 2
48+
ctx.Set("ETag", etag)
49+
return
50+
}
51+
if strings.Contains(clientEtag, etag) {
52+
// 1 == 1
53+
ctx.SendStatus(304)
54+
ctx.Fasthttp.ResetBody()
55+
return
56+
}
57+
// 1 != 2
58+
ctx.Set("ETag", etag)
59+
}
60+
1961
func groupPaths(prefix, path string) string {
2062
if path == "/" {
2163
path = ""

0 commit comments

Comments
 (0)