Skip to content

Commit

Permalink
Merge pull request #65 from xushiwei/cached
Browse files Browse the repository at this point in the history
HttpOpener.Open: 404 => fs.ErrNotExist
  • Loading branch information
xushiwei authored Sep 7, 2023
2 parents d25681c + cf194e1 commit 432552a
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 15 deletions.
4 changes: 2 additions & 2 deletions http/fs/cached/cached.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,11 @@ func (p *dir) Close() error {
}

func (p *dir) Read(b []byte) (n int, err error) {
return 0, os.ErrPermission
return 0, fs.ErrPermission
}

func (p *dir) Seek(offset int64, whence int) (int64, error) {
return 0, os.ErrPermission
return 0, fs.ErrPermission
}

func (p *dir) Stat() (fs.FileInfo, error) {
Expand Down
8 changes: 4 additions & 4 deletions http/fs/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ func (p *dataFile) Close() error {
}

func (p *dataFile) ReadDir(n int) ([]fs.DirEntry, error) {
return nil, os.ErrInvalid
return nil, fs.ErrInvalid
}

func (p *dataFile) Readdir(count int) ([]fs.FileInfo, error) {
return nil, os.ErrInvalid
return nil, fs.ErrInvalid
}

func (p *dataFile) IsDir() bool {
Expand Down Expand Up @@ -93,7 +93,7 @@ func (p *filesDataFS) Open(name string) (f http.File, err error) {
return File(name, strings.NewReader(files[i+1])), nil
}
}
return nil, os.ErrNotExist
return nil, fs.ErrNotExist
}

// FilesWithContent implements a http.FileSystem by a list of file name and content.
Expand All @@ -116,7 +116,7 @@ func (p *filesFS) Open(name string) (f http.File, err error) {
return
}
}
return nil, os.ErrNotExist
return nil, fs.ErrNotExist
}

// Files implements a http.FileSystem by a list of file name and content file.
Expand Down
4 changes: 2 additions & 2 deletions http/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (p *unionFS) Open(name string) (f http.File, err error) {
return
}
}
return nil, os.ErrNotExist
return nil, fs.ErrNotExist
}

// Union merge a list of http.FileSystem into a union http.FileSystem object.
Expand Down Expand Up @@ -120,7 +120,7 @@ func (p rootDir) Open(name string) (f http.File, err error) {
if name == "/" {
return rootDir{}, nil
}
return nil, os.ErrNotExist
return nil, fs.ErrNotExist
}

// Root implements a http.FileSystem that only have a root directory.
Expand Down
9 changes: 8 additions & 1 deletion http/fs/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fs
import (
"context"
"fmt"
"io/fs"
"net/http"
"path"
"strings"
Expand Down Expand Up @@ -34,11 +35,17 @@ func (p *HttpOpener) Open(ctx context.Context, url string) (file http.File, err
return nil, err
}
if resp.StatusCode >= 400 {
e := &fs.PathError{Op: "http.Get", Path: url}
if resp.StatusCode == 404 {
e.Err = fs.ErrNotExist
return nil, e
}
url := "url"
if req := resp.Request; req != nil {
url = req.URL.String()
}
return nil, fmt.Errorf("http.Get %s error: status %d (%s)", url, resp.StatusCode, resp.Status)
e.Err = fmt.Errorf("http.Get %s error: status %d (%s)", url, resp.StatusCode, resp.Status)
return nil, e
}
return HttpFile(resp.Request.URL.Path, resp), nil
}
Expand Down
115 changes: 115 additions & 0 deletions http/fs/ignore/ignore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package ignore

import (
"errors"
"io/fs"
"net/http"
"path"
"strings"
)

// -----------------------------------------------------------------------------------------

