Skip to content

Commit 99a7647

Browse files
committed
feat(serverHandler): add WSL 1 fix
`http.ServeContent` does not work well in WSL 1. The downloaded file content may corrupt. Apply a workaround fix if in WSL 1. See also: golang/go#27128
1 parent f835c1b commit 99a7647

File tree

4 files changed

+69
-2
lines changed

4 files changed

+69
-2
lines changed

src/app/main.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import (
44
"../goVirtualHost"
55
"../param"
66
"../serverErrHandler"
7+
"../serverHandler"
78
"../serverLog"
89
"../tpl"
910
"../util"
1011
"../vhostHandler"
12+
"fmt"
1113
"os"
1214
"path/filepath"
1315
)
@@ -34,6 +36,14 @@ func (app *App) ReOpenLog() {
3436
}
3537

3638
func NewApp(params []*param.Param) *App {
39+
verbose := !util.GetBoolEnv("GHFS_QUIET")
40+
41+
if serverHandler.TryEnableWSL1Fix() && verbose {
42+
ttyFile, teardownTtyFile := util.GetTTYFile()
43+
fmt.Fprintln(ttyFile, "WSL 1 compatible mode enabled")
44+
teardownTtyFile()
45+
}
46+
3747
vhSvc := goVirtualHost.NewService()
3848
vhHandlers := make([]*vhostHandler.VhostHandler, 0, len(params))
3949
logFileMan := serverLog.NewFileMan()
@@ -95,7 +105,7 @@ func NewApp(params []*param.Param) *App {
95105
}
96106
}
97107

98-
if !util.GetBoolEnv("GHFS_QUIET") {
108+
if verbose {
99109
go printAccessibleURLs(vhSvc)
100110
}
101111

src/serverHandler/content.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ package serverHandler
33
import (
44
"../util"
55
"net/http"
6+
"os"
67
"strconv"
78
"time"
89
)
910

11+
var serveContent = func(h *handler, w http.ResponseWriter, r *http.Request, info os.FileInfo, file *os.File) {
12+
http.ServeContent(w, r, info.Name(), info.ModTime(), file)
13+
}
14+
1015
func (h *handler) content(w http.ResponseWriter, r *http.Request, data *responseData) {
1116
header := w.Header()
1217
header.Set("X-Content-Type-Options", "nosniff")
@@ -18,7 +23,7 @@ func (h *handler) content(w http.ResponseWriter, r *http.Request, data *response
1823
file := data.File
1924

2025
if needResponseBody(r.Method) {
21-
http.ServeContent(w, r, item.Name(), item.ModTime(), file)
26+
serveContent(h, w, r, item, file)
2227
return
2328
}
2429

src/serverHandler/handler.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"strings"
1212
)
1313

14+
var createFileServer func(root string) http.Handler
15+
1416
type handler struct {
1517
root string
1618
emptyRoot bool
@@ -58,6 +60,8 @@ type handler struct {
5860
hideFiles *regexp.Regexp
5961
theme tpl.Theme
6062

63+
fileServer http.Handler
64+
6165
logger *serverLog.Logger
6266
errHandler *serverErrHandler.ErrHandler
6367
}
@@ -156,6 +160,11 @@ func newHandler(
156160
}
157161
}
158162

163+
var fileServer http.Handler
164+
if !emptyRoot && createFileServer != nil { // for WSL 1 fix
165+
fileServer = createFileServer(root)
166+
}
167+
159168
h := &handler{
160169
root: root,
161170
emptyRoot: emptyRoot,
@@ -203,6 +212,8 @@ func newHandler(
203212
hideFiles: p.HideFiles,
204213
theme: theme,
205214

215+
fileServer: fileServer,
216+
206217
logger: logger,
207218
errHandler: errHandler,
208219
}

src/serverHandler/wsl1.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package serverHandler
2+
3+
import (
4+
"net/http"
5+
"os"
6+
"runtime"
7+
)
8+
9+
type wrappedHttpFile struct {
10+
http.File
11+
}
12+
13+
func (f wrappedHttpFile) Readdir(n int) (items []os.FileInfo, err error) {
14+
return f.File.Readdir(n)
15+
}
16+
17+
type wrappedHttpFileSystem struct {
18+
http.FileSystem
19+
}
20+
21+
func (fs wrappedHttpFileSystem) Open(name string) (http.File, error) {
22+
file, err := fs.FileSystem.Open(name)
23+
return wrappedHttpFile{file}, err
24+
}
25+
26+
func createFsFileServer(root string) http.Handler {
27+
return http.FileServer(wrappedHttpFileSystem{http.Dir(root)})
28+
}
29+
30+
func serveFsContent(h *handler, w http.ResponseWriter, r *http.Request, info os.FileInfo, file *os.File) {
31+
h.fileServer.ServeHTTP(w, r)
32+
}
33+
34+
func TryEnableWSL1Fix() bool {
35+
if runtime.GOOS == "linux" && len(os.Getenv("WSL_DISTRO_NAME")) > 0 && len(os.Getenv("WSL_INTEROP")) == 0 {
36+
createFileServer = createFsFileServer
37+
serveContent = serveFsContent
38+
return true
39+
}
40+
return false
41+
}

0 commit comments

Comments
 (0)