server: Fix 404 redirects on Windows

Fixes #10314
This commit is contained in:
Bjørn Erik Pedersen 2022-09-23 09:16:59 +02:00
parent edf9038a92
commit f3560aa0e1
2 changed files with 87 additions and 32 deletions

View file

@ -436,7 +436,7 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, net.Listener, string
switch redirect.Status { switch redirect.Status {
case 404: case 404:
w.WriteHeader(404) w.WriteHeader(404)
file, err := fs.Open(filepath.FromSlash(strings.TrimPrefix(redirect.To, u.Path))) file, err := fs.Open(strings.TrimPrefix(redirect.To, u.Path))
if err == nil { if err == nil {
defer file.Close() defer file.Close()
io.Copy(w, file) io.Copy(w, file)

View file

@ -57,32 +57,87 @@ func TestServer404(t *testing.T) {
r := runServerTest(c, r := runServerTest(c,
serverTestOptions{ serverTestOptions{
test404: true, pathsToGet: []string{"this/does/not/exist"},
getNumHomes: 1, getNumHomes: 1,
}, },
) )
c.Assert(r.err, qt.IsNil) c.Assert(r.err, qt.IsNil)
c.Assert(r.content404, qt.Contains, "404: 404 Page not found|Not Found.") pr := r.pathsResults["this/does/not/exist"]
c.Assert(pr.statusCode, qt.Equals, http.StatusNotFound)
c.Assert(pr.body, qt.Contains, "404: 404 Page not found|Not Found.")
} }
// Issue 10287. func TestServerPathEncodingIssues(t *testing.T) {
func TestServerUnicode(t *testing.T) { if htesting.IsGitHubAction() {
if htesting.IsCI() { // This test is flaky on CI for some reason. Run it on Windows only for now.
// This test is flaky on CI for some reason.
// TODO(bep) // TODO(bep)
t.Skip("Skipping test on CI") if runtime.GOOS != "windows" {
t.Skip("Skipping test on CI")
}
} }
c := qt.New(t) c := qt.New(t)
r := runServerTest(c, // Issue 10287
serverTestOptions{ c.Run("Unicode paths", func(c *qt.C) {
pathsToGet: []string{"hügö/"}, r := runServerTest(c,
}, serverTestOptions{
) pathsToGet: []string{"hügö/"},
},
)
c.Assert(r.err, qt.IsNil)
c.Assert(r.pathsResults["hügö/"].body, qt.Contains, "This is hügö")
})
// Issue 10314
c.Run("Windows multilingual 404", func(c *qt.C) {
config := `
baseURL = 'https://example.org/'
title = 'Hugo Forum Topic #40568'
defaultContentLanguageInSubdir = true
[languages.en]
contentDir = 'content/en'
languageCode = 'en-US'
languageName = 'English'
weight = 1
[languages.es]
contentDir = 'content/es'
languageCode = 'es-ES'
languageName = 'Espanol'
weight = 2
[server]
[[server.redirects]]
from = '/en/**'
to = '/en/404.html'
status = 404
[[server.redirects]]
from = '/es/**'
to = '/es/404.html'
status = 404
`
r := runServerTest(c,
serverTestOptions{
config: config,
pathsToGet: []string{"en/this/does/not/exist", "es/this/does/not/exist"},
},
)
c.Assert(r.err, qt.IsNil)
pr1 := r.pathsResults["en/this/does/not/exist"]
pr2 := r.pathsResults["es/this/does/not/exist"]
c.Assert(pr1.statusCode, qt.Equals, http.StatusNotFound)
c.Assert(pr2.statusCode, qt.Equals, http.StatusNotFound)
c.Assert(pr1.body, qt.Contains, "404: 404 Page not found|Not Found.")
c.Assert(pr2.body, qt.Contains, "404: 404 Page not found|Not Found.")
})
c.Assert(r.err, qt.IsNil)
c.Assert(r.pathsResults["hügö/"], qt.Contains, "This is hügö")
} }
func TestServerFlags(t *testing.T) { func TestServerFlags(t *testing.T) {
c := qt.New(t) c := qt.New(t)
@ -191,12 +246,14 @@ baseURL="https://example.org"
opts := serverTestOptions{ opts := serverTestOptions{
config: test.config, config: test.config,
getNumHomes: test.numservers, getNumHomes: test.numservers,
test404: true, pathsToGet: []string{"this/does/not/exist"},
args: args, args: args,
} }
r := runServerTest(c, opts) r := runServerTest(c, opts)
c.Assert(r.content404, qt.Contains, "404: 404 Page not found|Not Found.") pr := r.pathsResults["this/does/not/exist"]
c.Assert(pr.statusCode, qt.Equals, http.StatusNotFound)
c.Assert(pr.body, qt.Contains, "404: 404 Page not found|Not Found.")
test.assert(c, r) test.assert(c, r)
}) })
@ -210,12 +267,16 @@ type serverTestResult struct {
homesContent []string homesContent []string
content404 string content404 string
publicDirnames map[string]bool publicDirnames map[string]bool
pathsResults map[string]string pathsResults map[string]pathResult
}
type pathResult struct {
statusCode int
body string
} }
type serverTestOptions struct { type serverTestOptions struct {
getNumHomes int getNumHomes int
test404 bool
config string config string
pathsToGet []string pathsToGet []string
args []string args []string
@ -225,7 +286,7 @@ func runServerTest(c *qt.C, opts serverTestOptions) serverTestResult {
dir := createSimpleTestSite(c, testSiteConfig{configTOML: opts.config}) dir := createSimpleTestSite(c, testSiteConfig{configTOML: opts.config})
result := serverTestResult{ result := serverTestResult{
publicDirnames: make(map[string]bool), publicDirnames: make(map[string]bool),
pathsResults: make(map[string]string), pathsResults: make(map[string]pathResult),
} }
sp, err := helpers.FindAvailablePort() sp, err := helpers.FindAvailablePort()
@ -280,24 +341,18 @@ func runServerTest(c *qt.C, opts serverTestOptions) serverTestResult {
func() { func() {
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/%s", port, path)) resp, err := http.Get(fmt.Sprintf("http://localhost:%d/%s", port, path))
c.Assert(err, qt.IsNil) c.Assert(err, qt.IsNil)
c.Assert(resp.StatusCode, qt.Equals, http.StatusOK) pr := pathResult{
statusCode: resp.StatusCode,
}
if err == nil { if err == nil {
defer resp.Body.Close() defer resp.Body.Close()
result.pathsResults[path] = helpers.ReaderToString(resp.Body) pr.body = helpers.ReaderToString(resp.Body)
} }
result.pathsResults[path] = pr
}() }()
} }
if opts.test404 {
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/this-page-does-not-exist", port))
c.Assert(err, qt.IsNil)
c.Assert(resp.StatusCode, qt.Equals, http.StatusNotFound)
if err == nil {
defer resp.Body.Close()
result.content404 = helpers.ReaderToString(resp.Body)
}
}
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
select { select {