mirror of
https://github.com/gofiber/fiber.git
synced 2025-05-31 11:52:41 +00:00
Merge pull request #196 from hanFengSan/master
support for range header
This commit is contained in:
commit
fa8e46f0a8
54
context.go
54
context.go
@ -13,6 +13,7 @@ import (
|
||||
"mime/multipart"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -36,6 +37,15 @@ type Ctx struct {
|
||||
Fasthttp *fasthttp.RequestCtx
|
||||
}
|
||||
|
||||
// RangeInfo info of range header
|
||||
type RangeInfo struct {
|
||||
Type string
|
||||
Ranges []struct {
|
||||
Start int64
|
||||
End int64
|
||||
}
|
||||
}
|
||||
|
||||
// Ctx pool
|
||||
var poolCtx = sync.Pool{
|
||||
New: func() interface{} {
|
||||
@ -548,11 +558,45 @@ func (ctx *Ctx) Query(key string) (value string) {
|
||||
}
|
||||
|
||||
// Range : https://fiber.wiki/context#range
|
||||
func (ctx *Ctx) Range() {
|
||||
// https://expressjs.com/en/api.html#req.range
|
||||
// https://github.com/jshttp/range-parser/blob/master/index.js
|
||||
// r := ctx.Fasthttp.Request.Header.Peek(HeaderRange)
|
||||
// *magic*
|
||||
func (ctx *Ctx) Range(size int64) (rangeInfo RangeInfo, err error) {
|
||||
rangeStr := string(ctx.Fasthttp.Request.Header.Peek("range"))
|
||||
if rangeStr == "" || !strings.Contains(rangeStr, "=") {
|
||||
return rangeInfo, fmt.Errorf("malformed range header string")
|
||||
}
|
||||
data := strings.Split(rangeStr, "=")
|
||||
rangeInfo.Type = data[0]
|
||||
arr := strings.Split(data[1], ",")
|
||||
for i := 0; i < len(arr); i++ {
|
||||
item := strings.Split(arr[i], "-")
|
||||
if len(item) == 1 {
|
||||
return rangeInfo, fmt.Errorf("malformed range header string")
|
||||
}
|
||||
start, startErr := strconv.ParseInt(item[0], 10, 64)
|
||||
end, endErr := strconv.ParseInt(item[1], 10, 64)
|
||||
if startErr != nil { // -nnn
|
||||
start = size - end
|
||||
end = size - 1
|
||||
} else if endErr != nil { // nnn-
|
||||
end = size - 1
|
||||
}
|
||||
if end > size-1 { // limit last-byte-pos to current length
|
||||
end = size - 1
|
||||
}
|
||||
if start > end || start < 0 {
|
||||
continue
|
||||
}
|
||||
rangeInfo.Ranges = append(rangeInfo.Ranges, struct {
|
||||
Start int64
|
||||
End int64
|
||||
}{
|
||||
start,
|
||||
end,
|
||||
})
|
||||
}
|
||||
if len(rangeInfo.Ranges) < 1 {
|
||||
return rangeInfo, fmt.Errorf("unsatisfiable range")
|
||||
}
|
||||
return rangeInfo, nil
|
||||
}
|
||||
|
||||
// Redirect : https://fiber.wiki/context#redirect
|
||||
|
@ -543,9 +543,26 @@ func Test_Query(t *testing.T) {
|
||||
func Test_Range(t *testing.T) {
|
||||
app := New()
|
||||
app.Get("/test", func(c *Ctx) {
|
||||
c.Range()
|
||||
result, err := c.Range(1000)
|
||||
if err != nil {
|
||||
t.Fatalf(`%s: %s`, t.Name(), err)
|
||||
return
|
||||
}
|
||||
expect := "bytes"
|
||||
if result.Type != expect {
|
||||
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result.Type)
|
||||
}
|
||||
expectNum := int64(500)
|
||||
if result.Ranges[0].Start != expectNum {
|
||||
t.Fatalf(`%s: Expecting %v, got %v`, t.Name(), expectNum, result.Ranges[0].Start)
|
||||
}
|
||||
expectNum = int64(700)
|
||||
if result.Ranges[0].End != expectNum {
|
||||
t.Fatalf(`%s: Expecting %v, got %v`, t.Name(), expectNum, result.Ranges[0].End)
|
||||
}
|
||||
})
|
||||
req, _ := http.NewRequest("GET", "/test", nil)
|
||||
req.Header.Set("range", "bytes=500-700")
|
||||
_, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf(`%s: %s`, t.Name(), err)
|
||||
|
4
go.mod
4
go.mod
@ -3,9 +3,9 @@ module github.com/gofiber/fiber
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
github.com/gorilla/schema v1.1.0
|
||||
github.com/fasthttp/websocket v1.4.2
|
||||
github.com/gofiber/template v1.0.0
|
||||
github.com/gorilla/schema v1.1.0
|
||||
github.com/json-iterator/go v1.1.9
|
||||
github.com/valyala/fasthttp v1.9.0
|
||||
github.com/fasthttp/websocket v1.4.2
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user