Skip to content

Commit

Permalink
Merge pull request #20 from ninedraft/fix-fs-serving
Browse files Browse the repository at this point in the history
fix(serve fs): 🐛 file open error log
  • Loading branch information
ninedraft committed Apr 11, 2021
2 parents 72bf34f + d057d89 commit b3db2b3
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 7 deletions.
26 changes: 19 additions & 7 deletions gemax/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ var _ Handler = new(FileSystem).Serve
func (fileSystem *FileSystem) Serve(ctx context.Context, rw ResponseWriter, req IncomingRequest) {
fileSystem.logf("INFO: %s is requested from %s", req.URL(), req.RemoteAddr())

var prefix = strings.Trim(fileSystem.Prefix, "/")
var p = path.Join(prefix, req.URL().Path)
var p = path.Join(fileSystem.Prefix, req.URL().Path)
p = strings.TrimPrefix(p, "/")
if p == "" {
p = "."
}
fileSystem.logf("INFO: serving path: %s", p)

var file, errOpen = fileSystem.FS.Open(p)
switch {
Expand All @@ -47,7 +51,7 @@ func (fileSystem *FileSystem) Serve(ctx context.Context, rw ResponseWriter, req
rw.WriteStatus(code, code.String()+": "+req.URL().Path)
return
case errOpen != nil:
fileSystem.logf("ERROR: serving %s: opening file: %v", p, file)
fileSystem.logf("ERROR: serving %s: opening file: %v", p, errOpen)
rw.WriteStatus(status.ServerUnavailable, "")
return
}
Expand Down Expand Up @@ -104,14 +108,21 @@ func (fileSystem *FileSystem) serveFileHead(rw ResponseWriter, name string, file
}

func (fileSystem *FileSystem) serveDir(rw ResponseWriter, req IncomingRequest, dir string) {
fileSystem.serveIndexFile(rw, dir, "index.gmi", "index.gemini")
if fileSystem.serveIndexFile(rw, dir, "index.gmi", "index.gemini") {
return
}
var entries, errEntries = fs.ReadDir(fileSystem.FS, dir)
if errEntries != nil {
fileSystem.Logf("ERROR: serving dir %s: reading dir content: %v", dir, errEntries)
rw.WriteStatus(status.ServerUnavailable, "")
return
}
_, _ = rw.Write([]byte("\r\n"))

var dirname = path.Base(dir)
if dirname == "." || dirname == "" {
dirname = req.URL().Host + "/"
}
_, _ = io.WriteString(rw, "# "+dirname+"\n\n")
for _, entry := range entries {
var fileLink = path.Join(req.URL().Path, entry.Name())
var _, errWriteEntry = fmt.Fprintf(rw, "=> %s %s \r\n", fileLink, entry.Name())
Expand All @@ -122,7 +133,7 @@ func (fileSystem *FileSystem) serveDir(rw ResponseWriter, req IncomingRequest, d
}
}

func (fileSystem *FileSystem) serveIndexFile(rw ResponseWriter, dir string, names ...string) {
func (fileSystem *FileSystem) serveIndexFile(rw ResponseWriter, dir string, names ...string) bool {
for _, name := range names {
var indexFile = path.Join(dir, name)
var data, err = fs.ReadFile(fileSystem.FS, indexFile)
Expand All @@ -131,9 +142,10 @@ func (fileSystem *FileSystem) serveIndexFile(rw ResponseWriter, dir string, name
continue
}
fileSystem.serveFile(rw, indexFile, bytes.NewReader(data))
return
return true
}
fileSystem.logf("WARN: serving dir %s: searching index files %v: no index files were found", dir, names)
return false
}

func (fileSystem *FileSystem) logf(format string, args ...interface{}) {
Expand Down
75 changes: 75 additions & 0 deletions gemax/fs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package gemax_test

import (
"bytes"
"context"
"net/url"
"testing"
"testing/fstest"

"github.com/ninedraft/gemax/gemax"
"github.com/ninedraft/gemax/gemax/status"
)

func TestFS(test *testing.T) {
var fsys = fstest.MapFS{
"gemax/index.gmi": {Data: []byte("# hello\n")},
"map.gmi": {Data: []byte("# hello\n")},
}
var fserve = gemax.FileSystem{
FS: fsys,
Logf: test.Logf,
}
var ctx = context.Background()

test.Run("", func(test *testing.T) {
var rw = &responseWriter{}
var req = &incomingRequest{
remoteAddr: test.Name(),
}
req.url, _ = url.Parse("gemini://example.com")
fserve.Serve(ctx, rw, req)
if rw.status != status.Success {
test.Errorf("expected %q, got %q", status.Success, rw.status)
}
})
}

type incomingRequest struct {
url *url.URL
remoteAddr string
}

func (req *incomingRequest) RemoteAddr() string { return req.remoteAddr }

func (req *incomingRequest) URL() *url.URL { return req.url }

type responseWriter struct {
status status.Code
meta string
b bytes.Buffer
}

func (rw *responseWriter) Write(data []byte) (int, error) {
if rw.status == 0 {
rw.status = status.Success
rw.meta = gemax.MIMEGemtext
}
return rw.b.Write(data)
}

func (rw *responseWriter) WriteStatus(code status.Code, meta string) {
if rw.status != 0 {
return
}
rw.status = code
rw.meta = meta
}

func (rw *responseWriter) Close() error {
if rw.status == 0 {
rw.status = status.Success
rw.meta = gemax.MIMEGemtext
}
return nil
}

0 comments on commit b3db2b3

Please sign in to comment.