baseURL.go (2247B)
1 // Copyright 2018 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package paths
15
16 import (
17 "fmt"
18 "net/url"
19 "strings"
20 )
21
22 // A BaseURL in Hugo is normally on the form scheme://path, but the
23 // form scheme: is also valid (mailto:hugo@rules.com).
24 type BaseURL struct {
25 url *url.URL
26 urlStr string
27 }
28
29 func (b BaseURL) String() string {
30 if b.urlStr != "" {
31 return b.urlStr
32 }
33 return b.url.String()
34 }
35
36 func (b BaseURL) Path() string {
37 return b.url.Path
38 }
39
40 // HostURL returns the URL to the host root without any path elements.
41 func (b BaseURL) HostURL() string {
42 return strings.TrimSuffix(b.String(), b.Path())
43 }
44
45 // WithProtocol returns the BaseURL prefixed with the given protocol.
46 // The Protocol is normally of the form "scheme://", i.e. "webcal://".
47 func (b BaseURL) WithProtocol(protocol string) (string, error) {
48 u := b.URL()
49
50 scheme := protocol
51 isFullProtocol := strings.HasSuffix(scheme, "://")
52 isOpaqueProtocol := strings.HasSuffix(scheme, ":")
53
54 if isFullProtocol {
55 scheme = strings.TrimSuffix(scheme, "://")
56 } else if isOpaqueProtocol {
57 scheme = strings.TrimSuffix(scheme, ":")
58 }
59
60 u.Scheme = scheme
61
62 if isFullProtocol && u.Opaque != "" {
63 u.Opaque = "//" + u.Opaque
64 } else if isOpaqueProtocol && u.Opaque == "" {
65 return "", fmt.Errorf("cannot determine BaseURL for protocol %q", protocol)
66 }
67
68 return u.String(), nil
69 }
70
71 // URL returns a copy of the internal URL.
72 // The copy can be safely used and modified.
73 func (b BaseURL) URL() *url.URL {
74 c := *b.url
75 return &c
76 }
77
78 func newBaseURLFromString(b string) (BaseURL, error) {
79 var result BaseURL
80
81 base, err := url.Parse(b)
82 if err != nil {
83 return result, err
84 }
85
86 return BaseURL{url: base, urlStr: base.String()}, nil
87 }