router.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package httpd
  2. import (
  3. "net/http"
  4. "github.com/drakkan/sftpgo/dataprovider"
  5. "github.com/drakkan/sftpgo/logger"
  6. "github.com/drakkan/sftpgo/sftpd"
  7. "github.com/drakkan/sftpgo/utils"
  8. "github.com/go-chi/chi"
  9. "github.com/go-chi/chi/middleware"
  10. "github.com/go-chi/render"
  11. "github.com/prometheus/client_golang/prometheus/promhttp"
  12. )
  13. // GetHTTPRouter returns the configured HTTP handler
  14. func GetHTTPRouter() http.Handler {
  15. return router
  16. }
  17. func initializeRouter(staticFilesPath string) {
  18. router = chi.NewRouter()
  19. router.Use(middleware.RequestID)
  20. router.Use(middleware.RealIP)
  21. router.Use(logger.NewStructuredLogger(logger.GetLogger()))
  22. router.Use(middleware.Recoverer)
  23. router.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  24. sendAPIResponse(w, r, nil, "Not Found", http.StatusNotFound)
  25. }))
  26. router.MethodNotAllowed(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  27. sendAPIResponse(w, r, nil, "Method not allowed", http.StatusMethodNotAllowed)
  28. }))
  29. router.Get("/", func(w http.ResponseWriter, r *http.Request) {
  30. http.Redirect(w, r, webUsersPath, http.StatusMovedPermanently)
  31. })
  32. router.Get(webBasePath, func(w http.ResponseWriter, r *http.Request) {
  33. http.Redirect(w, r, webUsersPath, http.StatusMovedPermanently)
  34. })
  35. router.Handle(metricsPath, promhttp.Handler())
  36. router.Get(versionPath, func(w http.ResponseWriter, r *http.Request) {
  37. render.JSON(w, r, utils.GetAppVersion())
  38. })
  39. router.Get(providerStatusPath, func(w http.ResponseWriter, r *http.Request) {
  40. err := dataprovider.GetProviderStatus(dataProvider)
  41. if err != nil {
  42. sendAPIResponse(w, r, err, "", http.StatusInternalServerError)
  43. } else {
  44. sendAPIResponse(w, r, err, "Alive", http.StatusOK)
  45. }
  46. })
  47. router.Get(activeConnectionsPath, func(w http.ResponseWriter, r *http.Request) {
  48. render.JSON(w, r, sftpd.GetConnectionsStats())
  49. })
  50. router.Delete(activeConnectionsPath+"/{connectionID}", func(w http.ResponseWriter, r *http.Request) {
  51. handleCloseConnection(w, r)
  52. })
  53. router.Get(quotaScanPath, func(w http.ResponseWriter, r *http.Request) {
  54. getQuotaScans(w, r)
  55. })
  56. router.Post(quotaScanPath, func(w http.ResponseWriter, r *http.Request) {
  57. startQuotaScan(w, r)
  58. })
  59. router.Get(userPath, func(w http.ResponseWriter, r *http.Request) {
  60. getUsers(w, r)
  61. })
  62. router.Post(userPath, func(w http.ResponseWriter, r *http.Request) {
  63. addUser(w, r)
  64. })
  65. router.Get(userPath+"/{userID}", func(w http.ResponseWriter, r *http.Request) {
  66. getUserByID(w, r)
  67. })
  68. router.Put(userPath+"/{userID}", func(w http.ResponseWriter, r *http.Request) {
  69. updateUser(w, r)
  70. })
  71. router.Delete(userPath+"/{userID}", func(w http.ResponseWriter, r *http.Request) {
  72. deleteUser(w, r)
  73. })
  74. router.Get(webUsersPath, func(w http.ResponseWriter, r *http.Request) {
  75. handleGetWebUsers(w, r)
  76. })
  77. router.Get(webUserPath, func(w http.ResponseWriter, r *http.Request) {
  78. handleWebAddUserGet(w, r)
  79. })
  80. router.Get(webUserPath+"/{userID}", func(w http.ResponseWriter, r *http.Request) {
  81. handleWebUpdateUserGet(chi.URLParam(r, "userID"), w, r)
  82. })
  83. router.Post(webUserPath, func(w http.ResponseWriter, r *http.Request) {
  84. handleWebAddUserPost(w, r)
  85. })
  86. router.Post(webUserPath+"/{userID}", func(w http.ResponseWriter, r *http.Request) {
  87. handleWebUpdateUserPost(chi.URLParam(r, "userID"), w, r)
  88. })
  89. router.Get(webConnectionsPath, func(w http.ResponseWriter, r *http.Request) {
  90. handleWebGetConnections(w, r)
  91. })
  92. router.Group(func(router chi.Router) {
  93. router.Use(middleware.DefaultCompress)
  94. fileServer(router, webStaticFilesPath, http.Dir(staticFilesPath))
  95. })
  96. }
  97. func handleCloseConnection(w http.ResponseWriter, r *http.Request) {
  98. connectionID := chi.URLParam(r, "connectionID")
  99. if connectionID == "" {
  100. sendAPIResponse(w, r, nil, "connectionID is mandatory", http.StatusBadRequest)
  101. return
  102. }
  103. if sftpd.CloseActiveConnection(connectionID) {
  104. sendAPIResponse(w, r, nil, "Connection closed", http.StatusOK)
  105. } else {
  106. sendAPIResponse(w, r, nil, "Not Found", http.StatusNotFound)
  107. }
  108. }
  109. func fileServer(r chi.Router, path string, root http.FileSystem) {
  110. fs := http.StripPrefix(path, http.FileServer(root))
  111. if path != "/" && path[len(path)-1] != '/' {
  112. r.Get(path, http.RedirectHandler(path+"/", http.StatusMovedPermanently).ServeHTTP)
  113. path += "/"
  114. }
  115. path += "*"
  116. r.Get(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  117. fs.ServeHTTP(w, r)
  118. }))
  119. }