| package container |
| |
| import ( |
| "encoding/base64" |
| "encoding/json" |
| "io" |
| "net/http" |
| |
| "github.com/docker/docker/api/server/httputils" |
| "github.com/docker/docker/api/types" |
| "github.com/docker/docker/api/types/versions" |
| "golang.org/x/net/context" |
| ) |
| |
| type pathError struct{} |
| |
| func (pathError) Error() string { |
| return "Path cannot be empty" |
| } |
| |
| func (pathError) InvalidParameter() {} |
| |
| // postContainersCopy is deprecated in favor of getContainersArchive. |
| func (s *containerRouter) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| // Deprecated since 1.8, Errors out since 1.12 |
| version := httputils.VersionFromContext(ctx) |
| if versions.GreaterThanOrEqualTo(version, "1.24") { |
| w.WriteHeader(http.StatusNotFound) |
| return nil |
| } |
| if err := httputils.CheckForJSON(r); err != nil { |
| return err |
| } |
| |
| cfg := types.CopyConfig{} |
| if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { |
| return err |
| } |
| |
| if cfg.Resource == "" { |
| return pathError{} |
| } |
| |
| data, err := s.backend.ContainerCopy(vars["name"], cfg.Resource) |
| if err != nil { |
| return err |
| } |
| defer data.Close() |
| |
| w.Header().Set("Content-Type", "application/x-tar") |
| _, err = io.Copy(w, data) |
| return err |
| } |
| |
| // // Encode the stat to JSON, base64 encode, and place in a header. |
| func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error { |
| statJSON, err := json.Marshal(stat) |
| if err != nil { |
| return err |
| } |
| |
| header.Set( |
| "X-Docker-Container-Path-Stat", |
| base64.StdEncoding.EncodeToString(statJSON), |
| ) |
| |
| return nil |
| } |
| |
| func (s *containerRouter) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| v, err := httputils.ArchiveFormValues(r, vars) |
| if err != nil { |
| return err |
| } |
| |
| stat, err := s.backend.ContainerStatPath(v.Name, v.Path) |
| if err != nil { |
| return err |
| } |
| |
| return setContainerPathStatHeader(stat, w.Header()) |
| } |
| |
| func (s *containerRouter) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| v, err := httputils.ArchiveFormValues(r, vars) |
| if err != nil { |
| return err |
| } |
| |
| tarArchive, stat, err := s.backend.ContainerArchivePath(v.Name, v.Path) |
| if err != nil { |
| return err |
| } |
| defer tarArchive.Close() |
| |
| if err := setContainerPathStatHeader(stat, w.Header()); err != nil { |
| return err |
| } |
| |
| w.Header().Set("Content-Type", "application/x-tar") |
| _, err = io.Copy(w, tarArchive) |
| |
| return err |
| } |
| |
| func (s *containerRouter) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| v, err := httputils.ArchiveFormValues(r, vars) |
| if err != nil { |
| return err |
| } |
| |
| noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir") |
| copyUIDGID := httputils.BoolValue(r, "copyUIDGID") |
| |
| return s.backend.ContainerExtractToDir(v.Name, v.Path, copyUIDGID, noOverwriteDirNonDir, r.Body) |
| } |