...
1
2
3
4
5
6 package httpfs
7
8 import (
9 "fmt"
10 "io"
11 "net/http"
12 "os"
13
14 "golang.org/x/tools/godoc/vfs"
15 )
16
17 func New(fs vfs.FileSystem) http.FileSystem {
18 return &httpFS{fs}
19 }
20
21 type httpFS struct {
22 fs vfs.FileSystem
23 }
24
25 func (h *httpFS) Open(name string) (http.File, error) {
26 fi, err := h.fs.Stat(name)
27 if err != nil {
28 return nil, err
29 }
30 if fi.IsDir() {
31 return &httpDir{h.fs, name, nil}, nil
32 }
33 f, err := h.fs.Open(name)
34 if err != nil {
35 return nil, err
36 }
37 return &httpFile{h.fs, f, name}, nil
38 }
39
40
41 type httpDir struct {
42 fs vfs.FileSystem
43 name string
44 pending []os.FileInfo
45 }
46
47 func (h *httpDir) Close() error { return nil }
48 func (h *httpDir) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
49 func (h *httpDir) Read([]byte) (int, error) {
50 return 0, fmt.Errorf("cannot Read from directory %s", h.name)
51 }
52
53 func (h *httpDir) Seek(offset int64, whence int) (int64, error) {
54 if offset == 0 && whence == 0 {
55 h.pending = nil
56 return 0, nil
57 }
58 return 0, fmt.Errorf("unsupported Seek in directory %s", h.name)
59 }
60
61 func (h *httpDir) Readdir(count int) ([]os.FileInfo, error) {
62 if h.pending == nil {
63 d, err := h.fs.ReadDir(h.name)
64 if err != nil {
65 return nil, err
66 }
67 if d == nil {
68 d = []os.FileInfo{}
69 }
70 h.pending = d
71 }
72
73 if len(h.pending) == 0 && count > 0 {
74 return nil, io.EOF
75 }
76 if count <= 0 || count > len(h.pending) {
77 count = len(h.pending)
78 }
79 d := h.pending[:count]
80 h.pending = h.pending[count:]
81 return d, nil
82 }
83
84
85 type httpFile struct {
86 fs vfs.FileSystem
87 vfs.ReadSeekCloser
88 name string
89 }
90
91 func (h *httpFile) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
92 func (h *httpFile) Readdir(int) ([]os.FileInfo, error) {
93 return nil, fmt.Errorf("cannot Readdir from file %s", h.name)
94 }
95
View as plain text