123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- package container // import "github.com/docker/docker/api/server/router/container"
- import (
- "compress/flate"
- "compress/gzip"
- "context"
- "encoding/base64"
- "encoding/json"
- "errors"
- "io"
- "net/http"
- "github.com/docker/docker/api/server/httputils"
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/versions"
- "github.com/docker/docker/errdefs"
- gddohttputil "github.com/golang/gddo/httputil"
- )
- 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 {
- if err == io.EOF {
- return errdefs.InvalidParameter(errors.New("got EOF while reading request body"))
- }
- return errdefs.InvalidParameter(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 writeCompressedResponse(w http.ResponseWriter, r *http.Request, body io.Reader) error {
- var cw io.Writer
- switch gddohttputil.NegotiateContentEncoding(r, []string{"gzip", "deflate"}) {
- case "gzip":
- gw := gzip.NewWriter(w)
- defer gw.Close()
- cw = gw
- w.Header().Set("Content-Encoding", "gzip")
- case "deflate":
- fw, err := flate.NewWriter(w, flate.DefaultCompression)
- if err != nil {
- return err
- }
- defer fw.Close()
- cw = fw
- w.Header().Set("Content-Encoding", "deflate")
- default:
- cw = w
- }
- _, err := io.Copy(cw, body)
- return err
- }
- 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")
- return writeCompressedResponse(w, r, tarArchive)
- }
- 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)
- }
|