package responses import ( "errors" "fmt" "io/ioutil" "os" "path/filepath" "strings" "git.kirsle.net/apps/gophertype/pkg/bundled" "git.kirsle.net/apps/gophertype/pkg/settings" ) // GetFile returns the template file's data, wherever it is. // Checks the embedded bindata, then the user root on disk, then error. // If it can be found, returns the contents or error. func GetFile(path string) ([]byte, error) { // Check the user root first. if b, err := ioutil.ReadFile(filepath.Join(settings.UserRoot, path)); err == nil { return b, nil } // Fall back on embedded bindata. if b, err := bundled.Asset(path); err == nil { return b, nil } return []byte{}, fmt.Errorf("GetFile(%s): not found in user root or bindata", path) } // GetFileExists checks if the file exists but doesn't return its data. func GetFileExists(path string) bool { // Check bindata. if _, err := bundled.AssetInfo(path); err == nil { return true } // Check the user root. if stat, err := os.Stat(filepath.Join(settings.UserRoot, path)); err == nil && !stat.IsDir() { return true } return false } /* ResolveFile searches for the existence of a file from a fuzzy URL path. `path` is a request path like "/about" This function would return e.g. "about.gohtml" as being a file path that is sure to return data in GetFile(). Path finding rules follow expected behavior from dominant web servers: - If the exact path is found, return it immediately. - Try assuming a ".gohtml" or ".md" file extension for the path. - Try checking if the path is a directory with an "index.gohtml" inside it, etc. */ func ResolveFile(path string) (string, error) { // Ensure the path doesn't begin with a slash. path = strings.TrimLeft(path, "/") // Try the exact path. if GetFileExists(path) { return path, nil } // Try fuzzy file matches. var tries = []string{ path + ".gohtml", path + ".md", path + "/index.gohtml", path + "/index.html", } for _, try := range tries { path = strings.TrimLeft(try, "/") if GetFileExists(path) { return path, nil } } return "", errors.New("not found") }