github.com/artpar/rclone@v1.67.3/cmd/serve/docker/serve.go (about) 1 package docker 2 3 import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "net" 8 "net/http" 9 "os" 10 "path/filepath" 11 "runtime" 12 13 "github.com/artpar/rclone/fs" 14 "github.com/artpar/rclone/lib/atexit" 15 "github.com/artpar/rclone/lib/file" 16 ) 17 18 // Server connects plugin with docker daemon by protocol 19 type Server http.Server 20 21 // NewServer creates new docker plugin server 22 func NewServer(drv *Driver) *Server { 23 return &Server{Handler: newRouter(drv)} 24 } 25 26 // Shutdown the server 27 func (s *Server) Shutdown(ctx context.Context) error { 28 hs := (*http.Server)(s) 29 return hs.Shutdown(ctx) 30 } 31 32 func (s *Server) serve(listener net.Listener, addr, tempFile string) error { 33 if tempFile != "" { 34 atexit.Register(func() { 35 // remove spec file or self-created unix socket 36 fs.Debugf(nil, "Removing stale file %s", tempFile) 37 _ = os.Remove(tempFile) 38 }) 39 } 40 hs := (*http.Server)(s) 41 return hs.Serve(listener) 42 } 43 44 // ServeUnix makes the handler to listen for requests in a unix socket. 45 // It also creates the socket file in the right directory for docker to read. 46 func (s *Server) ServeUnix(path string, gid int) error { 47 listener, socketPath, err := newUnixListener(path, gid) 48 if err != nil { 49 return err 50 } 51 if socketPath != "" { 52 path = socketPath 53 fs.Infof(nil, "Serving unix socket: %s", path) 54 } else { 55 fs.Infof(nil, "Serving systemd socket") 56 } 57 return s.serve(listener, path, socketPath) 58 } 59 60 // ServeTCP makes the handler listen for request on a given TCP address. 61 // It also writes the spec file in the right directory for docker to read. 62 func (s *Server) ServeTCP(addr, specDir string, tlsConfig *tls.Config, noSpec bool) error { 63 listener, err := net.Listen("tcp", addr) 64 if err != nil { 65 return err 66 } 67 if tlsConfig != nil { 68 tlsConfig.NextProtos = []string{"http/1.1"} 69 listener = tls.NewListener(listener, tlsConfig) 70 } 71 addr = listener.Addr().String() 72 specFile := "" 73 if !noSpec { 74 specFile, err = writeSpecFile(addr, "tcp", specDir) 75 if err != nil { 76 return err 77 } 78 } 79 fs.Infof(nil, "Serving TCP socket: %s", addr) 80 return s.serve(listener, addr, specFile) 81 } 82 83 func writeSpecFile(addr, proto, specDir string) (string, error) { 84 if specDir == "" && runtime.GOOS == "windows" { 85 specDir = os.TempDir() 86 } 87 if specDir == "" { 88 specDir = defSpecDir 89 } 90 if err := file.MkdirAll(specDir, 0755); err != nil { 91 return "", err 92 } 93 specFile := filepath.Join(specDir, "rclone.spec") 94 url := fmt.Sprintf("%s://%s", proto, addr) 95 if err := os.WriteFile(specFile, []byte(url), 0644); err != nil { 96 return "", err 97 } 98 fs.Debugf(nil, "Plugin spec has been written to %s", specFile) 99 return specFile, nil 100 }