From bfa0cab89288e3a33be21b5386faff2019eafb3c Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Sat, 29 Feb 2020 21:00:54 +0800 Subject: [PATCH 1/2] support for range header --- context.go | 54 ++++++++++++++++++++++++++++++++++++++++++++----- context_test.go | 19 ++++++++++++++++- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/context.go b/context.go index 292e7f9f..d01e3e98 100644 --- a/context.go +++ b/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.Index(rangeStr, "=") < 0 { + 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 diff --git a/context_test.go b/context_test.go index 5b60b02b..7be23278 100644 --- a/context_test.go +++ b/context_test.go @@ -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) From 34c5e46fd0a6c6c11d1b08f05b8f363b6a527577 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Sat, 29 Feb 2020 21:12:17 +0800 Subject: [PATCH 2/2] improve code --- context.go | 2 +- go.mod | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/context.go b/context.go index d01e3e98..ab05336e 100644 --- a/context.go +++ b/context.go @@ -560,7 +560,7 @@ func (ctx *Ctx) Query(key string) (value string) { // Range : https://fiber.wiki/context#range func (ctx *Ctx) Range(size int64) (rangeInfo RangeInfo, err error) { rangeStr := string(ctx.Fasthttp.Request.Header.Peek("range")) - if rangeStr == "" || strings.Index(rangeStr, "=") < 0 { + if rangeStr == "" || !strings.Contains(rangeStr, "=") { return rangeInfo, fmt.Errorf("malformed range header string") } data := strings.Split(rangeStr, "=") diff --git a/go.mod b/go.mod index a8b89739..61666dda 100644 --- a/go.mod +++ b/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 )