mirror of
https://github.com/kataras/iris.git
synced 2025-01-24 03:01:03 +01:00
Former-commit-id: 7de62d36b7927d790f5af0c1e64713e0a78d12c5
This commit is contained in:
parent
05b1e80e7f
commit
5e5e91e4bb
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kataras/iris/core/netutil"
|
"github.com/kataras/iris/core/netutil"
|
||||||
|
"github.com/kataras/iris/core/router/macro/interpreter/lexer"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -73,30 +74,91 @@ func joinPath(path1 string, path2 string) string {
|
||||||
// iteratively until no further processing can be done:
|
// iteratively until no further processing can be done:
|
||||||
//
|
//
|
||||||
// 1. Replace multiple slashes with a single slash.
|
// 1. Replace multiple slashes with a single slash.
|
||||||
// 3. Eliminate each inner .. path name element (the parent directory)
|
// 2. Replace '\' with '/'
|
||||||
// along with the non-.. element that precedes it.
|
// 3. Replace "\\" with '/'
|
||||||
// 4. Eliminate .. elements that begin a rooted path:
|
// 4. Ignore anything inside '{' and '}'
|
||||||
// that is, replace "/.." by "/" at the beginning of a path.
|
// 5. Makes sure that prefixed with '/'
|
||||||
|
// 6. Remove trailing '/'.
|
||||||
//
|
//
|
||||||
// The returned path ends in a slash only if it is the root "/".
|
// The returned path ends in a slash only if it is the root "/".
|
||||||
func cleanPath(s string) string {
|
func cleanPath(s string) string {
|
||||||
|
// note that we don't care about the performance here, it's before the server ran.
|
||||||
if s == "" || s == "." {
|
if s == "" || s == "." {
|
||||||
return "/"
|
return "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove suffix "/"
|
// remove suffix "/".
|
||||||
if lidx := len(s) - 1; s[lidx] == '/' {
|
if lidx := len(s) - 1; s[lidx] == '/' {
|
||||||
s = s[:lidx]
|
s = s[:lidx]
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefix with "/"
|
// prefix with "/".
|
||||||
s = prefix(s, "/")
|
s = prefix(s, "/")
|
||||||
|
|
||||||
// remove the os specific dir sep
|
// If you're learning go through Iris I will ask you to ignore the
|
||||||
s = strings.Replace(s, "\\", "/", -1)
|
// following part, it's not the recommending way to do that,
|
||||||
|
// but it's understable to me.
|
||||||
|
var (
|
||||||
|
insideMacro = false
|
||||||
|
i = -1
|
||||||
|
)
|
||||||
|
|
||||||
// use std path to clean the path
|
for {
|
||||||
s = path.Clean(s)
|
i++
|
||||||
|
if len(s) <= i {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if s[i] == lexer.Begin {
|
||||||
|
insideMacro = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if s[i] == lexer.End {
|
||||||
|
insideMacro = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// when inside {} then don't try to clean it.
|
||||||
|
if !insideMacro {
|
||||||
|
if s[i] == '/' {
|
||||||
|
if len(s)-1 >= i+1 && s[i+1] == '/' { // we have "//".
|
||||||
|
bckp := s
|
||||||
|
s = bckp[:i] + "/"
|
||||||
|
// forward two, we ignore the second "/" in the raw.
|
||||||
|
i = i + 2
|
||||||
|
if len(bckp)-1 >= i {
|
||||||
|
s += bckp[i:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if we have just a single slash then continue.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if s[i] == '\\' { // this will catch "\\" and "\".
|
||||||
|
bckp := s
|
||||||
|
s = bckp[:i] + "/"
|
||||||
|
|
||||||
|
if len(bckp)-1 >= i+1 {
|
||||||
|
s += bckp[i+1:]
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s)-1 > i && s[i] == '\\' {
|
||||||
|
bckp := s
|
||||||
|
s = bckp[:i]
|
||||||
|
if len(bckp)-1 >= i+2 {
|
||||||
|
s = bckp[:i-1] + bckp[i+1:]
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,38 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestCleanPath(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
path string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"noslashPrefix",
|
||||||
|
"/noslashPrefix"},
|
||||||
|
{"slashSuffix/",
|
||||||
|
"/slashSuffix"},
|
||||||
|
{"noSlashPrefixAndslashSuffix/",
|
||||||
|
"/noSlashPrefixAndslashSuffix"},
|
||||||
|
// don't do any clean up inside {},
|
||||||
|
// fixes #927.
|
||||||
|
{"/total/{year:string regexp(\\d{4})}",
|
||||||
|
"/total/{year:string regexp(\\d{4})}"},
|
||||||
|
{"/total/{year:string regexp(\\d{4})}/more",
|
||||||
|
"/total/{year:string regexp(\\d{4})}/more"},
|
||||||
|
{"/total/{year:string regexp(\\d{4})}/more/{s:string regexp(\\d{7})}",
|
||||||
|
"/total/{year:string regexp(\\d{4})}/more/{s:string regexp(\\d{7})}"},
|
||||||
|
{"/single_no_params",
|
||||||
|
"/single_no_params"},
|
||||||
|
{"/single/{id:int}",
|
||||||
|
"/single/{id:int}"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
if expected, got := tt.expected, cleanPath(tt.path); expected != got {
|
||||||
|
t.Fatalf("[%d] - expected path '%s' but got '%s'", i, expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSplitPath(t *testing.T) {
|
func TestSplitPath(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
path string
|
path string
|
||||||
|
@ -50,8 +82,8 @@ func TestSplitSubdomainAndPath(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{"admin./users/42", "admin.", "/users/42"},
|
{"admin./users/42", "admin.", "/users/42"},
|
||||||
{"//api/users\\42", "", "/api/users/42"},
|
{"//api/users\\42", "", "/api/users/42"},
|
||||||
{"admin./users/\\42", "admin.", "/users/42"},
|
{"admin./users//42", "admin.", "/users/42"},
|
||||||
{"*./users/\\42", "*.", "/users/42"},
|
{"*./users/42/", "*.", "/users/42"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user