Commit dd4de698 authored by Tobias Weingartner's avatar Tobias Weingartner

Better search for config.

Handle LastModifiedHeader better.
Handle HEAD/GET.
parent 19a85d08
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"os" "os"
"path" "path"
"text/template" "text/template"
"time"
"github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware"
"github.com/russross/blackfriday" "github.com/russross/blackfriday"
...@@ -65,75 +66,111 @@ type Config struct { ...@@ -65,75 +66,111 @@ type Config struct {
// ServeHTTP implements the http.Handler interface. // ServeHTTP implements the http.Handler interface.
func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
for _, cfg := range md.Configs { var cfg *Config
if !middleware.Path(r.URL.Path).Matches(cfg.PathScope) { for _, c := range md.Configs {
continue if middleware.Path(r.URL.Path).Matches(c.PathScope) { // not negated
cfg = c
break // or goto
} }
}
if cfg == nil {
return md.Next.ServeHTTP(w, r) // exit early
}
var dirents []os.FileInfo // We only deal with HEAD/GET
fpath := r.URL.Path switch r.Method {
if idx, ok := middleware.IndexFile(md.FileSys, fpath, md.IndexFiles); ok { case http.MethodGet, http.MethodHead:
// We're serving a directory index file, which may be a markdown default:
// file with a template. Let's grab a list of files this directory return http.StatusMethodNotAllowed, nil
// URL points to, and pass that in to any possible template invocations, }
// so that templates can customize the look and feel of a directory.
var dirents []os.FileInfo
fdp, err := md.FileSys.Open(fpath) var lastModTime time.Time
if err != nil { fpath := r.URL.Path
return http.StatusInternalServerError, err if idx, ok := middleware.IndexFile(md.FileSys, fpath, md.IndexFiles); ok {
} // We're serving a directory index file, which may be a markdown
dirents, err = fdp.Readdir(-1) // file with a template. Let's grab a list of files this directory
if err != nil { // URL points to, and pass that in to any possible template invocations,
return http.StatusInternalServerError, err // so that templates can customize the look and feel of a directory.
fdp, err := md.FileSys.Open(fpath)
if err != nil {
if os.IsPermission(err) {
return http.StatusForbidden, err
} }
return http.StatusInternalServerError, err
}
// Set path to found index file // Grab a possible set of directory entries. Note, we do not check
fpath = idx // for errors here (unreadable directory, for example). It may
// still be useful to have a directory template file, without the
// directory contents being present.
dirents, _ = fdp.Readdir(-1)
for _, d := range dirents {
lastModTime = latest(lastModTime, d.ModTime())
} }
// If supported extension, process it // Set path to found index file
if _, ok := cfg.Extensions[path.Ext(fpath)]; ok { fpath = idx
f, err := md.FileSys.Open(fpath) }
if err != nil {
if os.IsPermission(err) {
return http.StatusForbidden, err
}
return http.StatusNotFound, nil
}
fs, err := f.Stat() // If supported extension, process it
if err != nil { if _, ok := cfg.Extensions[path.Ext(fpath)]; ok {
return http.StatusNotFound, nil f, err := md.FileSys.Open(fpath)
if err != nil {
if os.IsPermission(err) {
return http.StatusForbidden, err
} }
return http.StatusNotFound, nil
}
body, err := ioutil.ReadAll(f) fs, err := f.Stat()
if err != nil { if err != nil {
return http.StatusInternalServerError, err return http.StatusNotFound, nil
} }
lastModTime = latest(lastModTime, fs.ModTime())
ctx := middleware.Context{ body, err := ioutil.ReadAll(f)
Root: md.FileSys, if err != nil {
Req: r, return http.StatusInternalServerError, err
URL: r.URL, }
}
html, err := cfg.Markdown(fpath, body, dirents, ctx) ctx := middleware.Context{
if err != nil { Root: md.FileSys,
return http.StatusInternalServerError, err Req: r,
} URL: r.URL,
}
html, err := cfg.Markdown(fpath, body, dirents, ctx)
if err != nil {
return http.StatusInternalServerError, err
}
// TODO(weingart): move template execution here, something like: // TODO(weingart): move template execution here, something like:
// //
// html, err = md.execTemplate(cfg, html, ctx) // html, err = md.execTemplate(cfg, html, ctx)
// if err != nil { // if err != nil {
// return http.StatusInternalServerError, err // return http.StatusInternalServerError, err
// } // }
middleware.SetLastModifiedHeader(w, fs.ModTime()) middleware.SetLastModifiedHeader(w, lastModTime)
if r.Method == "GET" {
w.Write(html) w.Write(html)
return http.StatusOK, nil
} }
return http.StatusOK, nil
} }
// Didn't qualify to serve as markdown; pass-thru // Didn't qualify to serve as markdown; pass-thru
return md.Next.ServeHTTP(w, r) return md.Next.ServeHTTP(w, r)
} }
// latest returns the latest time.Time
func latest(t ...time.Time) time.Time {
var last time.Time
for _, tt := range t {
if tt.After(last) {
last = tt
}
}
return last
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment