func SortPathLimits(pathLimits []httpserver.PathLimit) {
	sorter := &pathLimitSorter{
		pathLimits: pathLimits,
		by:         LengthDescending,
	}
	sort.Sort(sorter)
}
SortPathLimits sort pathLimits by their paths length, longest first
package limits
import (
	"errors"
	"sort"
	"strconv"
	"strings"
	"github.com/tmpim/casket"
	"github.com/tmpim/casket/caskethttp/httpserver"
)
const (
	serverType = "http"
	pluginName = "limits"
)
func init() {
	casket.RegisterPlugin(pluginName, casket.Plugin{
		ServerType: serverType,
		Action:     setupLimits,
	})
}
type pathLimitUnparsed struct {
	Path  string
	Limit string
}
func setupLimits(c *casket.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 *casket.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:
		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:
		headerLimit = args[0]
		argList = []pathLimitUnparsed{{
			Path:  "/",
			Limit: args[0],
		}}
	default:
		return nil, c.ArgErr()
	}
	if headerLimit != "" {
		size := parseSize(headerLimit)
		if size < 1 {  
			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 {  
			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},  
}
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
		}
	}
	return -1
}
func addPathLimit(pathLimit []httpserver.PathLimit, path string, limit int64) []httpserver.PathLimit {
	if path[0] != '/' {
		path = "/" + path
	}
	for i, p := range pathLimit {
		if p.Path == path {
			pathLimit[i].Limit = limit
			return pathLimit
		}
	}
	return append(pathLimit, httpserver.PathLimit{Path: path, Limit: limit})
}