Skip to content

Commit 9512f69

Browse files
committed
initial commit
0 parents  commit 9512f69

File tree

4 files changed

+196
-0
lines changed

4 files changed

+196
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License
2+
3+
Copyright (c) 2018 The AbsFs Contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

Readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# httpfs
2+
The `httpfs` package implements a `net/http` FileSystem interface compatible
3+
object that includes both file reading and file writing operations.
4+
5+
Work in progress

httpfs.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package httpfs
2+
3+
import (
4+
"net/http"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
"time"
9+
10+
"github.com/pkg/errors"
11+
12+
"github.com/absfs/absfs"
13+
)
14+
15+
var ErrNotImplemented = errors.New("not implemented")
16+
17+
type Httpfs struct {
18+
fs absfs.Filer
19+
}
20+
21+
func New(fs absfs.Filer) *Httpfs {
22+
return &Httpfs{fs}
23+
}
24+
25+
func (filer *Httpfs) Open(name string) (http.File, error) {
26+
f, err := filer.OpenFile(name, os.O_RDONLY, 0400)
27+
28+
return http.File(f), err
29+
}
30+
31+
// OpenFile opens a file using the given flags and the given mode.
32+
func (filer *Httpfs) OpenFile(name string, flag int, perm os.FileMode) (absfs.File, error) {
33+
return filer.fs.OpenFile(name, flag, perm)
34+
}
35+
36+
// Mkdir creates a directory in the filesystem, return an error if any
37+
// happens.
38+
func (filer *Httpfs) Mkdir(name string, perm os.FileMode) error {
39+
return filer.fs.Mkdir(name, perm)
40+
}
41+
42+
// MkdirAll creates all missing directories in `name` without returning an error
43+
// for directories that already exist
44+
func (filer *Httpfs) MkdirAll(name string, perm os.FileMode) error {
45+
p := string(filepath.Separator)
46+
for _, name := range strings.Split(name, p) {
47+
if name == "" {
48+
continue
49+
}
50+
p = filepath.Join(p, name)
51+
err := filer.Mkdir(p, perm)
52+
if err != nil && !os.IsExist(err) {
53+
return err
54+
}
55+
}
56+
return nil
57+
}
58+
59+
// Remove removes a file identified by name, returning an error, if any
60+
// happens.
61+
func (filer *Httpfs) Remove(name string) error {
62+
return filer.fs.Remove(name)
63+
}
64+
65+
// RemoveAll removes a directory after removing all children of that directory.
66+
func (filer *Httpfs) RemoveAll(path string) (err error) {
67+
info, err := filer.Stat(path)
68+
if err != nil {
69+
if os.IsNotExist(err) {
70+
return nil
71+
}
72+
return err
73+
}
74+
75+
// if it's not a directory remove it and return
76+
if !info.IsDir() {
77+
return filer.Remove(path)
78+
}
79+
80+
f, err := filer.OpenFile(path, os.O_RDWR, 0700)
81+
if err != nil {
82+
if os.IsNotExist(err) {
83+
return nil
84+
}
85+
return err
86+
}
87+
88+
// get and loop through each directory entry calling remove all recursively
89+
infos, err := f.Readdir(0)
90+
if err != nil {
91+
return err
92+
}
93+
f.Close()
94+
95+
for _, info := range infos {
96+
err = filer.RemoveAll(filepath.Join(path, info.Name()))
97+
if err != nil {
98+
return err
99+
}
100+
}
101+
102+
return filer.Remove(path)
103+
}
104+
105+
// Stat returns the FileInfo structure describing file. If there is an error, it will be of type *PathError.
106+
func (filer *Httpfs) Stat(name string) (os.FileInfo, error) {
107+
return filer.fs.Stat(name)
108+
}
109+
110+
//Chmod changes the mode of the named file to mode.
111+
func (filer *Httpfs) Chmod(name string, mode os.FileMode) error {
112+
return filer.fs.Chmod(name, mode)
113+
}
114+
115+
//Chtimes changes the access and modification times of the named file
116+
func (filer *Httpfs) Chtimes(name string, atime time.Time, mtime time.Time) error {
117+
return filer.fs.Chtimes(name, atime, mtime)
118+
}
119+
120+
//Chown changes the owner and group ids of the named file
121+
func (filer *Httpfs) Chown(name string, uid, gid int) error {
122+
return filer.fs.Chown(name, uid, gid)
123+
}

httpfs_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package httpfs_test
2+
3+
import (
4+
"io/ioutil"
5+
"log"
6+
"net/http"
7+
"net/http/httptest"
8+
"os"
9+
10+
"github.com/absfs/httpfs"
11+
"github.com/absfs/memfs"
12+
13+
"testing"
14+
)
15+
16+
func TestFileServer(t *testing.T) {
17+
mfs, err := memfs.NewFS()
18+
if err != nil {
19+
t.Fatal(err)
20+
}
21+
22+
fs := httpfs.New(mfs)
23+
24+
f, err := fs.OpenFile("/foo.txt", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0600)
25+
if err != nil {
26+
t.Fatal(err)
27+
}
28+
_, err = f.Write([]byte("foo bar bat."))
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
f.Close()
33+
34+
server := httptest.NewServer(http.FileServer(fs))
35+
defer server.Close()
36+
37+
res, err := http.Get(server.URL + "/foo.txt")
38+
if err != nil {
39+
log.Fatal(err)
40+
}
41+
data, err := ioutil.ReadAll(res.Body)
42+
res.Body.Close()
43+
if string(data) != "foo bar bat." {
44+
t.Fatal("wrong response")
45+
}
46+
t.Logf("received: %q", string(data))
47+
}

0 commit comments

Comments
 (0)