| 5226 | } |
| 5227 | |
| 5228 | func Test_Ctx_Range_SuffixNormalization(t *testing.T) { |
| 5229 | t.Parallel() |
| 5230 | |
| 5231 | body := bytes.Repeat([]byte("x"), 123) |
| 5232 | |
| 5233 | newApp := func() *App { |
| 5234 | app := New() |
| 5235 | |
| 5236 | app.Get("/", func(c Ctx) error { |
| 5237 | rangesHeader := c.Get(HeaderRange) |
| 5238 | if rangesHeader == "" { |
| 5239 | return c.Send(body) |
| 5240 | } |
| 5241 | |
| 5242 | rangeData, err := c.Range(int64(len(body))) |
| 5243 | if err != nil { |
| 5244 | return err |
| 5245 | } |
| 5246 | |
| 5247 | if len(rangeData.Ranges) != 1 { |
| 5248 | c.Status(StatusRequestedRangeNotSatisfiable) |
| 5249 | c.Set(HeaderContentRange, fmt.Sprintf("bytes */%d", len(body))) |
| 5250 | return ErrRequestedRangeNotSatisfiable |
| 5251 | } |
| 5252 | |
| 5253 | currentRange := rangeData.Ranges[0] |
| 5254 | contentRange := fmt.Sprintf("bytes %d-%d/%d", currentRange.Start, currentRange.End, len(body)) |
| 5255 | c.Set(HeaderContentRange, contentRange) |
| 5256 | |
| 5257 | statusCode := StatusPartialContent |
| 5258 | if currentRange.Start == 0 && currentRange.End == int64(len(body))-1 { |
| 5259 | statusCode = StatusOK |
| 5260 | } |
| 5261 | |
| 5262 | c.Status(statusCode) |
| 5263 | return c.Send(body[currentRange.Start : currentRange.End+1]) |
| 5264 | }) |
| 5265 | |
| 5266 | return app |
| 5267 | } |
| 5268 | |
| 5269 | testCases := []struct { |
| 5270 | name string |
| 5271 | rangeHeader string |
| 5272 | contentRange string |
| 5273 | statusCode int |
| 5274 | expectedBodySize int |
| 5275 | }{ |
| 5276 | { |
| 5277 | name: "suffix less than size", |
| 5278 | rangeHeader: "bytes=-20", |
| 5279 | contentRange: "bytes 103-122/123", |
| 5280 | statusCode: StatusPartialContent, |
| 5281 | expectedBodySize: 20, |
| 5282 | }, |
| 5283 | { |
| 5284 | name: "suffix equal to size", |
| 5285 | rangeHeader: "bytes=-123", |