github.com/getong/docker@v1.13.1/api/server/router/container/copy.go (about) 1 package container 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "fmt" 7 "io" 8 "net/http" 9 "os" 10 "strings" 11 12 "github.com/docker/docker/api/server/httputils" 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/api/types/versions" 15 "golang.org/x/net/context" 16 ) 17 18 // postContainersCopy is deprecated in favor of getContainersArchive. 19 func (s *containerRouter) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 20 // Deprecated since 1.8, Errors out since 1.12 21 version := httputils.VersionFromContext(ctx) 22 if versions.GreaterThanOrEqualTo(version, "1.24") { 23 w.WriteHeader(http.StatusNotFound) 24 return nil 25 } 26 if err := httputils.CheckForJSON(r); err != nil { 27 return err 28 } 29 30 cfg := types.CopyConfig{} 31 if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { 32 return err 33 } 34 35 if cfg.Resource == "" { 36 return fmt.Errorf("Path cannot be empty") 37 } 38 39 data, err := s.backend.ContainerCopy(vars["name"], cfg.Resource) 40 if err != nil { 41 if strings.Contains(strings.ToLower(err.Error()), "no such container") { 42 w.WriteHeader(http.StatusNotFound) 43 return nil 44 } 45 if os.IsNotExist(err) { 46 return fmt.Errorf("Could not find the file %s in container %s", cfg.Resource, vars["name"]) 47 } 48 return err 49 } 50 defer data.Close() 51 52 w.Header().Set("Content-Type", "application/x-tar") 53 if _, err := io.Copy(w, data); err != nil { 54 return err 55 } 56 57 return nil 58 } 59 60 // // Encode the stat to JSON, base64 encode, and place in a header. 61 func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error { 62 statJSON, err := json.Marshal(stat) 63 if err != nil { 64 return err 65 } 66 67 header.Set( 68 "X-Docker-Container-Path-Stat", 69 base64.StdEncoding.EncodeToString(statJSON), 70 ) 71 72 return nil 73 } 74 75 func (s *containerRouter) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 76 v, err := httputils.ArchiveFormValues(r, vars) 77 if err != nil { 78 return err 79 } 80 81 stat, err := s.backend.ContainerStatPath(v.Name, v.Path) 82 if err != nil { 83 return err 84 } 85 86 return setContainerPathStatHeader(stat, w.Header()) 87 } 88 89 func (s *containerRouter) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 90 v, err := httputils.ArchiveFormValues(r, vars) 91 if err != nil { 92 return err 93 } 94 95 tarArchive, stat, err := s.backend.ContainerArchivePath(v.Name, v.Path) 96 if err != nil { 97 return err 98 } 99 defer tarArchive.Close() 100 101 if err := setContainerPathStatHeader(stat, w.Header()); err != nil { 102 return err 103 } 104 105 w.Header().Set("Content-Type", "application/x-tar") 106 _, err = io.Copy(w, tarArchive) 107 108 return err 109 } 110 111 func (s *containerRouter) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 112 v, err := httputils.ArchiveFormValues(r, vars) 113 if err != nil { 114 return err 115 } 116 117 noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir") 118 return s.backend.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body) 119 }