util.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Public Domain Software
  3. *
  4. * I (Matthias Ladkau) am the author of the source code in this file.
  5. * I have placed the source code in this file in the public domain.
  6. *
  7. * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. package httputil
  10. import (
  11. "errors"
  12. "io/ioutil"
  13. "math/rand"
  14. "mime"
  15. "net/http"
  16. "net/url"
  17. "path/filepath"
  18. "time"
  19. "devt.de/krotik/common/fileutil"
  20. )
  21. /*
  22. CheckLocalRedirect checks if a given redirect URL is a local redirect.
  23. The function returns an error in all other cases.
  24. */
  25. func CheckLocalRedirect(urlString string) error {
  26. u, err := url.Parse(urlString)
  27. if err == nil && u.IsAbs() {
  28. err = errors.New("Redirection URL must not be an absolute URL")
  29. }
  30. return err
  31. }
  32. /*
  33. singleFileHandler is a handler for a single file.
  34. */
  35. type singleFileHandler struct {
  36. path string
  37. errHandler func(err error)
  38. }
  39. /*
  40. SingleFileServer returns a handler that serves all HTTP requests
  41. with the contents of a single file.
  42. */
  43. func SingleFileServer(path string, errHandler func(err error)) http.Handler {
  44. if errHandler == nil {
  45. errHandler = func(err error) {}
  46. }
  47. return &singleFileHandler{path, errHandler}
  48. }
  49. /*
  50. ServeHTTP serves HTTP requests.
  51. */
  52. func (f *singleFileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  53. ok, err := fileutil.PathExists(f.path)
  54. if ok {
  55. var content []byte
  56. ctype := mime.TypeByExtension(filepath.Ext(f.path))
  57. w.Header().Set("Content-Type", ctype)
  58. if content, err = ioutil.ReadFile(f.path); err == nil {
  59. if _, err = w.Write(content); err == nil {
  60. return
  61. }
  62. }
  63. }
  64. if err != nil {
  65. f.errHandler(err)
  66. }
  67. w.WriteHeader(http.StatusUnauthorized)
  68. w.Write([]byte("Unauthorized\n"))
  69. }
  70. /*
  71. randomFileHandler is a handler for a random file.
  72. */
  73. type randomFileHandler struct {
  74. *singleFileHandler
  75. paths []string
  76. }
  77. /*
  78. RandomFileServer returns a handler that serves all HTTP requests
  79. with the contents of a random file. The file is picked from a predefined
  80. list.
  81. */
  82. func RandomFileServer(paths []string, errHandler func(err error)) http.Handler {
  83. return &randomFileHandler{&singleFileHandler{"", errHandler}, paths}
  84. }
  85. /*
  86. ServeHTTP serves HTTP requests.
  87. */
  88. func (f *randomFileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  89. rand.Seed(int64(time.Now().Nanosecond()))
  90. selected := f.paths[rand.Intn(len(f.paths))]
  91. f.singleFileHandler.path = selected
  92. f.singleFileHandler.ServeHTTP(w, r)
  93. }