route/vendor/github.com/cjoudrey/gluaurl/gluaurl.go

179 lines
4.0 KiB
Go

package gluaurl
import "github.com/yuin/gopher-lua"
import "net/url"
import "strings"
import "fmt"
import "sort"
import "regexp"
var rBracket = regexp.MustCompile("\\[\\]$")
func Loader(L *lua.LState) int {
mod := L.SetFuncs(L.NewTable(), map[string]lua.LGFunction{
"parse": parse,
"build": build,
"build_query_string": buildQueryString,
"resolve": resolve,
})
L.Push(mod)
return 1
}
func parse(L *lua.LState) int {
parsed := L.NewTable()
url, err := url.Parse(L.CheckString(1))
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(fmt.Sprintf("%s", err)))
return 2
}
parsed.RawSetString("scheme", lua.LString(url.Scheme))
if url.User != nil {
parsed.RawSetString("username", lua.LString(url.User.Username()))
if password, hasPassword := url.User.Password(); hasPassword {
parsed.RawSetString("password", lua.LString(password))
} else {
parsed.RawSetString("password", lua.LNil)
}
} else {
parsed.RawSetString("username", lua.LNil)
parsed.RawSetString("password", lua.LNil)
}
parsed.RawSetString("host", lua.LString(url.Host))
parsed.RawSetString("path", lua.LString(url.Path))
parsed.RawSetString("query", lua.LString(url.RawQuery))
parsed.RawSetString("fragment", lua.LString(url.Fragment))
L.Push(parsed)
return 1
}
func build(L *lua.LState) int {
options := L.CheckTable(1)
buildUrl := url.URL{}
if scheme := options.RawGetString("scheme"); scheme != lua.LNil {
buildUrl.Scheme = scheme.String()
}
if username := options.RawGetString("username"); username != lua.LNil {
if password := options.RawGetString("password"); password != lua.LNil {
buildUrl.User = url.UserPassword(username.String(), password.String())
} else {
buildUrl.User = url.User(username.String())
}
}
if host := options.RawGetString("host"); host != lua.LNil {
buildUrl.Host = host.String()
}
if path := options.RawGetString("path"); path != lua.LNil {
buildUrl.Path = path.String()
}
if query := options.RawGetString("query"); query != lua.LNil {
buildUrl.RawQuery = query.String()
}
if fragment := options.RawGetString("fragment"); fragment != lua.LNil {
buildUrl.Fragment = fragment.String()
}
L.Push(lua.LString(buildUrl.String()))
return 1
}
func buildQueryString(L *lua.LState) int {
options := L.CheckTable(1)
ret := make([]string, 0)
options.ForEach(func(key, value lua.LValue) {
toQueryString(key.String(), value, &ret)
})
sort.Strings(ret)
L.Push(lua.LString(strings.Join(ret, "&")))
return 1
}
func toQueryString(prefix string, lv lua.LValue, ret *[]string) {
switch v := lv.(type) {
case lua.LBool:
*ret = append(*ret, url.QueryEscape(prefix)+"="+v.String())
break
case lua.LNumber:
*ret = append(*ret, url.QueryEscape(prefix)+"="+v.String())
break
case lua.LString:
*ret = append(*ret, url.QueryEscape(prefix)+"="+url.QueryEscape(v.String()))
break
case *lua.LTable:
maxn := v.MaxN()
if maxn == 0 {
ret2 := make([]string, 0)
v.ForEach(func(key lua.LValue, value lua.LValue) {
toQueryString(prefix+"["+key.String()+"]", value, &ret2)
})
sort.Strings(ret2)
*ret = append(*ret, strings.Join(ret2, "&"))
} else {
ret2 := make([]string, 0)
for i := 1; i <= maxn; i++ {
vi := v.RawGetInt(i)
if rBracket.MatchString(prefix) {
ret2 = append(ret2, url.QueryEscape(prefix)+"="+vi.String())
} else {
if vi.Type() == lua.LTTable {
toQueryString(fmt.Sprintf("%s[%d]", prefix, i-1), vi, &ret2)
} else {
toQueryString(prefix+"[]", vi, &ret2)
}
}
}
*ret = append(*ret, strings.Join(ret2, "&"))
}
break
}
}
func resolve(L *lua.LState) int {
from := L.CheckString(1)
to := L.CheckString(2)
fromUrl, err := url.Parse(from)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(fmt.Sprintf("%s", err)))
return 2
}
toUrl, err := url.Parse(to)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(fmt.Sprintf("%s", err)))
return 2
}
resolvedUrl := fromUrl.ResolveReference(toUrl).String()
L.Push(lua.LString(resolvedUrl))
return 1
}