Skip to content

Commit fa8e46f

Browse files
authored
Merge pull request #196 from hanFengSan/master
support for range header
2 parents 23d73c4 + 34c5e46 commit fa8e46f

File tree

3 files changed

+69
-8
lines changed

3 files changed

+69
-8
lines changed

context.go

+49-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"mime/multipart"
1414
"net/url"
1515
"path/filepath"
16+
"strconv"
1617
"strings"
1718
"sync"
1819
"time"
@@ -36,6 +37,15 @@ type Ctx struct {
3637
Fasthttp *fasthttp.RequestCtx
3738
}
3839

40+
// RangeInfo info of range header
41+
type RangeInfo struct {
42+
Type string
43+
Ranges []struct {
44+
Start int64
45+
End int64
46+
}
47+
}
48+
3949
// Ctx pool
4050
var poolCtx = sync.Pool{
4151
New: func() interface{} {
@@ -548,11 +558,45 @@ func (ctx *Ctx) Query(key string) (value string) {
548558
}
549559

550560
// Range : https://fiber.wiki/context#range
551-
func (ctx *Ctx) Range() {
552-
// https://expressjs.com/en/api.html#req.range
553-
// https://github.com/jshttp/range-parser/blob/master/index.js
554-
// r := ctx.Fasthttp.Request.Header.Peek(HeaderRange)
555-
// *magic*
561+
func (ctx *Ctx) Range(size int64) (rangeInfo RangeInfo, err error) {
562+
rangeStr := string(ctx.Fasthttp.Request.Header.Peek("range"))
563+
if rangeStr == "" || !strings.Contains(rangeStr, "=") {
564+
return rangeInfo, fmt.Errorf("malformed range header string")
565+
}
566+
data := strings.Split(rangeStr, "=")
567+
rangeInfo.Type = data[0]
568+
arr := strings.Split(data[1], ",")
569+
for i := 0; i < len(arr); i++ {
570+
item := strings.Split(arr[i], "-")
571+
if len(item) == 1 {
572+
return rangeInfo, fmt.Errorf("malformed range header string")
573+
}
574+
start, startErr := strconv.ParseInt(item[0], 10, 64)
575+
end, endErr := strconv.ParseInt(item[1], 10, 64)
576+
if startErr != nil { // -nnn
577+
start = size - end
578+
end = size - 1
579+
} else if endErr != nil { // nnn-
580+
end = size - 1
581+
}
582+
if end > size-1 { // limit last-byte-pos to current length
583+
end = size - 1
584+
}
585+
if start > end || start < 0 {
586+
continue
587+
}
588+
rangeInfo.Ranges = append(rangeInfo.Ranges, struct {
589+
Start int64
590+
End int64
591+
}{
592+
start,
593+
end,
594+
})
595+
}
596+
if len(rangeInfo.Ranges) < 1 {
597+
return rangeInfo, fmt.Errorf("unsatisfiable range")
598+
}
599+
return rangeInfo, nil
556600
}
557601

558602
// Redirect : https://fiber.wiki/context#redirect

context_test.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -543,9 +543,26 @@ func Test_Query(t *testing.T) {
543543
func Test_Range(t *testing.T) {
544544
app := New()
545545
app.Get("/test", func(c *Ctx) {
546-
c.Range()
546+
result, err := c.Range(1000)
547+
if err != nil {
548+
t.Fatalf(`%s: %s`, t.Name(), err)
549+
return
550+
}
551+
expect := "bytes"
552+
if result.Type != expect {
553+
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result.Type)
554+
}
555+
expectNum := int64(500)
556+
if result.Ranges[0].Start != expectNum {
557+
t.Fatalf(`%s: Expecting %v, got %v`, t.Name(), expectNum, result.Ranges[0].Start)
558+
}
559+
expectNum = int64(700)
560+
if result.Ranges[0].End != expectNum {
561+
t.Fatalf(`%s: Expecting %v, got %v`, t.Name(), expectNum, result.Ranges[0].End)
562+
}
547563
})
548564
req, _ := http.NewRequest("GET", "/test", nil)
565+
req.Header.Set("range", "bytes=500-700")
549566
_, err := app.Test(req)
550567
if err != nil {
551568
t.Fatalf(`%s: %s`, t.Name(), err)

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ module github.com/gofiber/fiber
33
go 1.11
44

55
require (
6-
github.com/gorilla/schema v1.1.0
6+
github.com/fasthttp/websocket v1.4.2
77
github.com/gofiber/template v1.0.0
8+
github.com/gorilla/schema v1.1.0
89
github.com/json-iterator/go v1.1.9
910
github.com/valyala/fasthttp v1.9.0
10-
github.com/fasthttp/websocket v1.4.2
1111
)

0 commit comments

Comments
 (0)