179 lines
4.0 KiB
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
|
|
}
|