mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-29 09:19:57 +00:00
TUN-528: Move cloudflared into a separate repo
This commit is contained in:
104
vendor/github.com/mholt/caddy/caddyhttp/limits/handler.go
generated
vendored
Normal file
104
vendor/github.com/mholt/caddy/caddyhttp/limits/handler.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2015 Light Code Labs, LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package limits
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/mholt/caddy/caddyhttp/httpserver"
|
||||
)
|
||||
|
||||
// Limit is a middleware to control request body size
|
||||
type Limit struct {
|
||||
Next httpserver.Handler
|
||||
BodyLimits []httpserver.PathLimit
|
||||
}
|
||||
|
||||
func (l Limit) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
if r.Body == nil {
|
||||
return l.Next.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// apply the path-based request body size limit.
|
||||
for _, bl := range l.BodyLimits {
|
||||
if httpserver.Path(r.URL.Path).Matches(bl.Path) {
|
||||
r.Body = MaxBytesReader(w, r.Body, bl.Limit)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return l.Next.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// MaxBytesReader and its associated methods are borrowed from the
|
||||
// Go Standard library (comments intact). The only difference is that
|
||||
// it returns a ErrMaxBytesExceeded error instead of a generic error message
|
||||
// when the request body has exceeded the requested limit
|
||||
func MaxBytesReader(w http.ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
|
||||
return &maxBytesReader{w: w, r: r, n: n}
|
||||
}
|
||||
|
||||
type maxBytesReader struct {
|
||||
w http.ResponseWriter
|
||||
r io.ReadCloser // underlying reader
|
||||
n int64 // max bytes remaining
|
||||
err error // sticky error
|
||||
}
|
||||
|
||||
func (l *maxBytesReader) Read(p []byte) (n int, err error) {
|
||||
if l.err != nil {
|
||||
return 0, l.err
|
||||
}
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
// If they asked for a 32KB byte read but only 5 bytes are
|
||||
// remaining, no need to read 32KB. 6 bytes will answer the
|
||||
// question of the whether we hit the limit or go past it.
|
||||
if int64(len(p)) > l.n+1 {
|
||||
p = p[:l.n+1]
|
||||
}
|
||||
n, err = l.r.Read(p)
|
||||
|
||||
if int64(n) <= l.n {
|
||||
l.n -= int64(n)
|
||||
l.err = err
|
||||
return n, err
|
||||
}
|
||||
|
||||
n = int(l.n)
|
||||
l.n = 0
|
||||
|
||||
// The server code and client code both use
|
||||
// maxBytesReader. This "requestTooLarge" check is
|
||||
// only used by the server code. To prevent binaries
|
||||
// which only using the HTTP Client code (such as
|
||||
// cmd/go) from also linking in the HTTP server, don't
|
||||
// use a static type assertion to the server
|
||||
// "*response" type. Check this interface instead:
|
||||
type requestTooLarger interface {
|
||||
requestTooLarge()
|
||||
}
|
||||
if res, ok := l.w.(requestTooLarger); ok {
|
||||
res.requestTooLarge()
|
||||
}
|
||||
l.err = httpserver.ErrMaxBytesExceeded
|
||||
return n, l.err
|
||||
}
|
||||
|
||||
func (l *maxBytesReader) Close() error {
|
||||
return l.r.Close()
|
||||
}
|
49
vendor/github.com/mholt/caddy/caddyhttp/limits/handler_test.go
generated
vendored
Normal file
49
vendor/github.com/mholt/caddy/caddyhttp/limits/handler_test.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2015 Light Code Labs, LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package limits
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mholt/caddy/caddyhttp/httpserver"
|
||||
)
|
||||
|
||||
func TestBodySizeLimit(t *testing.T) {
|
||||
var (
|
||||
gotContent []byte
|
||||
gotError error
|
||||
expectContent = "hello"
|
||||
)
|
||||
l := Limit{
|
||||
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
gotContent, gotError = ioutil.ReadAll(r.Body)
|
||||
return 0, nil
|
||||
}),
|
||||
BodyLimits: []httpserver.PathLimit{{Path: "/", Limit: int64(len(expectContent))}},
|
||||
}
|
||||
|
||||
r := httptest.NewRequest("GET", "/", strings.NewReader(expectContent+expectContent))
|
||||
l.ServeHTTP(httptest.NewRecorder(), r)
|
||||
if got := string(gotContent); got != expectContent {
|
||||
t.Errorf("expected content[%s], got[%s]", expectContent, got)
|
||||
}
|
||||
if gotError != httpserver.ErrMaxBytesExceeded {
|
||||
t.Errorf("expect error %v, got %v", httpserver.ErrMaxBytesExceeded, gotError)
|
||||
}
|
||||
}
|
233
vendor/github.com/mholt/caddy/caddyhttp/limits/setup.go
generated
vendored
Normal file
233
vendor/github.com/mholt/caddy/caddyhttp/limits/setup.go
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
// Copyright 2015 Light Code Labs, LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package limits
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/mholt/caddy"
|
||||
"github.com/mholt/caddy/caddyhttp/httpserver"
|
||||
)
|
||||
|
||||
const (
|
||||
serverType = "http"
|
||||
pluginName = "limits"
|
||||
)
|
||||
|
||||
func init() {
|
||||
caddy.RegisterPlugin(pluginName, caddy.Plugin{
|
||||
ServerType: serverType,
|
||||
Action: setupLimits,
|
||||
})
|
||||
}
|
||||
|
||||
// pathLimitUnparsed is a PathLimit before it's parsed
|
||||
type pathLimitUnparsed struct {
|
||||
Path string
|
||||
Limit string
|
||||
}
|
||||
|
||||
func setupLimits(c *caddy.Controller) error {
|
||||
bls, err := parseLimits(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
||||
return Limit{Next: next, BodyLimits: bls}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseLimits(c *caddy.Controller) ([]httpserver.PathLimit, error) {
|
||||
config := httpserver.GetConfig(c)
|
||||
|
||||
if !c.Next() {
|
||||
return nil, c.ArgErr()
|
||||
}
|
||||
|
||||
args := c.RemainingArgs()
|
||||
argList := []pathLimitUnparsed{}
|
||||
headerLimit := ""
|
||||
|
||||
switch len(args) {
|
||||
case 0:
|
||||
// Format: limits {
|
||||
// header <limit>
|
||||
// body <path> <limit>
|
||||
// body <limit>
|
||||
// ...
|
||||
// }
|
||||
for c.NextBlock() {
|
||||
kind := c.Val()
|
||||
pathOrLimit := c.RemainingArgs()
|
||||
switch kind {
|
||||
case "header":
|
||||
if len(pathOrLimit) != 1 {
|
||||
return nil, c.ArgErr()
|
||||
}
|
||||
headerLimit = pathOrLimit[0]
|
||||
case "body":
|
||||
if len(pathOrLimit) == 1 {
|
||||
argList = append(argList, pathLimitUnparsed{
|
||||
Path: "/",
|
||||
Limit: pathOrLimit[0],
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
if len(pathOrLimit) == 2 {
|
||||
argList = append(argList, pathLimitUnparsed{
|
||||
Path: pathOrLimit[0],
|
||||
Limit: pathOrLimit[1],
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
fallthrough
|
||||
default:
|
||||
return nil, c.ArgErr()
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
// Format: limits <limit>
|
||||
headerLimit = args[0]
|
||||
argList = []pathLimitUnparsed{{
|
||||
Path: "/",
|
||||
Limit: args[0],
|
||||
}}
|
||||
default:
|
||||
return nil, c.ArgErr()
|
||||
}
|
||||
|
||||
if headerLimit != "" {
|
||||
size := parseSize(headerLimit)
|
||||
if size < 1 { // also disallow size = 0
|
||||
return nil, c.ArgErr()
|
||||
}
|
||||
config.Limits.MaxRequestHeaderSize = size
|
||||
}
|
||||
|
||||
if len(argList) > 0 {
|
||||
pathLimit, err := parseArguments(argList)
|
||||
if err != nil {
|
||||
return nil, c.ArgErr()
|
||||
}
|
||||
SortPathLimits(pathLimit)
|
||||
config.Limits.MaxRequestBodySizes = pathLimit
|
||||
}
|
||||
|
||||
return config.Limits.MaxRequestBodySizes, nil
|
||||
}
|
||||
|
||||
func parseArguments(args []pathLimitUnparsed) ([]httpserver.PathLimit, error) {
|
||||
pathLimit := []httpserver.PathLimit{}
|
||||
|
||||
for _, pair := range args {
|
||||
size := parseSize(pair.Limit)
|
||||
if size < 1 { // also disallow size = 0
|
||||
return pathLimit, errors.New("Parse failed")
|
||||
}
|
||||
pathLimit = addPathLimit(pathLimit, pair.Path, size)
|
||||
}
|
||||
return pathLimit, nil
|
||||
}
|
||||
|
||||
var validUnits = []struct {
|
||||
symbol string
|
||||
multiplier int64
|
||||
}{
|
||||
{"KB", 1024},
|
||||
{"MB", 1024 * 1024},
|
||||
{"GB", 1024 * 1024 * 1024},
|
||||
{"B", 1},
|
||||
{"", 1}, // defaulting to "B"
|
||||
}
|
||||
|
||||
// parseSize parses the given string as size limit
|
||||
// Size are positive numbers followed by a unit (case insensitive)
|
||||
// Allowed units: "B" (bytes), "KB" (kilo), "MB" (mega), "GB" (giga)
|
||||
// If the unit is omitted, "b" is assumed
|
||||
// Returns the parsed size in bytes, or -1 if cannot parse
|
||||
func parseSize(sizeStr string) int64 {
|
||||
sizeStr = strings.ToUpper(sizeStr)
|
||||
|
||||
for _, unit := range validUnits {
|
||||
if strings.HasSuffix(sizeStr, unit.symbol) {
|
||||
size, err := strconv.ParseInt(sizeStr[0:len(sizeStr)-len(unit.symbol)], 10, 64)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return size * unit.multiplier
|
||||
}
|
||||
}
|
||||
|
||||
// Unreachable code
|
||||
return -1
|
||||
}
|
||||
|
||||
// addPathLimit appends the path-to-request body limit mapping to pathLimit
|
||||
// Slashes are checked and added to path if necessary. Duplicates are ignored.
|
||||
func addPathLimit(pathLimit []httpserver.PathLimit, path string, limit int64) []httpserver.PathLimit {
|
||||
// Enforces preceding slash
|
||||
if path[0] != '/' {
|
||||
path = "/" + path
|
||||
}
|
||||
|
||||
// Use the last value if there are duplicates
|
||||
for i, p := range pathLimit {
|
||||
if p.Path == path {
|
||||
pathLimit[i].Limit = limit
|
||||
return pathLimit
|
||||
}
|
||||
}
|
||||
|
||||
return append(pathLimit, httpserver.PathLimit{Path: path, Limit: limit})
|
||||
}
|
||||
|
||||
// SortPathLimits sort pathLimits by their paths length, longest first
|
||||
func SortPathLimits(pathLimits []httpserver.PathLimit) {
|
||||
sorter := &pathLimitSorter{
|
||||
pathLimits: pathLimits,
|
||||
by: LengthDescending,
|
||||
}
|
||||
sort.Sort(sorter)
|
||||
}
|
||||
|
||||
// structs and methods implementing the sorting interfaces for PathLimit
|
||||
type pathLimitSorter struct {
|
||||
pathLimits []httpserver.PathLimit
|
||||
by func(p1, p2 *httpserver.PathLimit) bool
|
||||
}
|
||||
|
||||
func (s *pathLimitSorter) Len() int {
|
||||
return len(s.pathLimits)
|
||||
}
|
||||
|
||||
func (s *pathLimitSorter) Swap(i, j int) {
|
||||
s.pathLimits[i], s.pathLimits[j] = s.pathLimits[j], s.pathLimits[i]
|
||||
}
|
||||
|
||||
func (s *pathLimitSorter) Less(i, j int) bool {
|
||||
return s.by(&s.pathLimits[i], &s.pathLimits[j])
|
||||
}
|
||||
|
||||
// LengthDescending is the comparator for SortPathLimits
|
||||
func LengthDescending(p1, p2 *httpserver.PathLimit) bool {
|
||||
return len(p1.Path) > len(p2.Path)
|
||||
}
|
238
vendor/github.com/mholt/caddy/caddyhttp/limits/setup_test.go
generated
vendored
Normal file
238
vendor/github.com/mholt/caddy/caddyhttp/limits/setup_test.go
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
// Copyright 2015 Light Code Labs, LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package limits
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/mholt/caddy"
|
||||
"github.com/mholt/caddy/caddyhttp/httpserver"
|
||||
)
|
||||
|
||||
const (
|
||||
KB = 1024
|
||||
MB = 1024 * 1024
|
||||
GB = 1024 * 1024 * 1024
|
||||
)
|
||||
|
||||
func TestParseLimits(t *testing.T) {
|
||||
for name, c := range map[string]struct {
|
||||
input string
|
||||
shouldErr bool
|
||||
expect httpserver.Limits
|
||||
}{
|
||||
"catchAll": {
|
||||
input: `limits 2kb`,
|
||||
expect: httpserver.Limits{
|
||||
MaxRequestHeaderSize: 2 * KB,
|
||||
MaxRequestBodySizes: []httpserver.PathLimit{{Path: "/", Limit: 2 * KB}},
|
||||
},
|
||||
},
|
||||
"onlyHeader": {
|
||||
input: `limits {
|
||||
header 2kb
|
||||
}`,
|
||||
expect: httpserver.Limits{
|
||||
MaxRequestHeaderSize: 2 * KB,
|
||||
},
|
||||
},
|
||||
"onlyBody": {
|
||||
input: `limits {
|
||||
body 2kb
|
||||
}`,
|
||||
expect: httpserver.Limits{
|
||||
MaxRequestBodySizes: []httpserver.PathLimit{{Path: "/", Limit: 2 * KB}},
|
||||
},
|
||||
},
|
||||
"onlyBodyWithPath": {
|
||||
input: `limits {
|
||||
body /test 2kb
|
||||
}`,
|
||||
expect: httpserver.Limits{
|
||||
MaxRequestBodySizes: []httpserver.PathLimit{{Path: "/test", Limit: 2 * KB}},
|
||||
},
|
||||
},
|
||||
"mixture": {
|
||||
input: `limits {
|
||||
header 1kb
|
||||
body 2kb
|
||||
body /bar 3kb
|
||||
}`,
|
||||
expect: httpserver.Limits{
|
||||
MaxRequestHeaderSize: 1 * KB,
|
||||
MaxRequestBodySizes: []httpserver.PathLimit{
|
||||
{Path: "/bar", Limit: 3 * KB},
|
||||
{Path: "/", Limit: 2 * KB},
|
||||
},
|
||||
},
|
||||
},
|
||||
"invalidFormat": {
|
||||
input: `limits a b`,
|
||||
shouldErr: true,
|
||||
},
|
||||
"invalidHeaderFormat": {
|
||||
input: `limits {
|
||||
header / 100
|
||||
}`,
|
||||
shouldErr: true,
|
||||
},
|
||||
"invalidBodyFormat": {
|
||||
input: `limits {
|
||||
body / 100 200
|
||||
}`,
|
||||
shouldErr: true,
|
||||
},
|
||||
"invalidKind": {
|
||||
input: `limits {
|
||||
head 100
|
||||
}`,
|
||||
shouldErr: true,
|
||||
},
|
||||
"invalidLimitSize": {
|
||||
input: `limits 10bk`,
|
||||
shouldErr: true,
|
||||
},
|
||||
} {
|
||||
c := c
|
||||
t.Run(name, func(t *testing.T) {
|
||||
controller := caddy.NewTestController("", c.input)
|
||||
_, err := parseLimits(controller)
|
||||
if c.shouldErr && err == nil {
|
||||
t.Error("failed to get expected error")
|
||||
}
|
||||
if !c.shouldErr && err != nil {
|
||||
t.Errorf("got unexpected error: %v", err)
|
||||
}
|
||||
if got := httpserver.GetConfig(controller).Limits; !reflect.DeepEqual(got, c.expect) {
|
||||
t.Errorf("expect %#v, but got %#v", c.expect, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseArguments(t *testing.T) {
|
||||
cases := []struct {
|
||||
arguments []pathLimitUnparsed
|
||||
expected []httpserver.PathLimit
|
||||
hasError bool
|
||||
}{
|
||||
// Parse errors
|
||||
{arguments: []pathLimitUnparsed{{"/", "123.5"}}, expected: []httpserver.PathLimit{}, hasError: true},
|
||||
{arguments: []pathLimitUnparsed{{"/", "200LB"}}, expected: []httpserver.PathLimit{}, hasError: true},
|
||||
{arguments: []pathLimitUnparsed{{"/", "path:999MB"}}, expected: []httpserver.PathLimit{}, hasError: true},
|
||||
{arguments: []pathLimitUnparsed{{"/", "1_234_567"}}, expected: []httpserver.PathLimit{}, hasError: true},
|
||||
{arguments: []pathLimitUnparsed{{"/", "0MB"}}, expected: []httpserver.PathLimit{}, hasError: true},
|
||||
|
||||
// Valid results
|
||||
{arguments: []pathLimitUnparsed{}, expected: []httpserver.PathLimit{}, hasError: false},
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"/", "100"}},
|
||||
expected: []httpserver.PathLimit{{Path: "/", Limit: 100}},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"/", "100KB"}},
|
||||
expected: []httpserver.PathLimit{{Path: "/", Limit: 100 * KB}},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"/", "100MB"}},
|
||||
expected: []httpserver.PathLimit{{Path: "/", Limit: 100 * MB}},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"/", "100GB"}},
|
||||
expected: []httpserver.PathLimit{{Path: "/", Limit: 100 * GB}},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"index", "100"}},
|
||||
expected: []httpserver.PathLimit{{Path: "/index", Limit: 100}},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"/home", "100MB"}, {"/upload/images", "500GB"}},
|
||||
expected: []httpserver.PathLimit{
|
||||
{Path: "/home", Limit: 100 * MB},
|
||||
{Path: "/upload/images", Limit: 500 * GB},
|
||||
},
|
||||
hasError: false},
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"/", "999"}, {"/home", "12345MB"}},
|
||||
expected: []httpserver.PathLimit{
|
||||
{Path: "/", Limit: 999},
|
||||
{Path: "/home", Limit: 12345 * MB},
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
|
||||
// Duplicates
|
||||
{
|
||||
arguments: []pathLimitUnparsed{{"/home", "999"}, {"/home", "12345MB"}},
|
||||
expected: []httpserver.PathLimit{
|
||||
{Path: "/home", Limit: 12345 * MB},
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for caseNum, c := range cases {
|
||||
output, err := parseArguments(c.arguments)
|
||||
if c.hasError && (err == nil) {
|
||||
t.Errorf("Expecting error for case %v but none encountered", caseNum)
|
||||
}
|
||||
if !c.hasError && (err != nil) {
|
||||
t.Errorf("Expecting no error for case %v but encountered %v", caseNum, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(c.expected, output) {
|
||||
t.Errorf("Case %v is expecting: %v, actual %v", caseNum, c.expected, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortPathLimits(t *testing.T) {
|
||||
cases := []struct {
|
||||
arguments []httpserver.PathLimit
|
||||
expected []httpserver.PathLimit
|
||||
}{
|
||||
// Parse errors
|
||||
{arguments: []httpserver.PathLimit{}, expected: []httpserver.PathLimit{}},
|
||||
{
|
||||
arguments: []httpserver.PathLimit{{Path: "/index", Limit: 100}},
|
||||
expected: []httpserver.PathLimit{{Path: "/index", Limit: 100}},
|
||||
},
|
||||
{
|
||||
arguments: []httpserver.PathLimit{
|
||||
{Path: "/static", Limit: 1},
|
||||
{Path: "/static/images", Limit: 100},
|
||||
{Path: "/index", Limit: 200},
|
||||
},
|
||||
expected: []httpserver.PathLimit{
|
||||
{Path: "/static/images", Limit: 100},
|
||||
{Path: "/static", Limit: 1},
|
||||
{Path: "/index", Limit: 200}},
|
||||
},
|
||||
}
|
||||
|
||||
for caseNum, c := range cases {
|
||||
output := append([]httpserver.PathLimit{}, c.arguments...)
|
||||
SortPathLimits(output)
|
||||
if !reflect.DeepEqual(c.expected, output) {
|
||||
t.Errorf("Case %v is expecting: %v, actual %v", caseNum, c.expected, output)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user