mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-03 04:26:36 +08:00
90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
package rule
|
||
|
||
import (
|
||
"fmt"
|
||
"net/url"
|
||
"strings"
|
||
|
||
"github.com/dop251/goja"
|
||
)
|
||
|
||
// newJSURLObject 构造 legado JsURL 的等效对象(java.toURL)。
|
||
//
|
||
// 对应 io.legado.app.utils.JsURL:它只暴露四个属性 ——
|
||
//
|
||
// host 主机名
|
||
// origin "scheme://host[:port]"(默认端口不写)
|
||
// pathname 路径(原样,未解码)
|
||
// searchParams 查询参数(值已 URL 解码;同名只留最后一个,与 legado 一致)
|
||
//
|
||
// legado 返回的是 Java Map,Rhino 下书源会写 searchParams.get("x"),
|
||
// 而 goja 里更自然的是 searchParams.x,所以两者都支持。
|
||
func newJSURLObject(vm *goja.Runtime, raw, base string) (*goja.Object, error) {
|
||
u, err := parseJSURL(raw, base)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
obj := vm.NewObject()
|
||
origin := u.Scheme + "://" + u.Hostname()
|
||
if port := u.Port(); port != "" {
|
||
origin += ":" + port
|
||
}
|
||
_ = obj.Set("host", u.Hostname())
|
||
_ = obj.Set("origin", origin)
|
||
_ = obj.Set("pathname", u.EscapedPath())
|
||
|
||
params := vm.NewObject()
|
||
for key, values := range u.Query() {
|
||
if len(values) == 0 {
|
||
continue
|
||
}
|
||
_ = params.Set(key, values[len(values)-1])
|
||
}
|
||
// searchParams.get(name):兼容 Java Map 的取法;不存在时给 null(对应 Java 的 null)。
|
||
get := func(call goja.FunctionCall) goja.Value {
|
||
if len(call.Arguments) == 0 {
|
||
return goja.Null()
|
||
}
|
||
v := params.Get(call.Arguments[0].String())
|
||
if v == nil || goja.IsUndefined(v) {
|
||
return goja.Null()
|
||
}
|
||
return v
|
||
}
|
||
_ = params.Set("get", get)
|
||
_ = obj.Set("searchParams", params)
|
||
return obj, nil
|
||
}
|
||
|
||
// parseJSURL 解析 java.toURL 的入参。base 非空时按基础地址解析相对路径
|
||
// (对应 Java 的 URL(base, url));解析不出绝对地址时报错(Java 会抛 MalformedURLException)。
|
||
func parseJSURL(raw, base string) (*url.URL, error) {
|
||
raw = strings.TrimSpace(raw)
|
||
if raw == "" {
|
||
return nil, fmt.Errorf("toURL: 地址为空")
|
||
}
|
||
if base != "" {
|
||
b, err := url.Parse(strings.TrimSpace(base))
|
||
if err != nil || !b.IsAbs() {
|
||
return nil, fmt.Errorf("toURL: baseUrl 不是绝对地址: %s", base)
|
||
}
|
||
rel, err := url.Parse(raw)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("toURL: %v", err)
|
||
}
|
||
u := b.ResolveReference(rel)
|
||
if !u.IsAbs() || u.Host == "" {
|
||
return nil, fmt.Errorf("toURL: 解析结果不是绝对地址: %s", raw)
|
||
}
|
||
return u, nil
|
||
}
|
||
u, err := url.Parse(raw)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("toURL: %v", err)
|
||
}
|
||
if u.Scheme == "" || u.Host == "" {
|
||
return nil, fmt.Errorf("toURL: 不是绝对地址: %s", raw)
|
||
}
|
||
return u, nil
|
||
}
|