mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 23:00:55 +03:00
@@ -159,7 +159,11 @@ func TestUserInvalidParams(t *testing.T) {
|
||||
HomeDir: "invalid",
|
||||
}
|
||||
c := &Configuration{
|
||||
BindPort: 9000,
|
||||
Bindings: []Binding{
|
||||
{
|
||||
Port: 9000,
|
||||
},
|
||||
},
|
||||
}
|
||||
server, err := newServer(c, configDir)
|
||||
assert.NoError(t, err)
|
||||
@@ -670,7 +674,11 @@ func TestBasicUsersCache(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
c := &Configuration{
|
||||
BindPort: 9000,
|
||||
Bindings: []Binding{
|
||||
{
|
||||
Port: 9000,
|
||||
},
|
||||
},
|
||||
Cache: Cache{
|
||||
Users: UsersCacheConfig{
|
||||
MaxSize: 50,
|
||||
@@ -782,7 +790,11 @@ func TestUsersCacheSizeAndExpiration(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
c := &Configuration{
|
||||
BindPort: 9000,
|
||||
Bindings: []Binding{
|
||||
{
|
||||
Port: 9000,
|
||||
},
|
||||
},
|
||||
Cache: Cache{
|
||||
Users: UsersCacheConfig{
|
||||
MaxSize: 3,
|
||||
@@ -926,7 +938,11 @@ func TestUsersCacheSizeAndExpiration(t *testing.T) {
|
||||
|
||||
func TestRecoverer(t *testing.T) {
|
||||
c := &Configuration{
|
||||
BindPort: 9000,
|
||||
Bindings: []Binding{
|
||||
{
|
||||
Port: 9000,
|
||||
},
|
||||
},
|
||||
}
|
||||
server, err := newServer(c, configDir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -53,13 +53,9 @@ func newServer(config *Configuration, configDir string) (*webDavServer, error) {
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func (s *webDavServer) listenAndServe() error {
|
||||
addr := fmt.Sprintf("%s:%d", s.config.BindAddress, s.config.BindPort)
|
||||
s.status.IsActive = true
|
||||
s.status.Address = addr
|
||||
s.status.Protocol = "HTTP"
|
||||
func (s *webDavServer) listenAndServe(binding Binding) error {
|
||||
httpServer := &http.Server{
|
||||
Addr: addr,
|
||||
Addr: binding.GetAddress(),
|
||||
Handler: server,
|
||||
ReadHeaderTimeout: 30 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
@@ -76,17 +72,17 @@ func (s *webDavServer) listenAndServe() error {
|
||||
OptionsPassthrough: true,
|
||||
})
|
||||
httpServer.Handler = c.Handler(server)
|
||||
} else {
|
||||
httpServer.Handler = server
|
||||
}
|
||||
if s.certMgr != nil {
|
||||
s.status.Protocol = "HTTPS"
|
||||
if s.certMgr != nil && binding.EnableHTTPS {
|
||||
server.status.Bindings = append(server.status.Bindings, binding)
|
||||
httpServer.TLSConfig = &tls.Config{
|
||||
GetCertificate: s.certMgr.GetCertificateFunc(),
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
return httpServer.ListenAndServeTLS("", "")
|
||||
}
|
||||
binding.EnableHTTPS = false
|
||||
server.status.Bindings = append(server.status.Bindings, binding)
|
||||
return httpServer.ListenAndServe()
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
package webdavd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/utils"
|
||||
)
|
||||
@@ -25,9 +27,8 @@ var (
|
||||
|
||||
// ServiceStatus defines the service status
|
||||
type ServiceStatus struct {
|
||||
IsActive bool `json:"is_active"`
|
||||
Address string `json:"address"`
|
||||
Protocol string `json:"protocol"`
|
||||
IsActive bool `json:"is_active"`
|
||||
Bindings []Binding `json:"bindings"`
|
||||
}
|
||||
|
||||
// Cors configuration
|
||||
@@ -59,11 +60,33 @@ type Cache struct {
|
||||
MimeTypes MimeCacheConfig `json:"mime_types" mapstructure:"mime_types"`
|
||||
}
|
||||
|
||||
// Binding defines the configuration for a network listener
|
||||
type Binding struct {
|
||||
// The address to listen on. A blank value means listen on all available network interfaces.
|
||||
Address string `json:"address" mapstructure:"address"`
|
||||
// The port used for serving requests
|
||||
Port int `json:"port" mapstructure:"port"`
|
||||
// you also need to provide a certificate for enabling HTTPS
|
||||
EnableHTTPS bool `json:"enable_https" mapstructure:"enable_https"`
|
||||
}
|
||||
|
||||
// GetAddress returns the binding address
|
||||
func (b *Binding) GetAddress() string {
|
||||
return fmt.Sprintf("%s:%d", b.Address, b.Port)
|
||||
}
|
||||
|
||||
// IsValid returns true if the binding port is > 0
|
||||
func (b *Binding) IsValid() bool {
|
||||
return b.Port > 0
|
||||
}
|
||||
|
||||
// Configuration defines the configuration for the WevDAV server
|
||||
type Configuration struct {
|
||||
// The port used for serving FTP requests
|
||||
// Addresses and ports to bind to
|
||||
Bindings []Binding `json:"bindings" mapstructure:"bindings"`
|
||||
// Deprecated: please use Bindings
|
||||
BindPort int `json:"bind_port" mapstructure:"bind_port"`
|
||||
// The address to listen on. A blank value means listen on all available network interfaces.
|
||||
// Deprecated: please use Bindings
|
||||
BindAddress string `json:"bind_address" mapstructure:"bind_address"`
|
||||
// If files containing a certificate and matching private key for the server are provided the server will expect
|
||||
// HTTPS connections.
|
||||
@@ -85,6 +108,17 @@ func GetStatus() ServiceStatus {
|
||||
return server.status
|
||||
}
|
||||
|
||||
// ShouldBind returns true if there is at least a valid binding
|
||||
func (c *Configuration) ShouldBind() bool {
|
||||
for _, binding := range c.Bindings {
|
||||
if binding.IsValid() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Initialize configures and starts the WebDAV server
|
||||
func (c *Configuration) Initialize(configDir string) error {
|
||||
var err error
|
||||
@@ -96,11 +130,31 @@ func (c *Configuration) Initialize(configDir string) error {
|
||||
if !c.Cache.MimeTypes.Enabled {
|
||||
mimeTypeCache.maxSize = 0
|
||||
}
|
||||
if !c.ShouldBind() {
|
||||
return common.ErrNoBinding
|
||||
}
|
||||
server, err = newServer(c, configDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return server.listenAndServe()
|
||||
|
||||
server.status.Bindings = nil
|
||||
|
||||
exitChannel := make(chan error)
|
||||
|
||||
for _, binding := range c.Bindings {
|
||||
if !binding.IsValid() {
|
||||
continue
|
||||
}
|
||||
|
||||
go func(binding Binding) {
|
||||
exitChannel <- server.listenAndServe(binding)
|
||||
}(binding)
|
||||
}
|
||||
|
||||
server.status.IsActive = true
|
||||
|
||||
return <-exitChannel
|
||||
}
|
||||
|
||||
// ReloadTLSCertificate reloads the TLS certificate and key from the configured paths
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/drakkan/sftpgo/httpd"
|
||||
"github.com/drakkan/sftpgo/kms"
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/vfs"
|
||||
"github.com/drakkan/sftpgo/webdavd"
|
||||
)
|
||||
@@ -143,11 +144,19 @@ func TestMain(m *testing.M) {
|
||||
|
||||
// required to test sftpfs
|
||||
sftpdConf := config.GetSFTPDConfig()
|
||||
sftpdConf.BindPort = 9022
|
||||
sftpdConf.Bindings = []sftpd.Binding{
|
||||
{
|
||||
Port: 9022,
|
||||
},
|
||||
}
|
||||
sftpdConf.HostKeys = []string{filepath.Join(os.TempDir(), "id_ecdsa")}
|
||||
|
||||
webDavConf := config.GetWebDAVDConfig()
|
||||
webDavConf.BindPort = webDavServerPort
|
||||
webDavConf.Bindings = []webdavd.Binding{
|
||||
{
|
||||
Port: webDavServerPort,
|
||||
},
|
||||
}
|
||||
webDavConf.Cors = webdavd.Cors{
|
||||
Enabled: true,
|
||||
AllowedOrigins: []string{"*"},
|
||||
@@ -196,9 +205,9 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
}()
|
||||
|
||||
waitTCPListening(fmt.Sprintf("%s:%d", webDavConf.BindAddress, webDavConf.BindPort))
|
||||
waitTCPListening(webDavConf.Bindings[0].GetAddress())
|
||||
waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
|
||||
waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
|
||||
waitTCPListening(sftpdConf.Bindings[0].GetAddress())
|
||||
webdavd.ReloadTLSCertificate() //nolint:errcheck
|
||||
|
||||
exitCode := m.Run()
|
||||
@@ -213,7 +222,15 @@ func TestMain(m *testing.M) {
|
||||
|
||||
func TestInitialization(t *testing.T) {
|
||||
cfg := webdavd.Configuration{
|
||||
BindPort: 1234,
|
||||
Bindings: []webdavd.Binding{
|
||||
{
|
||||
Port: 1234,
|
||||
EnableHTTPS: true,
|
||||
},
|
||||
{
|
||||
Port: 0,
|
||||
},
|
||||
},
|
||||
CertificateFile: "missing path",
|
||||
CertificateKeyFile: "bad path",
|
||||
}
|
||||
@@ -221,13 +238,21 @@ func TestInitialization(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
|
||||
cfg.Cache = config.GetWebDAVDConfig().Cache
|
||||
cfg.BindPort = webDavServerPort
|
||||
cfg.Bindings[0].Port = webDavServerPort
|
||||
cfg.CertificateFile = certPath
|
||||
cfg.CertificateKeyFile = keyPath
|
||||
err = cfg.Initialize(configDir)
|
||||
assert.Error(t, err)
|
||||
err = webdavd.ReloadTLSCertificate()
|
||||
assert.NoError(t, err)
|
||||
|
||||
cfg.Bindings = []webdavd.Binding{
|
||||
{
|
||||
Port: 0,
|
||||
},
|
||||
}
|
||||
err = cfg.Initialize(configDir)
|
||||
assert.EqualError(t, err, common.ErrNoBinding.Error())
|
||||
}
|
||||
|
||||
func TestBasicHandling(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user