A web blog and personal homepage engine written in Go.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

86 lines
2.1 KiB

  1. package responses
  2. import (
  3. "errors"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "git.kirsle.net/apps/gophertype/pkg/bundled"
  10. "git.kirsle.net/apps/gophertype/pkg/settings"
  11. )
  12. // GetFile returns the template file's data, wherever it is.
  13. // Checks the embedded bindata, then the user root on disk, then error.
  14. // If it can be found, returns the contents or error.
  15. func GetFile(path string) ([]byte, error) {
  16. // Check the user root first.
  17. if b, err := ioutil.ReadFile(filepath.Join(settings.UserRoot, path)); err == nil {
  18. return b, nil
  19. }
  20. // Fall back on embedded bindata.
  21. if b, err := bundled.Asset(path); err == nil {
  22. return b, nil
  23. }
  24. return []byte{}, fmt.Errorf("GetFile(%s): not found in user root or bindata", path)
  25. }
  26. // GetFileExists checks if the file exists but doesn't return its data.
  27. func GetFileExists(path string) bool {
  28. // Check bindata.
  29. if _, err := bundled.AssetInfo(path); err == nil {
  30. return true
  31. }
  32. // Check the user root.
  33. if stat, err := os.Stat(filepath.Join(settings.UserRoot, path)); err == nil && !stat.IsDir() {
  34. return true
  35. }
  36. return false
  37. }
  38. /*
  39. ResolveFile searches for the existence of a file from a fuzzy URL path.
  40. `path` is a request path like "/about"
  41. This function would return e.g. "about.gohtml" as being a file path that is
  42. sure to return data in GetFile().
  43. Path finding rules follow expected behavior from dominant web servers:
  44. - If the exact path is found, return it immediately.
  45. - Try assuming a ".gohtml" or ".md" file extension for the path.
  46. - Try checking if the path is a directory with an "index.gohtml" inside it, etc.
  47. */
  48. func ResolveFile(path string) (string, error) {
  49. // Ensure the path doesn't begin with a slash.
  50. path = strings.TrimLeft(path, "/")
  51. // Try the exact path.
  52. if GetFileExists(path) {
  53. return path, nil
  54. }
  55. // Try fuzzy file matches.
  56. var tries = []string{
  57. path + ".gohtml",
  58. path + ".md",
  59. path + "/index.gohtml",
  60. path + "/index.html",
  61. }
  62. for _, try := range tries {
  63. path = strings.TrimLeft(try, "/")
  64. if GetFileExists(path) {
  65. return path, nil
  66. }
  67. }
  68. return "", errors.New("not found")
  69. }