Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

125 lines
3.2KB

  1. package main
  2. import (
  3. "log"
  4. "net/http"
  5. "os"
  6. "path"
  7. "strings"
  8. )
  9. type httpEntry func(http.ResponseWriter, *http.Request)
  10. var httpEntryMap = map[string]httpEntry{
  11. apiV1Prefix: apiV1Main,
  12. apiV1WebSocket: apiV1WebSocketHandler,
  13. videoPrefix: videoMain,
  14. formPrefix: formMain,
  15. }
  16. func setupHTTPHandler() {
  17. for key, val := range httpEntryMap {
  18. http.HandleFunc(key, val)
  19. }
  20. log.Printf("Server started at %s:%s\n", config.Host, config.Port)
  21. log.Fatal(http.ListenAndServe(config.Host+":"+config.Port, nil))
  22. //log.Fatal(http.ListenAndServeTLS(config.Host+":"+config.Port, config.TlsCert, config.TlsKey, nil))
  23. }
  24. // FSHandler404 provides the function signature for passing to the FileServerWith404
  25. type FSHandler404 = func(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool)
  26. /*
  27. FileServerWith404 wraps the http.FileServer checking to see if the url path exists first.
  28. If the file fails to exist it calls the supplied FSHandle404 function
  29. The implementation can choose to either modify the request, e.g. change the URL path and return true to have the
  30. default FileServer handling to still take place, or return false to stop further processing, for example if you wanted
  31. to write a custom response
  32. e.g. redirects to root and continues the file serving handler chain
  33. func fileSystem404(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool) {
  34. //if not found redirect to /
  35. r.URL.Path = "/"
  36. return true
  37. }
  38. Use the same as you would with a http.FileServer e.g.
  39. r.Handle("/", http.StripPrefix("/", mw.FileServerWith404(http.Dir("./staticDir"), fileSystem404)))
  40. */
  41. func FileServerWith404(root http.FileSystem, handler404 FSHandler404) http.Handler {
  42. fs := http.FileServer(root)
  43. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  44. //make sure the url path starts with /
  45. upath := r.URL.Path
  46. if !strings.HasPrefix(upath, "/") {
  47. upath = "/" + upath
  48. r.URL.Path = upath
  49. }
  50. upath = path.Clean(upath)
  51. // attempt to open the file via the http.FileSystem
  52. f, err := root.Open(upath)
  53. if err != nil {
  54. if os.IsNotExist(err) {
  55. if handledBy404Handler(handler404, w, r) {
  56. return
  57. }
  58. }
  59. }
  60. // if successfully opened, check if it's dir
  61. defer func(f http.File) {
  62. err := f.Close()
  63. if err != nil {
  64. return //cannot close this file
  65. }
  66. }(f)
  67. //see if it's directory
  68. info, e := f.Stat()
  69. if e != nil {
  70. if handledBy404Handler(handler404, w, r) {
  71. return
  72. }
  73. }
  74. if info.IsDir() {
  75. //do we have index.html?
  76. f, err := root.Open(upath + "/index.html")
  77. if err != nil {
  78. //no we don't
  79. if handledBy404Handler(handler404, w, r) {
  80. return
  81. }
  82. } else {
  83. f.Close()
  84. }
  85. }
  86. // default serve
  87. fs.ServeHTTP(w, r)
  88. })
  89. }
  90. func fileSystem404(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool) {
  91. //if not found redirect to /
  92. // r.URL.Path = "/404.html" //not working as some directorys may not be feasible.
  93. // return true
  94. http.Redirect(w, r, "/404.html", http.StatusSeeOther)
  95. return false
  96. }
  97. //check if h is null, if not call this as handler.
  98. func handledBy404Handler(h FSHandler404, w http.ResponseWriter, r *http.Request) bool {
  99. if h != nil {
  100. doDefault := h(w, r)
  101. if !doDefault {
  102. return true
  103. }
  104. }
  105. return false
  106. }