@@ -1309,6 +1309,7 @@ func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *ht
13091309 return nil
13101310}
13111311
1312+ // postContainersCopy is deprecated in favor of getContainersArchivePath.
13121313func (s * Server ) postContainersCopy (version version.Version , w http.ResponseWriter , r * http.Request , vars map [string ]string ) error {
13131314 if vars == nil {
13141315 return fmt .Errorf ("Missing parameter" )
@@ -1348,6 +1349,104 @@ func (s *Server) postContainersCopy(version version.Version, w http.ResponseWrit
13481349 return nil
13491350}
13501351
1352+ // // Encode the stat to JSON, base64 encode, and place in a header.
1353+ func setContainerPathStatHeader (stat * types.ContainerPathStat , header http.Header ) error {
1354+ statJSON , err := json .Marshal (stat )
1355+ if err != nil {
1356+ return err
1357+ }
1358+
1359+ header .Set (
1360+ "X-Docker-Container-Path-Stat" ,
1361+ base64 .StdEncoding .EncodeToString (statJSON ),
1362+ )
1363+
1364+ return nil
1365+ }
1366+
1367+ func (s * Server ) headContainersArchive (version version.Version , w http.ResponseWriter , r * http.Request , vars map [string ]string ) error {
1368+ if vars == nil {
1369+ return fmt .Errorf ("Missing parameter" )
1370+ }
1371+ if err := parseForm (r ); err != nil {
1372+ return err
1373+ }
1374+
1375+ name := vars ["name" ]
1376+ path := r .Form .Get ("path" )
1377+
1378+ switch {
1379+ case name == "" :
1380+ return fmt .Errorf ("bad parameter: 'name' cannot be empty" )
1381+ case path == "" :
1382+ return fmt .Errorf ("bad parameter: 'path' cannot be empty" )
1383+ }
1384+
1385+ stat , err := s .daemon .ContainerStatPath (name , path )
1386+ if err != nil {
1387+ return err
1388+ }
1389+
1390+ return setContainerPathStatHeader (stat , w .Header ())
1391+ }
1392+
1393+ func (s * Server ) getContainersArchive (version version.Version , w http.ResponseWriter , r * http.Request , vars map [string ]string ) error {
1394+ if vars == nil {
1395+ return fmt .Errorf ("Missing parameter" )
1396+ }
1397+ if err := parseForm (r ); err != nil {
1398+ return err
1399+ }
1400+
1401+ name := vars ["name" ]
1402+ path := r .Form .Get ("path" )
1403+
1404+ switch {
1405+ case name == "" :
1406+ return fmt .Errorf ("bad parameter: 'name' cannot be empty" )
1407+ case path == "" :
1408+ return fmt .Errorf ("bad parameter: 'path' cannot be empty" )
1409+ }
1410+
1411+ tarArchive , stat , err := s .daemon .ContainerArchivePath (name , path )
1412+ if err != nil {
1413+ return err
1414+ }
1415+ defer tarArchive .Close ()
1416+
1417+ if err := setContainerPathStatHeader (stat , w .Header ()); err != nil {
1418+ return err
1419+ }
1420+
1421+ w .Header ().Set ("Content-Type" , "application/x-tar" )
1422+ _ , err = io .Copy (w , tarArchive )
1423+
1424+ return err
1425+ }
1426+
1427+ func (s * Server ) putContainersArchive (version version.Version , w http.ResponseWriter , r * http.Request , vars map [string ]string ) error {
1428+ if vars == nil {
1429+ return fmt .Errorf ("Missing parameter" )
1430+ }
1431+ if err := parseForm (r ); err != nil {
1432+ return err
1433+ }
1434+
1435+ name := vars ["name" ]
1436+ path := r .Form .Get ("path" )
1437+
1438+ noOverwriteDirNonDir := boolValue (r , "noOverwriteDirNonDir" )
1439+
1440+ switch {
1441+ case name == "" :
1442+ return fmt .Errorf ("bad parameter: 'name' cannot be empty" )
1443+ case path == "" :
1444+ return fmt .Errorf ("bad parameter: 'path' cannot be empty" )
1445+ }
1446+
1447+ return s .daemon .ContainerExtractToDir (name , path , noOverwriteDirNonDir , r .Body )
1448+ }
1449+
13511450func (s * Server ) postContainerExecCreate (version version.Version , w http.ResponseWriter , r * http.Request , vars map [string ]string ) error {
13521451 if err := parseForm (r ); err != nil {
13531452 return err
@@ -1536,6 +1635,9 @@ func createRouter(s *Server) *mux.Router {
15361635 ProfilerSetup (r , "/debug/" )
15371636 }
15381637 m := map [string ]map [string ]HttpApiFunc {
1638+ "HEAD" : {
1639+ "/containers/{name:.*}/archive" : s .headContainersArchive ,
1640+ },
15391641 "GET" : {
15401642 "/_ping" : s .ping ,
15411643 "/events" : s .getEvents ,
@@ -1557,6 +1659,7 @@ func createRouter(s *Server) *mux.Router {
15571659 "/containers/{name:.*}/stats" : s .getContainersStats ,
15581660 "/containers/{name:.*}/attach/ws" : s .wsContainersAttach ,
15591661 "/exec/{id:.*}/json" : s .getExecByID ,
1662+ "/containers/{name:.*}/archive" : s .getContainersArchive ,
15601663 },
15611664 "POST" : {
15621665 "/auth" : s .postAuth ,
@@ -1582,6 +1685,9 @@ func createRouter(s *Server) *mux.Router {
15821685 "/exec/{name:.*}/resize" : s .postContainerExecResize ,
15831686 "/containers/{name:.*}/rename" : s .postContainerRename ,
15841687 },
1688+ "PUT" : {
1689+ "/containers/{name:.*}/archive" : s .putContainersArchive ,
1690+ },
15851691 "DELETE" : {
15861692 "/containers/{name:.*}" : s .deleteContainers ,
15871693 "/images/{name:.*}" : s .deleteImages ,
0 commit comments