diff options
| author | Christine Dodrill <me@christine.website> | 2017-01-10 12:38:33 -0800 |
|---|---|---|
| committer | Christine Dodrill <me@christine.website> | 2017-01-10 12:38:33 -0800 |
| commit | 6e292d4d1d65d83cc089e74063cb70ea63bbd795 (patch) | |
| tree | 2409c6b3f26a4e70499cbbc19f327e01b4a85ca1 /vendor/github.com | |
| parent | ee89843f5bf60a1e8a3a6bf604ac3f67d25ff72a (diff) | |
| download | xesite-6e292d4d1d65d83cc089e74063cb70ea63bbd795.tar.xz xesite-6e292d4d1d65d83cc089e74063cb70ea63bbd795.zip | |
move vendor to repo root
Diffstat (limited to 'vendor/github.com')
| -rw-r--r-- | vendor/github.com/Xe/asarfs/asarfs.go | 117 | ||||
| -rw-r--r-- | vendor/github.com/Xe/asarfs/bench_test.go | 156 | ||||
| -rw-r--r-- | vendor/github.com/Xe/asarfs/runtest.go | 24 | ||||
| -rw-r--r-- | vendor/github.com/gernest/front/front.go | 144 | ||||
| -rw-r--r-- | vendor/github.com/urfave/negroni/doc.go | 25 | ||||
| -rw-r--r-- | vendor/github.com/urfave/negroni/logger.go | 35 | ||||
| -rw-r--r-- | vendor/github.com/urfave/negroni/negroni.go | 133 | ||||
| -rw-r--r-- | vendor/github.com/urfave/negroni/recovery.go | 65 | ||||
| -rw-r--r-- | vendor/github.com/urfave/negroni/response_writer.go | 99 | ||||
| -rw-r--r-- | vendor/github.com/urfave/negroni/static.go | 88 |
10 files changed, 886 insertions, 0 deletions
diff --git a/vendor/github.com/Xe/asarfs/asarfs.go b/vendor/github.com/Xe/asarfs/asarfs.go new file mode 100644 index 0000000..7d18949 --- /dev/null +++ b/vendor/github.com/Xe/asarfs/asarfs.go @@ -0,0 +1,117 @@ +package asarfs + +import ( + "io" + "mime" + "net/http" + "os" + "path/filepath" + "strings" + + "layeh.com/asar" +) + +// ASARfs serves the contents of an asar archive as an HTTP handler. +type ASARfs struct { + fin *os.File + ar *asar.Entry + notFound http.Handler +} + +// Close closes the underlying file used for the asar archive. +func (a *ASARfs) Close() error { + return a.fin.Close() +} + +// Open satisfies the http.FileSystem interface for ASARfs. +func (a *ASARfs) Open(name string) (http.File, error) { + if name == "/" { + name = "/index.html" + } + + e := a.ar.Find(strings.Split(name, "/")[1:]...) + if e == nil { + return nil, os.ErrNotExist + } + + f := &file{ + Entry: e, + r: e.Open(), + } + + return f, nil +} + +// ServeHTTP satisfies the http.Handler interface for ASARfs. +func (a *ASARfs) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if r.RequestURI == "/" { + r.RequestURI = "/index.html" + } + + f := a.ar.Find(strings.Split(r.RequestURI, "/")[1:]...) + if f == nil { + a.notFound.ServeHTTP(w, r) + return + } + + ext := filepath.Ext(f.Name) + mimeType := mime.TypeByExtension(ext) + + w.Header().Add("Content-Type", mimeType) + f.WriteTo(w) +} + +// New creates a new ASARfs pointer based on the filepath to the archive and +// a HTTP handler to hit when a file is not found. +func New(archivePath string, notFound http.Handler) (*ASARfs, error) { + fin, err := os.Open(archivePath) + if err != nil { + return nil, err + } + + root, err := asar.Decode(fin) + if err != nil { + return nil, err + } + + a := &ASARfs{ + fin: fin, + ar: root, + notFound: notFound, + } + + return a, nil +} + +// file is an internal shim that mimics http.File for an asar entry. +type file struct { + *asar.Entry + r io.ReadSeeker +} + +func (f *file) Close() error { + f.r = nil + return nil +} + +func (f *file) Read(buf []byte) (n int, err error) { + return f.r.Read(buf) +} + +func (f *file) Seek(offset int64, whence int) (int64, error) { + return f.r.Seek(offset, whence) +} + +func (f *file) Readdir(count int) ([]os.FileInfo, error) { + result := []os.FileInfo{} + + for _, e := range f.Entry.Children { + result = append(result, e.FileInfo()) + } + + return result, nil +} + +func (f *file) Stat() (os.FileInfo, error) { + return f.Entry.FileInfo(), nil +} diff --git a/vendor/github.com/Xe/asarfs/bench_test.go b/vendor/github.com/Xe/asarfs/bench_test.go new file mode 100644 index 0000000..fd332d5 --- /dev/null +++ b/vendor/github.com/Xe/asarfs/bench_test.go @@ -0,0 +1,156 @@ +// +build go1.8 + +package asarfs + +import ( + "fmt" + "io" + "io/ioutil" + "math/rand" + "net" + "net/http" + "os" + "testing" +) + +func BenchmarkHTTPFileSystem(b *testing.B) { + fs := http.FileServer(http.Dir(".")) + + l, s, err := setupHandler(fs) + if err != nil { + b.Fatal(err) + } + defer l.Close() + defer s.Close() + + url := fmt.Sprintf("http://%s", l.Addr()) + + for n := 0; n < b.N; n++ { + testHandler(url) + } +} + +func BenchmarkASARfs(b *testing.B) { + fs, err := New("./static.asar", http.HandlerFunc(do404)) + if err != nil { + b.Fatal(err) + } + + l, s, err := setupHandler(fs) + if err != nil { + b.Fatal(err) + } + defer l.Close() + defer s.Close() + + url := fmt.Sprintf("http://%s", l.Addr()) + + for n := 0; n < b.N; n++ { + testHandler(url) + } +} + +func BenchmarkPreloadedASARfs(b *testing.B) { + for n := 0; n < b.N; n++ { + testHandler(asarfsurl) + } +} + +func BenchmarkASARfsHTTPFilesystem(b *testing.B) { + fs, err := New("./static.asar", http.HandlerFunc(do404)) + if err != nil { + b.Fatal(err) + } + + l, s, err := setupHandler(http.FileServer(fs)) + if err != nil { + b.Fatal(err) + } + defer l.Close() + defer s.Close() + + url := fmt.Sprintf("http://%s", l.Addr()) + + for n := 0; n < b.N; n++ { + testHandler(url) + } +} + +func BenchmarkPreloadedASARfsHTTPFilesystem(b *testing.B) { + for n := 0; n < b.N; n++ { + testHandler(asarfshttpfsurl) + } +} + +func do404(w http.ResponseWriter, r *http.Request) { + http.Error(w, "Not found", http.StatusNotFound) +} + +func setupHandler(h http.Handler) (net.Listener, *http.Server, error) { + l, err := net.Listen("tcp", ":0") + if err != nil { + panic(err) + } + defer l.Close() + + s := &http.Server{ + Handler: h, + } + go s.ListenAndServe() + + return l, s, nil +} + +func testHandler(u string) error { + num := rand.Intn(9) + num++ + sub := rand.Intn(99) + + fname := fmt.Sprintf("/static/%d/%d%d.json", num, num, sub) + + resp, err := http.Get(u + fname) + if err != nil { + return err + } + defer resp.Body.Close() + + _, err = io.Copy(ioutil.Discard, resp.Body) + if err != nil { + panic(err) + } + + return nil +} + +var ( + asarfsurl string + asarfshttpfsurl string +) + +func TestMain(m *testing.M) { + go func() { + fs, err := New("./static.asar", http.HandlerFunc(do404)) + if err != nil { + } + + l, _, err := setupHandler(fs) + if err != nil { + } + + asarfsurl = fmt.Sprintf("http://%s", l.Addr().String()) + }() + + go func() { + fs, err := New("./static.asar", http.HandlerFunc(do404)) + if err != nil { + } + + l, _, err := setupHandler(http.FileServer(fs)) + if err != nil { + } + + asarfshttpfsurl = fmt.Sprintf("http://%s", l.Addr().String()) + }() + + os.Exit(m.Run()) +} diff --git a/vendor/github.com/Xe/asarfs/runtest.go b/vendor/github.com/Xe/asarfs/runtest.go new file mode 100644 index 0000000..4b839de --- /dev/null +++ b/vendor/github.com/Xe/asarfs/runtest.go @@ -0,0 +1,24 @@ +// +build ignore + +package main + +import ( + "log" + "net/http" + "os" + + "github.com/Xe/asarfs" +) + +func do404(w http.ResponseWriter, r *http.Request) { + http.Error(w, "Not found", http.StatusNotFound) +} + +func main() { + fs, err := asarfs.New("./static.asar", http.HandlerFunc(do404)) + if err != nil { + log.Fatal(err) + } + + http.ListenAndServe(":"+os.Getenv("PORT"), fs) +} diff --git a/vendor/github.com/gernest/front/front.go b/vendor/github.com/gernest/front/front.go new file mode 100644 index 0000000..f4c6f25 --- /dev/null +++ b/vendor/github.com/gernest/front/front.go @@ -0,0 +1,144 @@ +// Package front is a frontmatter extraction library. +package front + +import ( + "bufio" + "bytes" + "encoding/json" + "errors" + "io" + "strings" + + "gopkg.in/yaml.v2" +) + +var ( + //ErrIsEmpty is an error indicating no front matter was found + ErrIsEmpty = errors.New("front: an empty file") + + //ErrUnknownDelim is returned when the delimiters are not known by the + //FrontMatter implementation. + ErrUnknownDelim = errors.New("front: unknown delim") +) + +type ( + //HandlerFunc is an interface for a function that process front matter text. + HandlerFunc func(string) (map[string]interface{}, error) +) + +//Matter is all what matters here. +type Matter struct { + handlers map[string]HandlerFunc +} + +//NewMatter creates a new Matter instance +func NewMatter() *Matter { + return &Matter{handlers: make(map[string]HandlerFunc)} +} + +//Handle registers a handler for the given frontmatter delimiter +func (m *Matter) Handle(delim string, fn HandlerFunc) { + m.handlers[delim] = fn +} + +// Parse parses the input and extract the frontmatter +func (m *Matter) Parse(input io.Reader) (front map[string]interface{}, body string, err error) { + return m.parse(input) +} +func (m *Matter) parse(input io.Reader) (front map[string]interface{}, body string, err error) { + var getFront = func(f string) string { + return strings.TrimSpace(f[3:]) + } + f, body, err := m.splitFront(input) + if err != nil { + return nil, "", err + } + h := m.handlers[f[:3]] + front, err = h(getFront(f)) + if err != nil { + return nil, "", err + } + return front, body, nil + +} +func sniffDelim(input []byte) (string, error) { + if len(input) < 4 { + return "", ErrIsEmpty + } + return string(input[:3]), nil +} + +func (m *Matter) splitFront(input io.Reader) (front, body string, err error) { + bufsize := 1024 * 1024 + buf := make([]byte, bufsize) + + s := bufio.NewScanner(input) + // Necessary so we can handle larger than default 4096b buffer + s.Buffer(buf, bufsize) + + rst := make([]string, 2) + s.Split(m.split) + n := 0 + for s.Scan() { + if n == 0 { + rst[0] = s.Text() + } else if n == 1 { + rst[1] = s.Text() + } + n++ + } + if err = s.Err(); err != nil { + return + } + return rst[0], rst[1], nil +} + +//split implements bufio.SplitFunc for spliting fron matter from the body text. +func (m *Matter) split(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + delim, err := sniffDelim(data) + if err != nil { + return 0, nil, err + } + if _, ok := m.handlers[delim]; !ok { + return 0, nil, ErrUnknownDelim + } + if x := bytes.Index(data, []byte(delim)); x >= 0 { + // check the next delim index + if next := bytes.Index(data[x+len(delim):], []byte(delim)); next > 0 { + return next + len(delim), dropSpace(data[:next+len(delim)]), nil + } + return len(data), dropSpace(data[x+len(delim):]), nil + } + if atEOF { + return len(data), data, nil + } + return 0, nil, nil +} + +func dropSpace(d []byte) []byte { + return bytes.TrimSpace(d) +} + +//JSONHandler implements HandlerFunc interface. It extracts front matter data from the given +// string argument by interpreting it as a json string. +func JSONHandler(front string) (map[string]interface{}, error) { + var rst interface{} + err := json.Unmarshal([]byte(front), &rst) + if err != nil { + return nil, err + } + return rst.(map[string]interface{}), nil +} + +//YAMLHandler decodes ymal string into a go map[string]interface{} +func YAMLHandler(front string) (map[string]interface{}, error) { + out := make(map[string]interface{}) + err := yaml.Unmarshal([]byte(front), out) + if err != nil { + return nil, err + } + return out, nil +} diff --git a/vendor/github.com/urfave/negroni/doc.go b/vendor/github.com/urfave/negroni/doc.go new file mode 100644 index 0000000..add1ed9 --- /dev/null +++ b/vendor/github.com/urfave/negroni/doc.go @@ -0,0 +1,25 @@ +// Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers. +// +// If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit. +// +// For a full guide visit http://github.com/urfave/negroni +// +// package main +// +// import ( +// "github.com/urfave/negroni" +// "net/http" +// "fmt" +// ) +// +// func main() { +// mux := http.NewServeMux() +// mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { +// fmt.Fprintf(w, "Welcome to the home page!") +// }) +// +// n := negroni.Classic() +// n.UseHandler(mux) +// n.Run(":3000") +// } +package negroni diff --git a/vendor/github.com/urfave/negroni/logger.go b/vendor/github.com/urfave/negroni/logger.go new file mode 100644 index 0000000..04cd53b --- /dev/null +++ b/vendor/github.com/urfave/negroni/logger.go @@ -0,0 +1,35 @@ +package negroni + +import ( + "log" + "net/http" + "os" + "time" +) + +// ALogger interface +type ALogger interface { + Println(v ...interface{}) + Printf(format string, v ...interface{}) +} + +// Logger is a middleware handler that logs the request as it goes in and the response as it goes out. +type Logger struct { + // ALogger implements just enough log.Logger interface to be compatible with other implementations + ALogger +} + +// NewLogger returns a new Logger instance +func NewLogger() *Logger { + return &Logger{log.New(os.Stdout, "[negroni] ", 0)} +} + +func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + start := time.Now() + l.Printf("Started %s %s", r.Method, r.URL.Path) + + next(rw, r) + + res := rw.(ResponseWriter) + l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start)) +} diff --git a/vendor/github.com/urfave/negroni/negroni.go b/vendor/github.com/urfave/negroni/negroni.go new file mode 100644 index 0000000..9c7c187 --- /dev/null +++ b/vendor/github.com/urfave/negroni/negroni.go @@ -0,0 +1,133 @@ +package negroni + +import ( + "log" + "net/http" + "os" +) + +// Handler handler is an interface that objects can implement to be registered to serve as middleware +// in the Negroni middleware stack. +// ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc +// passed in. +// +// If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked. +type Handler interface { + ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) +} + +// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers. +// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f. +type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) + +func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + h(rw, r, next) +} + +type middleware struct { + handler Handler + next *middleware +} + +func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + m.handler.ServeHTTP(rw, r, m.next.ServeHTTP) +} + +// Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni +// middleware. The next http.HandlerFunc is automatically called after the Handler +// is executed. +func Wrap(handler http.Handler) Handler { + return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + handler.ServeHTTP(rw, r) + next(rw, r) + }) +} + +// Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler. +// Negroni middleware is evaluated in the order that they are added to the stack using +// the Use and UseHandler methods. +type Negroni struct { + middleware middleware + handlers []Handler +} + +// New returns a new Negroni instance with no middleware preconfigured. +func New(handlers ...Handler) *Negroni { + return &Negroni{ + handlers: handlers, + middleware: build(handlers), + } +} + +// Classic returns a new Negroni instance with the default middleware already +// in the stack. +// +// Recovery - Panic Recovery Middleware +// Logger - Request/Response Logging +// Static - Static File Serving +func Classic() *Negroni { + return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public"))) +} + +func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + n.middleware.ServeHTTP(NewResponseWriter(rw), r) +} + +// Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. +func (n *Negroni) Use(handler Handler) { + if handler == nil { + panic("handler cannot be nil") + } + + n.handlers = append(n.handlers, handler) + n.middleware = build(n.handlers) +} + +// UseFunc adds a Negroni-style handler function onto the middleware stack. +func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) { + n.Use(HandlerFunc(handlerFunc)) +} + +// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. +func (n *Negroni) UseHandler(handler http.Handler) { + n.Use(Wrap(handler)) +} + +// UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack. +func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { + n.UseHandler(http.HandlerFunc(handlerFunc)) +} + +// Run is a convenience function that runs the negroni stack as an HTTP +// server. The addr string takes the same format as http.ListenAndServe. +func (n *Negroni) Run(addr string) { + l := log.New(os.Stdout, "[negroni] ", 0) + l.Printf("listening on %s", addr) + l.Fatal(http.ListenAndServe(addr, n)) +} + +// Returns a list of all the handlers in the current Negroni middleware chain. +func (n *Negroni) Handlers() []Handler { + return n.handlers +} + +func build(handlers []Handler) middleware { + var next middleware + + if len(handlers) == 0 { + return voidMiddleware() + } else if len(handlers) > 1 { + next = build(handlers[1:]) + } else { + next = voidMiddleware() + } + + return middleware{handlers[0], &next} +} + +func voidMiddleware() middleware { + return middleware{ + HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}), + &middleware{}, + } +} diff --git a/vendor/github.com/urfave/negroni/recovery.go b/vendor/github.com/urfave/negroni/recovery.go new file mode 100644 index 0000000..8396cb1 --- /dev/null +++ b/vendor/github.com/urfave/negroni/recovery.go @@ -0,0 +1,65 @@ +package negroni + +import ( + "fmt" + "log" + "net/http" + "os" + "runtime" + "runtime/debug" +) + +// Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one. +type Recovery struct { + Logger ALogger + PrintStack bool + ErrorHandlerFunc func(interface{}) + StackAll bool + StackSize int +} + +// NewRecovery returns a new instance of Recovery +func NewRecovery() *Recovery { + return &Recovery{ + Logger: log.New(os.Stdout, "[negroni] ", 0), + PrintStack: true, + StackAll: false, + StackSize: 1024 * 8, + } +} + +func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + defer func() { + if err := recover(); err != nil { + if rw.Header().Get("Content-Type") == "" { + rw.Header().Set("Content-Type", "text/plain; charset=utf-8") + } + + rw.WriteHeader(http.StatusInternalServerError) + + stack := make([]byte, rec.StackSize) + stack = stack[:runtime.Stack(stack, rec.StackAll)] + + f := "PANIC: %s\n%s" + rec.Logger.Printf(f, err, stack) + + if rec.PrintStack { + fmt.Fprintf(rw, f, err, stack) + } + + if rec.ErrorHandlerFunc != nil { + func() { + defer func() { + if err := recover(); err != nil { + rec.Logger.Printf("provided ErrorHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack()) + rec.Logger.Printf("%s\n", debug.Stack()) + } + }() + rec.ErrorHandlerFunc(err) + }() + } + } + }() + + next(rw, r) +} diff --git a/vendor/github.com/urfave/negroni/response_writer.go b/vendor/github.com/urfave/negroni/response_writer.go new file mode 100644 index 0000000..f805825 --- /dev/null +++ b/vendor/github.com/urfave/negroni/response_writer.go @@ -0,0 +1,99 @@ +package negroni + +import ( + "bufio" + "fmt" + "net" + "net/http" +) + +// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about +// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter +// if the functionality calls for it. +type ResponseWriter interface { + http.ResponseWriter + http.Flusher + // Status returns the status code of the response or 200 if the response has + // not been written (as this is the default response code in net/http) + Status() int + // Written returns whether or not the ResponseWriter has been written. + Written() bool + // Size returns the size of the response body. + Size() int + // Before allows for a function to be called before the ResponseWriter has been written to. This is + // useful for setting headers or any other operations that must happen before a response has been written. + Before(func(ResponseWriter)) +} + +type beforeFunc func(ResponseWriter) + +// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter +func NewResponseWriter(rw http.ResponseWriter) ResponseWriter { + return &responseWriter{ + ResponseWriter: rw, + } +} + +type responseWriter struct { + http.ResponseWriter + status int + size int + beforeFuncs []beforeFunc +} + +func (rw *responseWriter) WriteHeader(s int) { + rw.status = s + rw.callBefore() + rw.ResponseWriter.WriteHeader(s) +} + +func (rw *responseWriter) Write(b []byte) (int, error) { + if !rw.Written() { + // The status will be StatusOK if WriteHeader has not been called yet + rw.WriteHeader(http.StatusOK) + } + size, err := rw.ResponseWriter.Write(b) + rw.size += size + return size, err +} + +func (rw *responseWriter) Status() int { + return rw.status +} + +func (rw *responseWriter) Size() int { + return rw.size +} + +func (rw *responseWriter) Written() bool { + return rw.status != 0 +} + +func (rw *responseWriter) Before(before func(ResponseWriter)) { + rw.beforeFuncs = append(rw.beforeFuncs, before) +} + +func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + hijacker, ok := rw.ResponseWriter.(http.Hijacker) + if !ok { + return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface") + } + return hijacker.Hijack() +} + +func (rw *responseWriter) CloseNotify() <-chan bool { + return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() +} + +func (rw *responseWriter) callBefore() { + for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { + rw.beforeFuncs[i](rw) + } +} + +func (rw *responseWriter) Flush() { + flusher, ok := rw.ResponseWriter.(http.Flusher) + if ok { + flusher.Flush() + } +} diff --git a/vendor/github.com/urfave/negroni/static.go b/vendor/github.com/urfave/negroni/static.go new file mode 100644 index 0000000..34be967 --- /dev/null +++ b/vendor/github.com/urfave/negroni/static.go @@ -0,0 +1,88 @@ +package negroni + +import ( + "net/http" + "path" + "strings" +) + +// Static is a middleware handler that serves static files in the given +// directory/filesystem. If the file does not exist on the filesystem, it +// passes along to the next middleware in the chain. If you desire "fileserver" +// type behavior where it returns a 404 for unfound files, you should consider +// using http.FileServer from the Go stdlib. +type Static struct { + // Dir is the directory to serve static files from + Dir http.FileSystem + // Prefix is the optional prefix used to serve the static directory content + Prefix string + // IndexFile defines which file to serve as index if it exists. + IndexFile string +} + +// NewStatic returns a new instance of Static +func NewStatic(directory http.FileSystem) *Static { + return &Static{ + Dir: directory, + Prefix: "", + IndexFile: "index.html", + } +} + +func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + if r.Method != "GET" && r.Method != "HEAD" { + next(rw, r) + return + } + file := r.URL.Path + // if we have a prefix, filter requests by stripping the prefix + if s.Prefix != "" { + if !strings.HasPrefix(file, s.Prefix) { + next(rw, r) + return + } + file = file[len(s.Prefix):] + if file != "" && file[0] != '/' { + next(rw, r) + return + } + } + f, err := s.Dir.Open(file) + if err != nil { + // discard the error? + next(rw, r) + return + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + next(rw, r) + return + } + + // try to serve index file + if fi.IsDir() { + // redirect if missing trailing slash + if !strings.HasSuffix(r.URL.Path, "/") { + http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound) + return + } + + file = path.Join(file, s.IndexFile) + f, err = s.Dir.Open(file) + if err != nil { + next(rw, r) + return + } + defer f.Close() + + fi, err = f.Stat() + if err != nil || fi.IsDir() { + next(rw, r) + return + } + } + + http.ServeContent(rw, r, file, fi.ModTime(), f) +} |
