-
Notifications
You must be signed in to change notification settings - Fork 14
/
url.go
77 lines (65 loc) · 2.05 KB
/
url.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package lib
import (
"fmt"
"net/url"
"regexp"
"strings"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
var (
// https://datatracker.ietf.org/doc/html/rfc3986#page-50
regexParseURL = regexp.MustCompile(`^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?`)
UrlEncodeFunc = newUrlEncodeFunction()
RelativeUrlFunc = newRelativeUrlFunction()
)
func newUrlEncodeFunction() function.Function {
return function.New(&function.Spec{
Params: []function.Parameter{{
Name: "s",
Type: cty.String,
}},
Type: function.StaticReturnType(cty.String),
Impl: func(args []cty.Value, _ cty.Type) (ret cty.Value, err error) {
first := args[0]
result := strings.Replace(url.QueryEscape(first.AsString()), "+", "%20", -1)
return cty.StringVal(string(result)), nil
},
})
}
func AbsoluteURL(urlRef string, origin *url.URL) (string, error) {
u, err := url.Parse(urlRef)
if err != nil {
return "", err
}
if !u.IsAbs() {
return origin.ResolveReference(u).String(), nil
}
return urlRef, nil
}
func newRelativeUrlFunction() function.Function {
return function.New(&function.Spec{
Params: []function.Parameter{{
Name: "s",
Type: cty.String,
}},
Type: function.StaticReturnType(cty.String),
Impl: func(args []cty.Value, _ cty.Type) (ret cty.Value, err error) {
absURL := strings.TrimSpace(args[0].AsString())
if !strings.HasPrefix(absURL, "/") && !strings.HasPrefix(absURL, "http://") && !strings.HasPrefix(absURL, "https://") {
return cty.StringVal(""), fmt.Errorf("invalid url given: %q", absURL)
}
// Do not use the result of url.Parse() to preserve the # character in an emtpy fragment.
if _, err := url.Parse(absURL); err != nil {
return cty.StringVal(""), err
}
// The regexParseURL garanties the len of 10 in the result.
urlParts := regexParseURL.FindStringSubmatch(absURL)
// The path must begin w/ a slash.
if !strings.HasPrefix(urlParts[5], "/") {
urlParts[5] = "/" + urlParts[5]
}
return cty.StringVal(urlParts[5] + urlParts[6] + urlParts[8]), nil
},
})
}