router.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package httpd
  2. import (
  3. "net/http"
  4. "strings"
  5. "github.com/go-chi/chi"
  6. "github.com/go-chi/chi/middleware"
  7. "github.com/go-chi/render"
  8. "github.com/drakkan/sftpgo/common"
  9. "github.com/drakkan/sftpgo/dataprovider"
  10. "github.com/drakkan/sftpgo/logger"
  11. "github.com/drakkan/sftpgo/metrics"
  12. "github.com/drakkan/sftpgo/version"
  13. )
  14. // GetHTTPRouter returns the configured HTTP handler
  15. func GetHTTPRouter() http.Handler {
  16. return router
  17. }
  18. func initializeRouter(staticFilesPath string, enableProfiler, enableWebAdmin bool) {
  19. router = chi.NewRouter()
  20. router.Group(func(router chi.Router) {
  21. router.Use(middleware.RequestID)
  22. router.Use(middleware.RealIP)
  23. router.Use(logger.NewStructuredLogger(logger.GetLogger()))
  24. router.Use(middleware.Recoverer)
  25. if enableProfiler {
  26. logger.InfoToConsole("enabling the built-in profiler")
  27. logger.Info(logSender, "", "enabling the built-in profiler")
  28. router.Mount(pprofBasePath, middleware.Profiler())
  29. }
  30. router.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  31. sendAPIResponse(w, r, nil, "Not Found", http.StatusNotFound)
  32. }))
  33. router.MethodNotAllowed(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  34. sendAPIResponse(w, r, nil, "Method not allowed", http.StatusMethodNotAllowed)
  35. }))
  36. router.Get("/", func(w http.ResponseWriter, r *http.Request) {
  37. http.Redirect(w, r, webUsersPath, http.StatusMovedPermanently)
  38. })
  39. router.Group(func(router chi.Router) {
  40. router.Use(checkAuth)
  41. router.Get(webBasePath, func(w http.ResponseWriter, r *http.Request) {
  42. http.Redirect(w, r, webUsersPath, http.StatusMovedPermanently)
  43. })
  44. metrics.AddMetricsEndpoint(metricsPath, router)
  45. router.Get(versionPath, func(w http.ResponseWriter, r *http.Request) {
  46. render.JSON(w, r, version.Get())
  47. })
  48. router.Get(providerStatusPath, func(w http.ResponseWriter, r *http.Request) {
  49. err := dataprovider.GetProviderStatus()
  50. if err != nil {
  51. sendAPIResponse(w, r, err, "", http.StatusInternalServerError)
  52. } else {
  53. sendAPIResponse(w, r, err, "Alive", http.StatusOK)
  54. }
  55. })
  56. router.Get(activeConnectionsPath, func(w http.ResponseWriter, r *http.Request) {
  57. render.JSON(w, r, common.Connections.GetStats())
  58. })
  59. router.Delete(activeConnectionsPath+"/{connectionID}", handleCloseConnection)
  60. router.Get(quotaScanPath, getQuotaScans)
  61. router.Post(quotaScanPath, startQuotaScan)
  62. router.Get(quotaScanVFolderPath, getVFolderQuotaScans)
  63. router.Post(quotaScanVFolderPath, startVFolderQuotaScan)
  64. router.Get(userPath, getUsers)
  65. router.Post(userPath, addUser)
  66. router.Get(userPath+"/{userID}", getUserByID)
  67. router.Put(userPath+"/{userID}", updateUser)
  68. router.Delete(userPath+"/{userID}", deleteUser)
  69. router.Get(folderPath, getFolders)
  70. router.Post(folderPath, addFolder)
  71. router.Delete(folderPath, deleteFolderByPath)
  72. router.Get(dumpDataPath, dumpData)
  73. router.Get(loadDataPath, loadData)
  74. router.Put(updateUsedQuotaPath, updateUserQuotaUsage)
  75. router.Put(updateFolderUsedQuotaPath, updateVFolderQuotaUsage)
  76. if enableWebAdmin {
  77. router.Get(webUsersPath, handleGetWebUsers)
  78. router.Get(webUserPath, handleWebAddUserGet)
  79. router.Get(webUserPath+"/{userID}", handleWebUpdateUserGet)
  80. router.Post(webUserPath, handleWebAddUserPost)
  81. router.Post(webUserPath+"/{userID}", handleWebUpdateUserPost)
  82. router.Get(webConnectionsPath, handleWebGetConnections)
  83. router.Get(webFoldersPath, handleWebGetFolders)
  84. router.Get(webFolderPath, handleWebAddFolderGet)
  85. router.Post(webFolderPath, handleWebAddFolderPost)
  86. }
  87. })
  88. if enableWebAdmin {
  89. router.Group(func(router chi.Router) {
  90. compressor := middleware.NewCompressor(5)
  91. router.Use(compressor.Handler)
  92. fileServer(router, webStaticFilesPath, http.Dir(staticFilesPath))
  93. })
  94. }
  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 common.Connections.Close(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. if path != "/" && path[len(path)-1] != '/' {
  111. r.Get(path, http.RedirectHandler(path+"/", http.StatusMovedPermanently).ServeHTTP)
  112. path += "/"
  113. }
  114. path += "*"
  115. r.Get(path, func(w http.ResponseWriter, r *http.Request) {
  116. rctx := chi.RouteContext(r.Context())
  117. pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*")
  118. fs := http.StripPrefix(pathPrefix, http.FileServer(root))
  119. fs.ServeHTTP(w, r)
  120. })
  121. }