~john-koepi/ubuntu/trusty/golang/default

« back to all changes in this revision

Viewing changes to src/pkg/http/fs.go

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-08-03 17:04:59 UTC
  • mfrom: (14.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20110803170459-wzd99m3567y80ila
Tags: 1:59-1
* Imported Upstream version 59
* Refresh patches to a new release
* Fix FTBFS on ARM (Closes: #634270)
* Update version.bash to work with Debian packaging and not hg
  repository

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
        "io"
12
12
        "mime"
13
13
        "os"
 
14
        "path"
14
15
        "path/filepath"
15
16
        "strconv"
16
17
        "strings"
18
19
        "utf8"
19
20
)
20
21
 
 
22
// A Dir implements http.FileSystem using the native file
 
23
// system restricted to a specific directory tree.
 
24
type Dir string
 
25
 
 
26
func (d Dir) Open(name string) (File, os.Error) {
 
27
        if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 {
 
28
                return nil, os.NewError("http: invalid character in file path")
 
29
        }
 
30
        f, err := os.Open(filepath.Join(string(d), filepath.FromSlash(path.Clean("/"+name))))
 
31
        if err != nil {
 
32
                return nil, err
 
33
        }
 
34
        return f, nil
 
35
}
 
36
 
 
37
// A FileSystem implements access to a collection of named files.
 
38
// The elements in a file path are separated by slash ('/', U+002F)
 
39
// characters, regardless of host operating system convention.
 
40
type FileSystem interface {
 
41
        Open(name string) (File, os.Error)
 
42
}
 
43
 
 
44
// A File is returned by a FileSystem's Open method and can be
 
45
// served by the FileServer implementation.
 
46
type File interface {
 
47
        Close() os.Error
 
48
        Stat() (*os.FileInfo, os.Error)
 
49
        Readdir(count int) ([]os.FileInfo, os.Error)
 
50
        Read([]byte) (int, os.Error)
 
51
        Seek(offset int64, whence int) (int64, os.Error)
 
52
}
 
53
 
21
54
// Heuristic: b is text if it is valid UTF-8 and doesn't
22
55
// contain any unprintable ASCII or Unicode characters.
23
56
func isText(b []byte) bool {
44
77
        return true
45
78
}
46
79
 
47
 
func dirList(w ResponseWriter, f *os.File) {
 
80
func dirList(w ResponseWriter, f File) {
48
81
        fmt.Fprintf(w, "<pre>\n")
49
82
        for {
50
83
                dirs, err := f.Readdir(100)
63
96
        fmt.Fprintf(w, "</pre>\n")
64
97
}
65
98
 
66
 
func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
 
99
// name is '/'-separated, not filepath.Separator.
 
100
func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
67
101
        const indexPage = "/index.html"
68
102
 
69
103
        // redirect .../index.html to .../
72
106
                return
73
107
        }
74
108
 
75
 
        f, err := os.Open(name)
 
109
        f, err := fs.Open(name)
76
110
        if err != nil {
77
111
                // TODO expose actual error?
78
112
                NotFound(w, r)
113
147
        // use contents of index.html for directory, if present
114
148
        if d.IsDirectory() {
115
149
                index := name + filepath.FromSlash(indexPage)
116
 
                ff, err := os.Open(index)
 
150
                ff, err := fs.Open(index)
117
151
                if err == nil {
118
152
                        defer ff.Close()
119
153
                        dd, err := ff.Stat()
157
191
        // TODO(adg): handle multiple ranges
158
192
        ranges, err := parseRange(r.Header.Get("Range"), size)
159
193
        if err == nil && len(ranges) > 1 {
160
 
                err = os.ErrorString("multiple ranges not supported")
 
194
                err = os.NewError("multiple ranges not supported")
161
195
        }
162
196
        if err != nil {
163
197
                Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
188
222
 
189
223
// ServeFile replies to the request with the contents of the named file or directory.
190
224
func ServeFile(w ResponseWriter, r *Request, name string) {
191
 
        serveFile(w, r, name, false)
 
225
        serveFile(w, r, Dir(name), "", false)
192
226
}
193
227
 
194
228
type fileHandler struct {
195
 
        root   string
196
 
        prefix string
 
229
        root FileSystem
197
230
}
198
231
 
199
232
// FileServer returns a handler that serves HTTP requests
200
233
// with the contents of the file system rooted at root.
201
 
// It strips prefix from the incoming requests before
202
 
// looking up the file name in the file system.
203
 
func FileServer(root, prefix string) Handler { return &fileHandler{root, prefix} }
 
234
//
 
235
// To use the operating system's file system implementation,
 
236
// use http.Dir:
 
237
//
 
238
//     http.Handle("/", http.FileServer(http.Dir("/tmp")))
 
239
func FileServer(root FileSystem) Handler {
 
240
        return &fileHandler{root}
 
241
}
204
242
 
205
243
func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
206
 
        path := r.URL.Path
207
 
        if !strings.HasPrefix(path, f.prefix) {
208
 
                NotFound(w, r)
209
 
                return
210
 
        }
211
 
        path = path[len(f.prefix):]
212
 
        serveFile(w, r, filepath.Join(f.root, filepath.FromSlash(path)), true)
 
244
        serveFile(w, r, f.root, path.Clean(r.URL.Path), true)
213
245
}
214
246
 
215
247
// httpRange specifies the byte range to be sent to the client.
227
259
                return nil, os.NewError("invalid range")
228
260
        }
229
261
        var ranges []httpRange
230
 
        for _, ra := range strings.Split(s[len(b):], ",", -1) {
 
262
        for _, ra := range strings.Split(s[len(b):], ",") {
231
263
                i := strings.Index(ra, "-")
232
264
                if i < 0 {
233
265
                        return nil, os.NewError("invalid range")