2019-10-07 16:19:01 +00:00
|
|
|
// Package httpd implements REST API and Web interface for SFTPGo.
|
|
|
|
// REST API allows to manage users and quota and to get real time reports for the active connections
|
|
|
|
// with possibility of forcibly closing a connection.
|
|
|
|
// The OpenAPI 3 schema for the exposed API can be found inside the source tree:
|
|
|
|
// https://github.com/drakkan/sftpgo/tree/master/api/schema/openapi.yaml
|
|
|
|
// A basic Web interface to manage users and connections is provided too
|
|
|
|
package httpd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/drakkan/sftpgo/dataprovider"
|
|
|
|
"github.com/drakkan/sftpgo/logger"
|
|
|
|
"github.com/go-chi/chi"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2019-10-07 20:37:28 +00:00
|
|
|
logSender = "httpd"
|
2019-10-07 16:19:01 +00:00
|
|
|
activeConnectionsPath = "/api/v1/connection"
|
|
|
|
quotaScanPath = "/api/v1/quota_scan"
|
|
|
|
userPath = "/api/v1/user"
|
|
|
|
versionPath = "/api/v1/version"
|
2019-11-14 17:48:01 +00:00
|
|
|
providerStatusPath = "/api/v1/providerstatus"
|
2019-12-27 22:12:44 +00:00
|
|
|
dumpDataPath = "/api/v1/dumpdata"
|
|
|
|
loadDataPath = "/api/v1/loaddata"
|
2019-10-07 16:19:01 +00:00
|
|
|
metricsPath = "/metrics"
|
2019-10-07 20:37:28 +00:00
|
|
|
webBasePath = "/web"
|
|
|
|
webUsersPath = "/web/users"
|
|
|
|
webUserPath = "/web/user"
|
|
|
|
webConnectionsPath = "/web/connections"
|
2019-10-08 06:20:26 +00:00
|
|
|
webStaticFilesPath = "/static"
|
2019-12-27 22:12:44 +00:00
|
|
|
maxRestoreSize = 10485760 // 10 MB
|
2019-10-07 16:19:01 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
router *chi.Mux
|
|
|
|
dataProvider dataprovider.Provider
|
2019-12-27 22:12:44 +00:00
|
|
|
backupsPath string
|
2019-10-07 16:19:01 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Conf httpd daemon configuration
|
|
|
|
type Conf struct {
|
|
|
|
// The port used for serving HTTP requests. 0 disable the HTTP server. Default: 8080
|
|
|
|
BindPort int `json:"bind_port" mapstructure:"bind_port"`
|
|
|
|
// The address to listen on. A blank value means listen on all available network interfaces. Default: "127.0.0.1"
|
|
|
|
BindAddress string `json:"bind_address" mapstructure:"bind_address"`
|
|
|
|
// Path to the HTML web templates. This can be an absolute path or a path relative to the config dir
|
|
|
|
TemplatesPath string `json:"templates_path" mapstructure:"templates_path"`
|
|
|
|
// Path to the static files for the web interface. This can be an absolute path or a path relative to the config dir
|
|
|
|
StaticFilesPath string `json:"static_files_path" mapstructure:"static_files_path"`
|
2019-12-27 22:12:44 +00:00
|
|
|
// Path to the backup directory. This can be an absolute path or a path relative to the config dir
|
|
|
|
BackupsPath string `json:"backups_path" mapstructure:"backups_path"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// BackupData defines the structure for the backup/restore files
|
|
|
|
type BackupData struct {
|
|
|
|
Users []dataprovider.User `json:"users"`
|
2019-10-07 16:19:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type apiResponse struct {
|
|
|
|
Error string `json:"error"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
HTTPStatus int `json:"status"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetDataProvider sets the data provider to use to fetch the data about users
|
|
|
|
func SetDataProvider(provider dataprovider.Provider) {
|
|
|
|
dataProvider = provider
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the HTTP server
|
|
|
|
func (c Conf) Initialize(configDir string) error {
|
|
|
|
logger.Debug(logSender, "", "initializing HTTP server with config %+v", c)
|
2019-12-27 22:12:44 +00:00
|
|
|
backupsPath = c.BackupsPath
|
|
|
|
if !filepath.IsAbs(backupsPath) {
|
|
|
|
backupsPath = filepath.Join(configDir, backupsPath)
|
|
|
|
}
|
2019-10-07 16:19:01 +00:00
|
|
|
staticFilesPath := c.StaticFilesPath
|
|
|
|
if !filepath.IsAbs(staticFilesPath) {
|
|
|
|
staticFilesPath = filepath.Join(configDir, staticFilesPath)
|
|
|
|
}
|
|
|
|
templatesPath := c.TemplatesPath
|
|
|
|
if !filepath.IsAbs(templatesPath) {
|
|
|
|
templatesPath = filepath.Join(configDir, templatesPath)
|
|
|
|
}
|
|
|
|
loadTemplates(templatesPath)
|
|
|
|
initializeRouter(staticFilesPath)
|
|
|
|
httpServer := &http.Server{
|
|
|
|
Addr: fmt.Sprintf("%s:%d", c.BindAddress, c.BindPort),
|
|
|
|
Handler: router,
|
|
|
|
ReadTimeout: 300 * time.Second,
|
|
|
|
WriteTimeout: 300 * time.Second,
|
2019-11-14 17:48:01 +00:00
|
|
|
MaxHeaderBytes: 1 << 16, // 64KB
|
2019-10-07 16:19:01 +00:00
|
|
|
}
|
|
|
|
return httpServer.ListenAndServe()
|
|
|
|
}
|