// ServeDirIndex serves up a directory to the request func (r *Routes) ServeDirIndex(pattern, indexFile, dir, strip string) { r.Add("get head", pattern+"/*", func(res http.ResponseWriter, req *http.Request, c Collector) { requested := reggy.CleanPath(req.URL.Path) file := strings.TrimPrefix(requested, strip) if err := ServeFile(indexFile, dir, file, res, req); err != nil { r.doFail(res, req, c) } }) }
// FSHandler returns a valid Route.RHandler for use with the relay.Route func FSHandler(fs *FS, fail http.HandlerFunc) RHandler { return func(res http.ResponseWriter, req *http.Request, c Collector) { strip := path.Clean(fmt.Sprintf("/%s/", fs.Strip)) requested := reggy.CleanPath(req.URL.Path) file := strings.TrimPrefix(requested, strip) fi, err := fs.Open(file) if err != nil { if fail != nil { fail(res, req) } else { http.NotFound(res, req) } return } ext := strings.ToLower(filepath.Ext(file)) stat, err := fi.Stat() if err != nil { if fail != nil { fail(res, req) } else { http.NotFound(res, req) } return } // var cext string cext := mime.TypeByExtension(ext) // log.Printf("Type ext: %s -> %s", ext, cext) if cext == "" { if types, ok := mediaTypes[ext]; ok { cext = types } else { cext = "text/plain" } } res.Header().Set("Content-Type", cext) if fs.Header != nil { for m, v := range fs.Header { for _, va := range v { res.Header().Add(m, va) } } } http.ServeContent(res, req, stat.Name(), stat.ModTime(), fi) } }
// Add adds a route into the sets of routes, method can be "" to allow all methods to be handled or a stringed range eg "get head put" to allow this range of methods(get,head,put) only for the handler func (r *Routes) Add(mo, pattern string, h RHandler) { r.ro.Lock() defer r.ro.Unlock() var methods []string if mo != "" { cln := multispaces.ReplaceAllString(mo, " ") methods = multispaces.Split(cln, -1) } if router, ok := r.routes[pattern]; ok { for _, ro := range methods { if _, ok := router.method[ro]; !ok { router.method[ro] = h } } return } var fatt string if r.namespace != "" { fatt = reggy.CleanPath(fmt.Sprintf("/%s/%s", r.namespace, pattern)) } else { fatt = pattern } var mod = make(map[string]RHandler) for _, ro := range methods { mod[ro] = h } r.routes[pattern] = &Route{ ClassicMatchMux: reggy.CreateClassic(fatt), handler: h, method: mod, nomethod: len(mod) == 0, } }
// Namespace returns the path of the route with a added '/*' to endicate allowance of all paths,this is used by other routes to bind to a parent router func (r *Routes) Namespace() string { if r.namespace == "" { return r.namespace } return reggy.CleanPath(fmt.Sprintf("/%s/*", r.namespace)) }