Skip to content

Commit a5a4422

Browse files
committed
Fix relURL with leading slash when baseURL includes a subdirectory
Fixes #9994
1 parent 617e094 commit a5a4422

File tree

4 files changed

+48
-23
lines changed

4 files changed

+48
-23
lines changed

helpers/pathspec_test.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestNewPathSpecFromConfig(t *testing.T) {
3232
v.Set("uglyURLs", true)
3333
v.Set("canonifyURLs", true)
3434
v.Set("paginatePath", "side")
35-
v.Set("baseURL", "http://base.com")
35+
v.Set("baseURL", "http://base.com/foo")
3636
v.Set("themesDir", "thethemes")
3737
v.Set("layoutDir", "thelayouts")
3838
v.Set("workingDir", "thework")
@@ -53,7 +53,10 @@ func TestNewPathSpecFromConfig(t *testing.T) {
5353
c.Assert(p.Language.Lang, qt.Equals, "no")
5454
c.Assert(p.PaginatePath, qt.Equals, "side")
5555

56-
c.Assert(p.BaseURL.String(), qt.Equals, "http://base.com")
56+
c.Assert(p.BaseURL.String(), qt.Equals, "http://base.com/foo")
57+
c.Assert(p.BaseURLString, qt.Equals, "http://base.com/foo")
58+
c.Assert(p.BaseURLNoPathString, qt.Equals, "http://base.com")
59+
5760
c.Assert(p.ThemesDir, qt.Equals, "thethemes")
5861
c.Assert(p.WorkingDir, qt.Equals, "thework")
5962
}

helpers/url.go

+14-11
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,11 @@ func (p *PathSpec) AbsURL(in string, addLanguage bool) string {
103103
}
104104

105105
if url.IsAbs() || strings.HasPrefix(in, "//") {
106+
// It is already absolute, return it as is.
106107
return in
107108
}
108109

109-
var baseURL string
110-
if strings.HasPrefix(in, "/") {
111-
u := p.BaseURL.URL()
112-
u.Path = ""
113-
baseURL = u.String()
114-
} else {
115-
baseURL = p.BaseURL.String()
116-
}
110+
baseURL := p.getBaseURLRoot(in)
117111

118112
if addLanguage {
119113
prefix := p.GetLanguagePrefix()
@@ -140,13 +134,22 @@ func (p *PathSpec) AbsURL(in string, addLanguage bool) string {
140134
}
141135
}
142136
}
137+
143138
return paths.MakePermalink(baseURL, in).String()
144139
}
145140

146-
// RelURL creates a URL relative to the BaseURL root.
147-
// Note: The result URL will not include the context root if canonifyURLs is enabled.
141+
func (p *PathSpec) getBaseURLRoot(path string) string {
142+
if strings.HasPrefix(path, "/") {
143+
// Treat it as relative to the server root.
144+
return p.BaseURLNoPathString
145+
} else {
146+
// Treat it as relative to the baseURL.
147+
return p.BaseURLString
148+
}
149+
}
150+
148151
func (p *PathSpec) RelURL(in string, addLanguage bool) string {
149-
baseURL := p.BaseURL.String()
152+
baseURL := p.getBaseURLRoot(in)
150153
canonifyURLs := p.CanonifyURLs
151154
if (!strings.HasPrefix(in, baseURL) && strings.HasPrefix(in, "http")) || strings.HasPrefix(in, "//") {
152155
return in

helpers/url_test.go

+17-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"strings"
1818
"testing"
1919

20+
qt "github.com/frankban/quicktest"
2021
"github.com/gohugoio/hugo/hugofs"
2122
"github.com/gohugoio/hugo/langs"
2223
)
@@ -59,6 +60,7 @@ func TestAbsURL(t *testing.T) {
5960
}
6061

6162
func doTestAbsURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, lang string) {
63+
c := qt.New(t)
6264
v := newTestCfg()
6365
v.Set("multilingual", multilingual)
6466
v.Set("defaultContentLanguage", "en")
@@ -69,6 +71,10 @@ func doTestAbsURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool,
6971
baseURL string
7072
expected string
7173
}{
74+
// Issue 9994
75+
{"foo/bar", "https://example.org/foo/", "https://example.org/foo/MULTIfoo/bar"},
76+
{"/foo/bar", "https://example.org/foo/", "https://example.org/MULTIfoo/bar"},
77+
7278
{"/test/foo", "http://base/", "http://base/MULTItest/foo"},
7379
{"/" + lang + "/test/foo", "http://base/", "http://base/" + lang + "/test/foo"},
7480
{"", "http://base/ace/", "http://base/ace/MULTI"},
@@ -113,9 +119,8 @@ func doTestAbsURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool,
113119
} else {
114120
expected = strings.Replace(expected, "MULTI", "", 1)
115121
}
116-
if output != expected {
117-
t.Fatalf("Expected %#v, got %#v\n", expected, output)
118-
}
122+
123+
c.Assert(output, qt.Equals, expected)
119124
}
120125
}
121126

@@ -132,6 +137,7 @@ func TestRelURL(t *testing.T) {
132137
}
133138

134139
func doTestRelURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, lang string) {
140+
c := qt.New(t)
135141
v := newTestCfg()
136142
v.Set("multilingual", multilingual)
137143
v.Set("defaultContentLanguage", "en")
@@ -143,13 +149,18 @@ func doTestRelURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool,
143149
canonify bool
144150
expected string
145151
}{
152+
153+
// Issue 9994
154+
{"/foo/bar", "https://example.org/foo/", false, "MULTI/foo/bar"},
155+
{"foo/bar", "https://example.org/foo/", false, "/fooMULTI/foo/bar"},
156+
146157
{"/test/foo", "http://base/", false, "MULTI/test/foo"},
147158
{"/" + lang + "/test/foo", "http://base/", false, "/" + lang + "/test/foo"},
148159
{lang + "/test/foo", "http://base/", false, "/" + lang + "/test/foo"},
149160
{"test.css", "http://base/sub", false, "/subMULTI/test.css"},
150161
{"test.css", "http://base/sub", true, "MULTI/test.css"},
151162
{"/test/", "http://base/", false, "MULTI/test/"},
152-
{"/test/", "http://base/sub/", false, "/subMULTI/test/"},
163+
{"test/", "http://base/sub/", false, "/subMULTI/test/"},
153164
{"/test/", "http://base/sub/", true, "MULTI/test/"},
154165
{"", "http://base/ace/", false, "/aceMULTI/"},
155166
{"", "http://base/ace", false, "/aceMULTI"},
@@ -189,9 +200,8 @@ func doTestRelURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool,
189200
expected = strings.Replace(expected, "MULTI", "", 1)
190201
}
191202

192-
if output != expected {
193-
t.Errorf("[%d][%t] Expected %#v, got %#v\n", i, test.canonify, expected, output)
194-
}
203+
c.Assert(output, qt.Equals, expected, qt.Commentf("[%d] %s", i, test.input))
204+
195205
}
196206
}
197207

hugolib/paths/paths.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ type Paths struct {
3434
Cfg config.Provider
3535

3636
BaseURL
37+
BaseURLString string
38+
BaseURLNoPathString string
3739

3840
// If the baseURL contains a base path, e.g. https://example.com/docs, then "/docs" will be the BasePath.
3941
BasePath string
@@ -145,10 +147,17 @@ func New(fs *hugofs.Fs, cfg config.Provider) (*Paths, error) {
145147
}
146148
}
147149

150+
var baseURLString = baseURL.String()
151+
var baseURLNoPath = baseURL.URL()
152+
baseURLNoPath.Path = ""
153+
var baseURLNoPathString = baseURLNoPath.String()
154+
148155
p := &Paths{
149-
Fs: fs,
150-
Cfg: cfg,
151-
BaseURL: baseURL,
156+
Fs: fs,
157+
Cfg: cfg,
158+
BaseURL: baseURL,
159+
BaseURLString: baseURLString,
160+
BaseURLNoPathString: baseURLNoPathString,
152161

153162
DisablePathToLower: cfg.GetBool("disablePathToLower"),
154163
RemovePathAccents: cfg.GetBool("removePathAccents"),

0 commit comments

Comments
 (0)