func Matched(ignore []string, fullName, dir, fname string) bool {
for _, ign := range ignore {
if strings.HasPrefix(ign, "/") { // start with /
if fullName == "" {
fullName = path.Join(dir, fname)
}
if strings.HasSuffix(ign, "/") { // end with /
if strings.HasPrefix(fullName, ign) {
return true
}
} else if strings.HasSuffix(ign, "*") {
if strings.HasPrefix(fullName, ign[:len(ign)-1]) {
return true
}
} else if fullName == ign {
return true
}
} else {
if fname == "" {
dir, fname = path.Split(fullName)
}
if strings.HasSuffix(ign, "*") {
if strings.HasPrefix(fname, ign[:len(ign)-1]) {
return true
}
} else if strings.HasPrefix(ign, "*") {
if strings.HasSuffix(fname, ign[1:]) {
return true
}
} else if fname == ign {
return true
}
}
}
return false
}

// -----------------------------------------------------------------------------------------

type ignDir struct {
http.File
dir string
ignore []string
}

func (p *ignDir) ReadDir(count int) (fis []fs.DirEntry, err error) {
f, ok := p.File.(interface {
ReadDir(count int) ([]fs.DirEntry, error)
})
if !ok {
return nil, &fs.PathError{Op: "readdir", Path: p.dir, Err: errors.New("not implemented")}
}
if fis, err = f.ReadDir(count); err != nil {
return
}
n := 0
dir, ignore := p.dir, p.ignore
for _, fi := range fis {
if Matched(ignore, "", dir, fi.Name()) {
continue
}
fis[n] = fi
n++
}
return fis[:n], nil
}

func (p *ignDir) Readdir(count int) (fis []fs.FileInfo, err error) {
if fis, err = p.File.Readdir(count); err != nil {
return
}
n := 0
dir, ignore := p.dir, p.ignore
for _, fi := range fis {
if Matched(ignore, "", dir, fi.Name()) {
continue
}
fis[n] = fi
n++
}
return fis[:n], nil
}

type fsIgnore struct {
fs http.FileSystem
ignore []string
}

func (p *fsIgnore) Open(name string) (f http.File, err error) {
if f, err = p.fs.Open(name); err != nil {
return
}
if fi, err := f.Stat(); err == nil && fi.IsDir() {
f = &ignDir{f, name, p.ignore}
}
return
}

func New(fs http.FileSystem, patterns ...string) http.FileSystem {
return &fsIgnore{fs, patterns}
}

// -----------------------------------------------------------------------------------------
31 changes: 25 additions & 6 deletions http/fs/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ func Download(destFile string, src http.File) (err error) {

// -----------------------------------------------------------------------------------------

// Unseekable convert a http.File into a io.ReadCloser object without io.Seeker.
// Note you should stop using the origin http.File object to read data.
// This method is used to reduce unnecessary memory usage.
func Unseekable(file http.File) io.ReadCloser {
switch f := file.(type) {
case *stream:
if f.br == nil {
return f.file
}
case *httpFile:
if f.br == nil {
return f.file
}
}
return file
}

// -----------------------------------------------------------------------------------------

type stream struct {
file io.ReadCloser
b bytes.Buffer
Expand All @@ -42,19 +61,19 @@ func (p *stream) TryReader() *bytes.Reader {
}

func (p *stream) ReadDir(n int) ([]fs.DirEntry, error) {
return nil, os.ErrInvalid
return nil, fs.ErrInvalid
}

func (p *stream) Readdir(count int) ([]fs.FileInfo, error) {
return nil, os.ErrInvalid
return nil, fs.ErrInvalid
}

func (p *stream) IsDir() bool {
return false
}

func (p *stream) Mode() fs.FileMode {
return 0
return fs.ModeIrregular
}

func (p *stream) Name() string {
Expand Down Expand Up @@ -135,19 +154,19 @@ func (p *httpFile) TryReader() *bytes.Reader {
}

func (p *httpFile) ReadDir(n int) ([]fs.DirEntry, error) {
return nil, os.ErrInvalid
return nil, fs.ErrInvalid
}

func (p *httpFile) Readdir(count int) ([]fs.FileInfo, error) {
return nil, os.ErrInvalid
return nil, fs.ErrInvalid
}

func (p *httpFile) IsDir() bool {
return false
}

func (p *httpFile) Mode() fs.FileMode {
return 0
return fs.ModeIrregular
}

func (p *httpFile) Name() string {
Expand Down

0 comments on commit 432552a

Please sign in to comment.