serve restic: Print actual listener address

This commit is contained in:
Matt Holt 2018-04-04 07:56:26 -06:00 committed by Nick Craig-Wood
parent 5b8977a053
commit e13f65b953
5 changed files with 80 additions and 15 deletions

View File

@ -72,8 +72,12 @@ func newServer(f fs.Fs, opt *httplib.Options) *server {
// serve runs the http server - doesn't return
func (s *server) serve() {
err := s.srv.Serve()
if err != nil {
fs.Errorf(s.f, "Opening listener: %v", err)
}
fs.Logf(s.f, "Serving on %s", s.srv.URL())
s.srv.Serve()
s.srv.Wait()
}
// handler reads incoming requests and dispatches them

View File

@ -7,6 +7,7 @@ import (
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"time"
@ -24,10 +25,11 @@ var Help = `
Use --addr to specify which IP address and port the server should
listen on, eg --addr 1.2.3.4:8000 or --addr :8080 to listen to all
IPs. By default it only listens on localhost.
IPs. By default it only listens on localhost. You can use port
:0 to let the OS choose an available port.
If you set --addr to listen on a public or LAN accessible IP address
then using Authentication if advised - see the next section for info.
then using Authentication is advised - see the next section for info.
--server-read-timeout and --server-write-timeout can be used to
control the timeouts on the server. Note that this is the total time
@ -98,6 +100,8 @@ var DefaultOpt = Options{
type Server struct {
Opt Options
handler http.Handler // original handler
listener net.Listener
waitChan chan struct{} // for waiting on the listener to close
httpServer *http.Server
basicPassHashed string
useSSL bool // if server is configured for SSL/TLS
@ -178,15 +182,52 @@ func NewServer(handler http.Handler, opt *Options) *Server {
return s
}
// Serve runs the server - doesn't return
func (s *Server) Serve() {
var err error
if s.useSSL {
err = s.httpServer.ListenAndServeTLS(s.Opt.SslCert, s.Opt.SslKey)
} else {
err = s.httpServer.ListenAndServe()
// Serve runs the server - returns an error only if
// the listener was not started; does not block, so
// use s.Wait() to block on the listener indefinitely.
func (s *Server) Serve() error {
ln, err := net.Listen("tcp", s.httpServer.Addr)
if err != nil {
return err
}
log.Printf("Error while serving HTTP: %v", err)
s.listener = ln
s.waitChan = make(chan struct{})
go func() {
var err error
if s.useSSL {
// hacky hack to get this to work with old Go versions, which
// don't have ServeTLS on http.Server; see PR #2194.
type tlsServer interface {
ServeTLS(ln net.Listener, cert, key string) error
}
srvIface := interface{}(s.httpServer)
if tlsSrv, ok := srvIface.(tlsServer); ok {
// yay -- we get easy TLS support with HTTP/2
err = tlsSrv.ServeTLS(s.listener, s.Opt.SslCert, s.Opt.SslKey)
} else {
// oh well -- we can still do TLS but might not have HTTP/2
tlsConfig := new(tls.Config)
tlsConfig.Certificates = make([]tls.Certificate, 1)
tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(s.Opt.SslCert, s.Opt.SslKey)
if err != nil {
log.Printf("Error loading key pair: %v", err)
}
tlsLn := tls.NewListener(s.listener, tlsConfig)
err = s.httpServer.Serve(tlsLn)
}
} else {
err = s.httpServer.Serve(s.listener)
}
if err != nil {
log.Printf("Error on serving HTTP server: %v", err)
}
}()
return nil
}
// Wait blocks while the listener is open.
func (s *Server) Wait() {
<-s.waitChan
}
// Close shuts the running server down
@ -194,7 +235,9 @@ func (s *Server) Close() {
err := closeServer(s.httpServer)
if err != nil {
log.Printf("Error on closing HTTP server: %v", err)
return
}
close(s.waitChan)
}
// URL returns the serving address of this server
@ -203,5 +246,11 @@ func (s *Server) URL() string {
if s.useSSL {
proto = "https"
}
return fmt.Sprintf("%s://%s/", proto, s.Opt.ListenAddr)
addr := s.Opt.ListenAddr
if s.listener != nil {
// prefer actual listener address; required if using 0-port
// (i.e. port assigned by operating system)
addr = s.listener.Addr().String()
}
return fmt.Sprintf("%s://%s/", proto, addr)
}

View File

@ -169,8 +169,12 @@ func newServer(f fs.Fs, opt *httplib.Options) *server {
// serve runs the http server - doesn't return
func (s *server) serve() {
err := s.srv.Serve()
if err != nil {
fs.Errorf(s.f, "Opening listener: %v", err)
}
fs.Logf(s.f, "Serving restic REST API on %s", s.srv.URL())
s.srv.Serve()
s.srv.Wait()
}
var matchData = regexp.MustCompile("(?:^|/)data/([^/]{2,})$")

View File

@ -88,8 +88,12 @@ func newWebDAV(f fs.Fs, opt *httplib.Options) *WebDAV {
// serve runs the http server - doesn't return
func (w *WebDAV) serve() {
err := w.srv.Serve()
if err != nil {
fs.Errorf(w.f, "Opening listener: %v", err)
}
fs.Logf(w.f, "WebDav Server started on %s", w.srv.URL())
w.srv.Serve()
w.srv.Wait()
}
// logRequest is called by the webdav module on every request

View File

@ -58,8 +58,12 @@ func newServer(opt *Options) *server {
// serve runs the http server - doesn't return
func (s *server) serve() {
err := s.srv.Serve()
if err != nil {
fs.Errorf(nil, "Opening listener: %v", err)
}
fs.Logf(nil, "Serving remote control on %s", s.srv.URL())
s.srv.Serve()
s.srv.Wait()
}
// handler reads incoming requests and dispatches them