github.com/rentongzhang/docker@v1.8.2-rc1/api/server/server.go (about)

     1  package server
     2  
     3  import (
     4  	"crypto/tls"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"net"
    10  	"net/http"
    11  	"os"
    12  	"runtime"
    13  	"strconv"
    14  	"strings"
    15  	"time"
    16  
    17  	"github.com/gorilla/mux"
    18  	"golang.org/x/net/websocket"
    19  
    20  	"github.com/Sirupsen/logrus"
    21  	"github.com/docker/docker/api"
    22  	"github.com/docker/docker/api/types"
    23  	"github.com/docker/docker/autogen/dockerversion"
    24  	"github.com/docker/docker/builder"
    25  	"github.com/docker/docker/cliconfig"
    26  	"github.com/docker/docker/daemon"
    27  	"github.com/docker/docker/graph"
    28  	"github.com/docker/docker/pkg/ioutils"
    29  	"github.com/docker/docker/pkg/jsonmessage"
    30  	"github.com/docker/docker/pkg/parsers"
    31  	"github.com/docker/docker/pkg/parsers/filters"
    32  	"github.com/docker/docker/pkg/parsers/kernel"
    33  	"github.com/docker/docker/pkg/signal"
    34  	"github.com/docker/docker/pkg/sockets"
    35  	"github.com/docker/docker/pkg/stdcopy"
    36  	"github.com/docker/docker/pkg/streamformatter"
    37  	"github.com/docker/docker/pkg/ulimit"
    38  	"github.com/docker/docker/pkg/version"
    39  	"github.com/docker/docker/runconfig"
    40  	"github.com/docker/docker/utils"
    41  )
    42  
    43  type ServerConfig struct {
    44  	Logging     bool
    45  	EnableCors  bool
    46  	CorsHeaders string
    47  	Version     string
    48  	SocketGroup string
    49  	TLSConfig   *tls.Config
    50  }
    51  
    52  type Server struct {
    53  	daemon  *daemon.Daemon
    54  	cfg     *ServerConfig
    55  	router  *mux.Router
    56  	start   chan struct{}
    57  	servers []serverCloser
    58  }
    59  
    60  func New(cfg *ServerConfig) *Server {
    61  	srv := &Server{
    62  		cfg:   cfg,
    63  		start: make(chan struct{}),
    64  	}
    65  	r := createRouter(srv)
    66  	srv.router = r
    67  	return srv
    68  }
    69  
    70  func (s *Server) Close() {
    71  	for _, srv := range s.servers {
    72  		if err := srv.Close(); err != nil {
    73  			logrus.Error(err)
    74  		}
    75  	}
    76  }
    77  
    78  type serverCloser interface {
    79  	Serve() error
    80  	Close() error
    81  }
    82  
    83  // ServeApi loops through all of the protocols sent in to docker and spawns
    84  // off a go routine to setup a serving http.Server for each.
    85  func (s *Server) ServeApi(protoAddrs []string) error {
    86  	var chErrors = make(chan error, len(protoAddrs))
    87  
    88  	for _, protoAddr := range protoAddrs {
    89  		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
    90  		if len(protoAddrParts) != 2 {
    91  			return fmt.Errorf("bad format, expected PROTO://ADDR")
    92  		}
    93  		srv, err := s.newServer(protoAddrParts[0], protoAddrParts[1])
    94  		if err != nil {
    95  			return err
    96  		}
    97  		s.servers = append(s.servers, srv...)
    98  
    99  		for _, s := range srv {
   100  			logrus.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
   101  			go func(s serverCloser) {
   102  				if err := s.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
   103  					err = nil
   104  				}
   105  				chErrors <- err
   106  			}(s)
   107  		}
   108  	}
   109  
   110  	for i := 0; i < len(protoAddrs); i++ {
   111  		err := <-chErrors
   112  		if err != nil {
   113  			return err
   114  		}
   115  	}
   116  
   117  	return nil
   118  }
   119  
   120  type HttpServer struct {
   121  	srv *http.Server
   122  	l   net.Listener
   123  }
   124  
   125  func (s *HttpServer) Serve() error {
   126  	return s.srv.Serve(s.l)
   127  }
   128  func (s *HttpServer) Close() error {
   129  	return s.l.Close()
   130  }
   131  
   132  type HttpApiFunc func(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error
   133  
   134  func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
   135  	conn, _, err := w.(http.Hijacker).Hijack()
   136  	if err != nil {
   137  		return nil, nil, err
   138  	}
   139  	// Flush the options to make sure the client sets the raw mode
   140  	conn.Write([]byte{})
   141  	return conn, conn, nil
   142  }
   143  
   144  func closeStreams(streams ...interface{}) {
   145  	for _, stream := range streams {
   146  		if tcpc, ok := stream.(interface {
   147  			CloseWrite() error
   148  		}); ok {
   149  			tcpc.CloseWrite()
   150  		} else if closer, ok := stream.(io.Closer); ok {
   151  			closer.Close()
   152  		}
   153  	}
   154  }
   155  
   156  // Check to make sure request's Content-Type is application/json
   157  func checkForJson(r *http.Request) error {
   158  	ct := r.Header.Get("Content-Type")
   159  
   160  	// No Content-Type header is ok as long as there's no Body
   161  	if ct == "" {
   162  		if r.Body == nil || r.ContentLength == 0 {
   163  			return nil
   164  		}
   165  	}
   166  
   167  	// Otherwise it better be json
   168  	if api.MatchesContentType(ct, "application/json") {
   169  		return nil
   170  	}
   171  	return fmt.Errorf("Content-Type specified (%s) must be 'application/json'", ct)
   172  }
   173  
   174  //If we don't do this, POST method without Content-type (even with empty body) will fail
   175  func parseForm(r *http.Request) error {
   176  	if r == nil {
   177  		return nil
   178  	}
   179  	if err := r.ParseForm(); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
   180  		return err
   181  	}
   182  	return nil
   183  }
   184  
   185  func parseMultipartForm(r *http.Request) error {
   186  	if err := r.ParseMultipartForm(4096); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
   187  		return err
   188  	}
   189  	return nil
   190  }
   191  
   192  func httpError(w http.ResponseWriter, err error) {
   193  	if err == nil || w == nil {
   194  		logrus.WithFields(logrus.Fields{"error": err, "writer": w}).Error("unexpected HTTP error handling")
   195  		return
   196  	}
   197  	statusCode := http.StatusInternalServerError
   198  	// FIXME: this is brittle and should not be necessary.
   199  	// If we need to differentiate between different possible error types, we should
   200  	// create appropriate error types with clearly defined meaning.
   201  	errStr := strings.ToLower(err.Error())
   202  	for keyword, status := range map[string]int{
   203  		"not found":             http.StatusNotFound,
   204  		"no such":               http.StatusNotFound,
   205  		"bad parameter":         http.StatusBadRequest,
   206  		"conflict":              http.StatusConflict,
   207  		"impossible":            http.StatusNotAcceptable,
   208  		"wrong login/password":  http.StatusUnauthorized,
   209  		"hasn't been activated": http.StatusForbidden,
   210  	} {
   211  		if strings.Contains(errStr, keyword) {
   212  			statusCode = status
   213  			break
   214  		}
   215  	}
   216  
   217  	logrus.WithFields(logrus.Fields{"statusCode": statusCode, "err": err}).Error("HTTP Error")
   218  	http.Error(w, err.Error(), statusCode)
   219  }
   220  
   221  // writeJSON writes the value v to the http response stream as json with standard
   222  // json encoding.
   223  func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
   224  	w.Header().Set("Content-Type", "application/json")
   225  	w.WriteHeader(code)
   226  	return json.NewEncoder(w).Encode(v)
   227  }
   228  
   229  func (s *Server) postAuth(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   230  	var config *cliconfig.AuthConfig
   231  	err := json.NewDecoder(r.Body).Decode(&config)
   232  	r.Body.Close()
   233  	if err != nil {
   234  		return err
   235  	}
   236  	status, err := s.daemon.RegistryService.Auth(config)
   237  	if err != nil {
   238  		return err
   239  	}
   240  	return writeJSON(w, http.StatusOK, &types.AuthResponse{
   241  		Status: status,
   242  	})
   243  }
   244  
   245  func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   246  	v := &types.Version{
   247  		Version:    dockerversion.VERSION,
   248  		ApiVersion: api.Version,
   249  		GitCommit:  dockerversion.GITCOMMIT,
   250  		GoVersion:  runtime.Version(),
   251  		Os:         runtime.GOOS,
   252  		Arch:       runtime.GOARCH,
   253  		BuildTime:  dockerversion.BUILDTIME,
   254  	}
   255  
   256  	if version.GreaterThanOrEqualTo("1.19") {
   257  		v.Experimental = utils.ExperimentalBuild()
   258  	}
   259  
   260  	if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
   261  		v.KernelVersion = kernelVersion.String()
   262  	}
   263  
   264  	return writeJSON(w, http.StatusOK, v)
   265  }
   266  
   267  func (s *Server) postContainersKill(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   268  	if vars == nil {
   269  		return fmt.Errorf("Missing parameter")
   270  	}
   271  	if err := parseForm(r); err != nil {
   272  		return err
   273  	}
   274  
   275  	var sig uint64
   276  	name := vars["name"]
   277  
   278  	// If we have a signal, look at it. Otherwise, do nothing
   279  	if sigStr := r.Form.Get("signal"); sigStr != "" {
   280  		// Check if we passed the signal as a number:
   281  		// The largest legal signal is 31, so let's parse on 5 bits
   282  		sigN, err := strconv.ParseUint(sigStr, 10, 5)
   283  		if err != nil {
   284  			// The signal is not a number, treat it as a string (either like
   285  			// "KILL" or like "SIGKILL")
   286  			syscallSig, ok := signal.SignalMap[strings.TrimPrefix(sigStr, "SIG")]
   287  			if !ok {
   288  				return fmt.Errorf("Invalid signal: %s", sigStr)
   289  			}
   290  			sig = uint64(syscallSig)
   291  		} else {
   292  			sig = sigN
   293  		}
   294  
   295  		if sig == 0 {
   296  			return fmt.Errorf("Invalid signal: %s", sigStr)
   297  		}
   298  	}
   299  
   300  	if err := s.daemon.ContainerKill(name, sig); err != nil {
   301  		_, isStopped := err.(daemon.ErrContainerNotRunning)
   302  		// Return error that's not caused because the container is stopped.
   303  		// Return error if the container is not running and the api is >= 1.20
   304  		// to keep backwards compatibility.
   305  		if version.GreaterThanOrEqualTo("1.20") || !isStopped {
   306  			return fmt.Errorf("Cannot kill container %s: %v", name, err)
   307  		}
   308  	}
   309  
   310  	w.WriteHeader(http.StatusNoContent)
   311  	return nil
   312  }
   313  
   314  func (s *Server) postContainersPause(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   315  	if vars == nil {
   316  		return fmt.Errorf("Missing parameter")
   317  	}
   318  	if err := parseForm(r); err != nil {
   319  		return err
   320  	}
   321  
   322  	if err := s.daemon.ContainerPause(vars["name"]); err != nil {
   323  		return err
   324  	}
   325  
   326  	w.WriteHeader(http.StatusNoContent)
   327  
   328  	return nil
   329  }
   330  
   331  func (s *Server) postContainersUnpause(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   332  	if vars == nil {
   333  		return fmt.Errorf("Missing parameter")
   334  	}
   335  	if err := parseForm(r); err != nil {
   336  		return err
   337  	}
   338  
   339  	if err := s.daemon.ContainerUnpause(vars["name"]); err != nil {
   340  		return err
   341  	}
   342  
   343  	w.WriteHeader(http.StatusNoContent)
   344  
   345  	return nil
   346  }
   347  
   348  func (s *Server) getContainersExport(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   349  	if vars == nil {
   350  		return fmt.Errorf("Missing parameter")
   351  	}
   352  
   353  	return s.daemon.ContainerExport(vars["name"], w)
   354  }
   355  
   356  func (s *Server) getImagesJSON(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   357  	if err := parseForm(r); err != nil {
   358  		return err
   359  	}
   360  
   361  	imagesConfig := graph.ImagesConfig{
   362  		Filters: r.Form.Get("filters"),
   363  		// FIXME this parameter could just be a match filter
   364  		Filter: r.Form.Get("filter"),
   365  		All:    boolValue(r, "all"),
   366  	}
   367  
   368  	images, err := s.daemon.Repositories().Images(&imagesConfig)
   369  	if err != nil {
   370  		return err
   371  	}
   372  
   373  	return writeJSON(w, http.StatusOK, images)
   374  }
   375  
   376  func (s *Server) getInfo(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   377  	info, err := s.daemon.SystemInfo()
   378  	if err != nil {
   379  		return err
   380  	}
   381  
   382  	return writeJSON(w, http.StatusOK, info)
   383  }
   384  
   385  func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   386  	if err := parseForm(r); err != nil {
   387  		return err
   388  	}
   389  	var since int64 = -1
   390  	if r.Form.Get("since") != "" {
   391  		s, err := strconv.ParseInt(r.Form.Get("since"), 10, 64)
   392  		if err != nil {
   393  			return err
   394  		}
   395  		since = s
   396  	}
   397  
   398  	var until int64 = -1
   399  	if r.Form.Get("until") != "" {
   400  		u, err := strconv.ParseInt(r.Form.Get("until"), 10, 64)
   401  		if err != nil {
   402  			return err
   403  		}
   404  		until = u
   405  	}
   406  
   407  	timer := time.NewTimer(0)
   408  	timer.Stop()
   409  	if until > 0 {
   410  		dur := time.Unix(until, 0).Sub(time.Now())
   411  		timer = time.NewTimer(dur)
   412  	}
   413  
   414  	ef, err := filters.FromParam(r.Form.Get("filters"))
   415  	if err != nil {
   416  		return err
   417  	}
   418  
   419  	isFiltered := func(field string, filter []string) bool {
   420  		if len(field) == 0 {
   421  			return false
   422  		}
   423  		if len(filter) == 0 {
   424  			return false
   425  		}
   426  		for _, v := range filter {
   427  			if v == field {
   428  				return false
   429  			}
   430  			if strings.Contains(field, ":") {
   431  				image := strings.Split(field, ":")
   432  				if image[0] == v {
   433  					return false
   434  				}
   435  			}
   436  		}
   437  		return true
   438  	}
   439  
   440  	d := s.daemon
   441  	es := d.EventsService
   442  	w.Header().Set("Content-Type", "application/json")
   443  	outStream := ioutils.NewWriteFlusher(w)
   444  	outStream.Write(nil) // make sure response is sent immediately
   445  	enc := json.NewEncoder(outStream)
   446  
   447  	getContainerId := func(cn string) string {
   448  		c, err := d.Get(cn)
   449  		if err != nil {
   450  			return ""
   451  		}
   452  		return c.ID
   453  	}
   454  
   455  	sendEvent := func(ev *jsonmessage.JSONMessage) error {
   456  		//incoming container filter can be name,id or partial id, convert and replace as a full container id
   457  		for i, cn := range ef["container"] {
   458  			ef["container"][i] = getContainerId(cn)
   459  		}
   460  
   461  		if isFiltered(ev.Status, ef["event"]) || (isFiltered(ev.ID, ef["image"]) &&
   462  			isFiltered(ev.From, ef["image"])) || isFiltered(ev.ID, ef["container"]) {
   463  			return nil
   464  		}
   465  
   466  		return enc.Encode(ev)
   467  	}
   468  
   469  	current, l := es.Subscribe()
   470  	if since == -1 {
   471  		current = nil
   472  	}
   473  	defer es.Evict(l)
   474  	for _, ev := range current {
   475  		if ev.Time < since {
   476  			continue
   477  		}
   478  		if err := sendEvent(ev); err != nil {
   479  			return err
   480  		}
   481  	}
   482  
   483  	var closeNotify <-chan bool
   484  	if closeNotifier, ok := w.(http.CloseNotifier); ok {
   485  		closeNotify = closeNotifier.CloseNotify()
   486  	}
   487  
   488  	for {
   489  		select {
   490  		case ev := <-l:
   491  			jev, ok := ev.(*jsonmessage.JSONMessage)
   492  			if !ok {
   493  				continue
   494  			}
   495  			if err := sendEvent(jev); err != nil {
   496  				return err
   497  			}
   498  		case <-timer.C:
   499  			return nil
   500  		case <-closeNotify:
   501  			logrus.Debug("Client disconnected, stop sending events")
   502  			return nil
   503  		}
   504  	}
   505  }
   506  
   507  func (s *Server) getImagesHistory(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   508  	if vars == nil {
   509  		return fmt.Errorf("Missing parameter")
   510  	}
   511  
   512  	name := vars["name"]
   513  	history, err := s.daemon.Repositories().History(name)
   514  	if err != nil {
   515  		return err
   516  	}
   517  
   518  	return writeJSON(w, http.StatusOK, history)
   519  }
   520  
   521  func (s *Server) getContainersChanges(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   522  	if vars == nil {
   523  		return fmt.Errorf("Missing parameter")
   524  	}
   525  
   526  	changes, err := s.daemon.ContainerChanges(vars["name"])
   527  	if err != nil {
   528  		return err
   529  	}
   530  
   531  	return writeJSON(w, http.StatusOK, changes)
   532  }
   533  
   534  func (s *Server) getContainersTop(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   535  	if vars == nil {
   536  		return fmt.Errorf("Missing parameter")
   537  	}
   538  
   539  	if err := parseForm(r); err != nil {
   540  		return err
   541  	}
   542  
   543  	procList, err := s.daemon.ContainerTop(vars["name"], r.Form.Get("ps_args"))
   544  	if err != nil {
   545  		return err
   546  	}
   547  
   548  	return writeJSON(w, http.StatusOK, procList)
   549  }
   550  
   551  func (s *Server) getContainersJSON(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   552  	if err := parseForm(r); err != nil {
   553  		return err
   554  	}
   555  
   556  	config := &daemon.ContainersConfig{
   557  		All:     boolValue(r, "all"),
   558  		Size:    boolValue(r, "size"),
   559  		Since:   r.Form.Get("since"),
   560  		Before:  r.Form.Get("before"),
   561  		Filters: r.Form.Get("filters"),
   562  	}
   563  
   564  	if tmpLimit := r.Form.Get("limit"); tmpLimit != "" {
   565  		limit, err := strconv.Atoi(tmpLimit)
   566  		if err != nil {
   567  			return err
   568  		}
   569  		config.Limit = limit
   570  	}
   571  
   572  	containers, err := s.daemon.Containers(config)
   573  	if err != nil {
   574  		return err
   575  	}
   576  
   577  	return writeJSON(w, http.StatusOK, containers)
   578  }
   579  
   580  func (s *Server) getContainersStats(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   581  	if err := parseForm(r); err != nil {
   582  		return err
   583  	}
   584  	if vars == nil {
   585  		return fmt.Errorf("Missing parameter")
   586  	}
   587  
   588  	stream := boolValueOrDefault(r, "stream", true)
   589  	var out io.Writer
   590  	if !stream {
   591  		w.Header().Set("Content-Type", "application/json")
   592  		out = w
   593  	} else {
   594  		out = ioutils.NewWriteFlusher(w)
   595  	}
   596  
   597  	var closeNotifier <-chan bool
   598  	if notifier, ok := w.(http.CloseNotifier); ok {
   599  		closeNotifier = notifier.CloseNotify()
   600  	}
   601  
   602  	config := &daemon.ContainerStatsConfig{
   603  		Stream:    stream,
   604  		OutStream: out,
   605  		Stop:      closeNotifier,
   606  	}
   607  
   608  	return s.daemon.ContainerStats(vars["name"], config)
   609  }
   610  
   611  func (s *Server) getContainersLogs(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   612  	if err := parseForm(r); err != nil {
   613  		return err
   614  	}
   615  	if vars == nil {
   616  		return fmt.Errorf("Missing parameter")
   617  	}
   618  
   619  	// Validate args here, because we can't return not StatusOK after job.Run() call
   620  	stdout, stderr := boolValue(r, "stdout"), boolValue(r, "stderr")
   621  	if !(stdout || stderr) {
   622  		return fmt.Errorf("Bad parameters: you must choose at least one stream")
   623  	}
   624  
   625  	var since time.Time
   626  	if r.Form.Get("since") != "" {
   627  		s, err := strconv.ParseInt(r.Form.Get("since"), 10, 64)
   628  		if err != nil {
   629  			return err
   630  		}
   631  		since = time.Unix(s, 0)
   632  	}
   633  
   634  	var closeNotifier <-chan bool
   635  	if notifier, ok := w.(http.CloseNotifier); ok {
   636  		closeNotifier = notifier.CloseNotify()
   637  	}
   638  
   639  	c, err := s.daemon.Get(vars["name"])
   640  	if err != nil {
   641  		return err
   642  	}
   643  
   644  	outStream := ioutils.NewWriteFlusher(w)
   645  	// write an empty chunk of data (this is to ensure that the
   646  	// HTTP Response is sent immediatly, even if the container has
   647  	// not yet produced any data)
   648  	outStream.Write(nil)
   649  
   650  	logsConfig := &daemon.ContainerLogsConfig{
   651  		Follow:     boolValue(r, "follow"),
   652  		Timestamps: boolValue(r, "timestamps"),
   653  		Since:      since,
   654  		Tail:       r.Form.Get("tail"),
   655  		UseStdout:  stdout,
   656  		UseStderr:  stderr,
   657  		OutStream:  outStream,
   658  		Stop:       closeNotifier,
   659  	}
   660  
   661  	if err := s.daemon.ContainerLogs(c, logsConfig); err != nil {
   662  		fmt.Fprintf(w, "Error running logs job: %s\n", err)
   663  	}
   664  
   665  	return nil
   666  }
   667  
   668  func (s *Server) postImagesTag(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   669  	if err := parseForm(r); err != nil {
   670  		return err
   671  	}
   672  	if vars == nil {
   673  		return fmt.Errorf("Missing parameter")
   674  	}
   675  
   676  	repo := r.Form.Get("repo")
   677  	tag := r.Form.Get("tag")
   678  	force := boolValue(r, "force")
   679  	name := vars["name"]
   680  	if err := s.daemon.Repositories().Tag(repo, tag, name, force); err != nil {
   681  		return err
   682  	}
   683  	s.daemon.EventsService.Log("tag", utils.ImageReference(repo, tag), "")
   684  	w.WriteHeader(http.StatusCreated)
   685  	return nil
   686  }
   687  
   688  func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   689  	if err := parseForm(r); err != nil {
   690  		return err
   691  	}
   692  
   693  	if err := checkForJson(r); err != nil {
   694  		return err
   695  	}
   696  
   697  	cname := r.Form.Get("container")
   698  
   699  	pause := boolValue(r, "pause")
   700  	if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") {
   701  		pause = true
   702  	}
   703  
   704  	c, _, err := runconfig.DecodeContainerConfig(r.Body)
   705  	if err != nil && err != io.EOF { //Do not fail if body is empty.
   706  		return err
   707  	}
   708  
   709  	commitCfg := &builder.CommitConfig{
   710  		Pause:   pause,
   711  		Repo:    r.Form.Get("repo"),
   712  		Tag:     r.Form.Get("tag"),
   713  		Author:  r.Form.Get("author"),
   714  		Comment: r.Form.Get("comment"),
   715  		Changes: r.Form["changes"],
   716  		Config:  c,
   717  	}
   718  
   719  	imgID, err := builder.Commit(cname, s.daemon, commitCfg)
   720  	if err != nil {
   721  		return err
   722  	}
   723  
   724  	return writeJSON(w, http.StatusCreated, &types.ContainerCommitResponse{
   725  		ID: imgID,
   726  	})
   727  }
   728  
   729  // Creates an image from Pull or from Import
   730  func (s *Server) postImagesCreate(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   731  	if err := parseForm(r); err != nil {
   732  		return err
   733  	}
   734  
   735  	var (
   736  		image = r.Form.Get("fromImage")
   737  		repo  = r.Form.Get("repo")
   738  		tag   = r.Form.Get("tag")
   739  	)
   740  	authEncoded := r.Header.Get("X-Registry-Auth")
   741  	authConfig := &cliconfig.AuthConfig{}
   742  	if authEncoded != "" {
   743  		authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
   744  		if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
   745  			// for a pull it is not an error if no auth was given
   746  			// to increase compatibility with the existing api it is defaulting to be empty
   747  			authConfig = &cliconfig.AuthConfig{}
   748  		}
   749  	}
   750  
   751  	var (
   752  		err    error
   753  		output = ioutils.NewWriteFlusher(w)
   754  	)
   755  
   756  	w.Header().Set("Content-Type", "application/json")
   757  
   758  	if image != "" { //pull
   759  		if tag == "" {
   760  			image, tag = parsers.ParseRepositoryTag(image)
   761  		}
   762  		metaHeaders := map[string][]string{}
   763  		for k, v := range r.Header {
   764  			if strings.HasPrefix(k, "X-Meta-") {
   765  				metaHeaders[k] = v
   766  			}
   767  		}
   768  
   769  		imagePullConfig := &graph.ImagePullConfig{
   770  			MetaHeaders: metaHeaders,
   771  			AuthConfig:  authConfig,
   772  			OutStream:   output,
   773  		}
   774  
   775  		err = s.daemon.Repositories().Pull(image, tag, imagePullConfig)
   776  	} else { //import
   777  		if tag == "" {
   778  			repo, tag = parsers.ParseRepositoryTag(repo)
   779  		}
   780  
   781  		src := r.Form.Get("fromSrc")
   782  		imageImportConfig := &graph.ImageImportConfig{
   783  			Changes:   r.Form["changes"],
   784  			InConfig:  r.Body,
   785  			OutStream: output,
   786  		}
   787  
   788  		// 'err' MUST NOT be defined within this block, we need any error
   789  		// generated from the download to be available to the output
   790  		// stream processing below
   791  		var newConfig *runconfig.Config
   792  		newConfig, err = builder.BuildFromConfig(s.daemon, &runconfig.Config{}, imageImportConfig.Changes)
   793  		if err != nil {
   794  			return err
   795  		}
   796  		imageImportConfig.ContainerConfig = newConfig
   797  
   798  		err = s.daemon.Repositories().Import(src, repo, tag, imageImportConfig)
   799  	}
   800  	if err != nil {
   801  		if !output.Flushed() {
   802  			return err
   803  		}
   804  		sf := streamformatter.NewJSONStreamFormatter()
   805  		output.Write(sf.FormatError(err))
   806  	}
   807  
   808  	return nil
   809  
   810  }
   811  
   812  func (s *Server) getImagesSearch(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   813  	if err := parseForm(r); err != nil {
   814  		return err
   815  	}
   816  	var (
   817  		config      *cliconfig.AuthConfig
   818  		authEncoded = r.Header.Get("X-Registry-Auth")
   819  		headers     = map[string][]string{}
   820  	)
   821  
   822  	if authEncoded != "" {
   823  		authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
   824  		if err := json.NewDecoder(authJson).Decode(&config); err != nil {
   825  			// for a search it is not an error if no auth was given
   826  			// to increase compatibility with the existing api it is defaulting to be empty
   827  			config = &cliconfig.AuthConfig{}
   828  		}
   829  	}
   830  	for k, v := range r.Header {
   831  		if strings.HasPrefix(k, "X-Meta-") {
   832  			headers[k] = v
   833  		}
   834  	}
   835  	query, err := s.daemon.RegistryService.Search(r.Form.Get("term"), config, headers)
   836  	if err != nil {
   837  		return err
   838  	}
   839  	return writeJSON(w, http.StatusOK, query.Results)
   840  }
   841  
   842  func (s *Server) postImagesPush(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   843  	if vars == nil {
   844  		return fmt.Errorf("Missing parameter")
   845  	}
   846  
   847  	metaHeaders := map[string][]string{}
   848  	for k, v := range r.Header {
   849  		if strings.HasPrefix(k, "X-Meta-") {
   850  			metaHeaders[k] = v
   851  		}
   852  	}
   853  	if err := parseForm(r); err != nil {
   854  		return err
   855  	}
   856  	authConfig := &cliconfig.AuthConfig{}
   857  
   858  	authEncoded := r.Header.Get("X-Registry-Auth")
   859  	if authEncoded != "" {
   860  		// the new format is to handle the authConfig as a header
   861  		authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
   862  		if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
   863  			// to increase compatibility to existing api it is defaulting to be empty
   864  			authConfig = &cliconfig.AuthConfig{}
   865  		}
   866  	} else {
   867  		// the old format is supported for compatibility if there was no authConfig header
   868  		if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
   869  			return fmt.Errorf("Bad parameters and missing X-Registry-Auth: %v", err)
   870  		}
   871  	}
   872  
   873  	name := vars["name"]
   874  	output := ioutils.NewWriteFlusher(w)
   875  	imagePushConfig := &graph.ImagePushConfig{
   876  		MetaHeaders: metaHeaders,
   877  		AuthConfig:  authConfig,
   878  		Tag:         r.Form.Get("tag"),
   879  		OutStream:   output,
   880  	}
   881  
   882  	w.Header().Set("Content-Type", "application/json")
   883  
   884  	if err := s.daemon.Repositories().Push(name, imagePushConfig); err != nil {
   885  		if !output.Flushed() {
   886  			return err
   887  		}
   888  		sf := streamformatter.NewJSONStreamFormatter()
   889  		output.Write(sf.FormatError(err))
   890  	}
   891  	return nil
   892  
   893  }
   894  
   895  func (s *Server) getImagesGet(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   896  	if vars == nil {
   897  		return fmt.Errorf("Missing parameter")
   898  	}
   899  	if err := parseForm(r); err != nil {
   900  		return err
   901  	}
   902  
   903  	w.Header().Set("Content-Type", "application/x-tar")
   904  
   905  	output := ioutils.NewWriteFlusher(w)
   906  	imageExportConfig := &graph.ImageExportConfig{Outstream: output}
   907  	if name, ok := vars["name"]; ok {
   908  		imageExportConfig.Names = []string{name}
   909  	} else {
   910  		imageExportConfig.Names = r.Form["names"]
   911  	}
   912  
   913  	if err := s.daemon.Repositories().ImageExport(imageExportConfig); err != nil {
   914  		if !output.Flushed() {
   915  			return err
   916  		}
   917  		sf := streamformatter.NewJSONStreamFormatter()
   918  		output.Write(sf.FormatError(err))
   919  	}
   920  	return nil
   921  
   922  }
   923  
   924  func (s *Server) postImagesLoad(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   925  	return s.daemon.Repositories().Load(r.Body, w)
   926  }
   927  
   928  func (s *Server) postContainersCreate(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   929  	if err := parseForm(r); err != nil {
   930  		return err
   931  	}
   932  	if err := checkForJson(r); err != nil {
   933  		return err
   934  	}
   935  	var (
   936  		warnings []string
   937  		name     = r.Form.Get("name")
   938  	)
   939  
   940  	config, hostConfig, err := runconfig.DecodeContainerConfig(r.Body)
   941  	if err != nil {
   942  		return err
   943  	}
   944  	adjustCpuShares(version, hostConfig)
   945  
   946  	containerId, warnings, err := s.daemon.ContainerCreate(name, config, hostConfig)
   947  	if err != nil {
   948  		return err
   949  	}
   950  
   951  	return writeJSON(w, http.StatusCreated, &types.ContainerCreateResponse{
   952  		ID:       containerId,
   953  		Warnings: warnings,
   954  	})
   955  }
   956  
   957  func (s *Server) postContainersRestart(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   958  	if err := parseForm(r); err != nil {
   959  		return err
   960  	}
   961  	if vars == nil {
   962  		return fmt.Errorf("Missing parameter")
   963  	}
   964  
   965  	timeout, _ := strconv.Atoi(r.Form.Get("t"))
   966  
   967  	if err := s.daemon.ContainerRestart(vars["name"], timeout); err != nil {
   968  		return err
   969  	}
   970  
   971  	w.WriteHeader(http.StatusNoContent)
   972  
   973  	return nil
   974  }
   975  
   976  func (s *Server) postContainerRename(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   977  	if err := parseForm(r); err != nil {
   978  		return err
   979  	}
   980  	if vars == nil {
   981  		return fmt.Errorf("Missing parameter")
   982  	}
   983  
   984  	name := vars["name"]
   985  	newName := r.Form.Get("name")
   986  	if err := s.daemon.ContainerRename(name, newName); err != nil {
   987  		return err
   988  	}
   989  	w.WriteHeader(http.StatusNoContent)
   990  	return nil
   991  }
   992  
   993  func (s *Server) deleteContainers(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   994  	if err := parseForm(r); err != nil {
   995  		return err
   996  	}
   997  	if vars == nil {
   998  		return fmt.Errorf("Missing parameter")
   999  	}
  1000  
  1001  	name := vars["name"]
  1002  	config := &daemon.ContainerRmConfig{
  1003  		ForceRemove:  boolValue(r, "force"),
  1004  		RemoveVolume: boolValue(r, "v"),
  1005  		RemoveLink:   boolValue(r, "link"),
  1006  	}
  1007  
  1008  	if err := s.daemon.ContainerRm(name, config); err != nil {
  1009  		// Force a 404 for the empty string
  1010  		if strings.Contains(strings.ToLower(err.Error()), "prefix can't be empty") {
  1011  			return fmt.Errorf("no such id: \"\"")
  1012  		}
  1013  		return err
  1014  	}
  1015  
  1016  	w.WriteHeader(http.StatusNoContent)
  1017  
  1018  	return nil
  1019  }
  1020  
  1021  func (s *Server) deleteImages(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1022  	if err := parseForm(r); err != nil {
  1023  		return err
  1024  	}
  1025  	if vars == nil {
  1026  		return fmt.Errorf("Missing parameter")
  1027  	}
  1028  
  1029  	name := vars["name"]
  1030  	force := boolValue(r, "force")
  1031  	noprune := boolValue(r, "noprune")
  1032  
  1033  	list, err := s.daemon.ImageDelete(name, force, noprune)
  1034  	if err != nil {
  1035  		return err
  1036  	}
  1037  
  1038  	return writeJSON(w, http.StatusOK, list)
  1039  }
  1040  
  1041  func (s *Server) postContainersStart(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1042  	if vars == nil {
  1043  		return fmt.Errorf("Missing parameter")
  1044  	}
  1045  
  1046  	// If contentLength is -1, we can assumed chunked encoding
  1047  	// or more technically that the length is unknown
  1048  	// https://golang.org/src/pkg/net/http/request.go#L139
  1049  	// net/http otherwise seems to swallow any headers related to chunked encoding
  1050  	// including r.TransferEncoding
  1051  	// allow a nil body for backwards compatibility
  1052  	var hostConfig *runconfig.HostConfig
  1053  	if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) {
  1054  		if err := checkForJson(r); err != nil {
  1055  			return err
  1056  		}
  1057  
  1058  		c, err := runconfig.DecodeHostConfig(r.Body)
  1059  		if err != nil {
  1060  			return err
  1061  		}
  1062  
  1063  		hostConfig = c
  1064  	}
  1065  
  1066  	if err := s.daemon.ContainerStart(vars["name"], hostConfig); err != nil {
  1067  		if err.Error() == "Container already started" {
  1068  			w.WriteHeader(http.StatusNotModified)
  1069  			return nil
  1070  		}
  1071  		return err
  1072  	}
  1073  	w.WriteHeader(http.StatusNoContent)
  1074  	return nil
  1075  }
  1076  
  1077  func (s *Server) postContainersStop(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1078  	if err := parseForm(r); err != nil {
  1079  		return err
  1080  	}
  1081  	if vars == nil {
  1082  		return fmt.Errorf("Missing parameter")
  1083  	}
  1084  
  1085  	seconds, _ := strconv.Atoi(r.Form.Get("t"))
  1086  
  1087  	if err := s.daemon.ContainerStop(vars["name"], seconds); err != nil {
  1088  		if err.Error() == "Container already stopped" {
  1089  			w.WriteHeader(http.StatusNotModified)
  1090  			return nil
  1091  		}
  1092  		return err
  1093  	}
  1094  	w.WriteHeader(http.StatusNoContent)
  1095  
  1096  	return nil
  1097  }
  1098  
  1099  func (s *Server) postContainersWait(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1100  	if vars == nil {
  1101  		return fmt.Errorf("Missing parameter")
  1102  	}
  1103  
  1104  	status, err := s.daemon.ContainerWait(vars["name"], -1*time.Second)
  1105  	if err != nil {
  1106  		return err
  1107  	}
  1108  
  1109  	return writeJSON(w, http.StatusOK, &types.ContainerWaitResponse{
  1110  		StatusCode: status,
  1111  	})
  1112  }
  1113  
  1114  func (s *Server) postContainersResize(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1115  	if err := parseForm(r); err != nil {
  1116  		return err
  1117  	}
  1118  	if vars == nil {
  1119  		return fmt.Errorf("Missing parameter")
  1120  	}
  1121  
  1122  	height, err := strconv.Atoi(r.Form.Get("h"))
  1123  	if err != nil {
  1124  		return err
  1125  	}
  1126  	width, err := strconv.Atoi(r.Form.Get("w"))
  1127  	if err != nil {
  1128  		return err
  1129  	}
  1130  
  1131  	return s.daemon.ContainerResize(vars["name"], height, width)
  1132  }
  1133  
  1134  func (s *Server) postContainersAttach(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1135  	if err := parseForm(r); err != nil {
  1136  		return err
  1137  	}
  1138  	if vars == nil {
  1139  		return fmt.Errorf("Missing parameter")
  1140  	}
  1141  
  1142  	cont, err := s.daemon.Get(vars["name"])
  1143  	if err != nil {
  1144  		return err
  1145  	}
  1146  
  1147  	inStream, outStream, err := hijackServer(w)
  1148  	if err != nil {
  1149  		return err
  1150  	}
  1151  	defer closeStreams(inStream, outStream)
  1152  
  1153  	if _, ok := r.Header["Upgrade"]; ok {
  1154  		fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
  1155  	} else {
  1156  		fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
  1157  	}
  1158  
  1159  	attachWithLogsConfig := &daemon.ContainerAttachWithLogsConfig{
  1160  		InStream:  inStream,
  1161  		OutStream: outStream,
  1162  		UseStdin:  boolValue(r, "stdin"),
  1163  		UseStdout: boolValue(r, "stdout"),
  1164  		UseStderr: boolValue(r, "stderr"),
  1165  		Logs:      boolValue(r, "logs"),
  1166  		Stream:    boolValue(r, "stream"),
  1167  	}
  1168  
  1169  	if err := s.daemon.ContainerAttachWithLogs(cont, attachWithLogsConfig); err != nil {
  1170  		fmt.Fprintf(outStream, "Error attaching: %s\n", err)
  1171  	}
  1172  
  1173  	return nil
  1174  }
  1175  
  1176  func (s *Server) wsContainersAttach(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1177  	if err := parseForm(r); err != nil {
  1178  		return err
  1179  	}
  1180  	if vars == nil {
  1181  		return fmt.Errorf("Missing parameter")
  1182  	}
  1183  
  1184  	cont, err := s.daemon.Get(vars["name"])
  1185  	if err != nil {
  1186  		return err
  1187  	}
  1188  
  1189  	h := websocket.Handler(func(ws *websocket.Conn) {
  1190  		defer ws.Close()
  1191  
  1192  		wsAttachWithLogsConfig := &daemon.ContainerWsAttachWithLogsConfig{
  1193  			InStream:  ws,
  1194  			OutStream: ws,
  1195  			ErrStream: ws,
  1196  			Logs:      boolValue(r, "logs"),
  1197  			Stream:    boolValue(r, "stream"),
  1198  		}
  1199  
  1200  		if err := s.daemon.ContainerWsAttachWithLogs(cont, wsAttachWithLogsConfig); err != nil {
  1201  			logrus.Errorf("Error attaching websocket: %s", err)
  1202  		}
  1203  	})
  1204  	h.ServeHTTP(w, r)
  1205  
  1206  	return nil
  1207  }
  1208  
  1209  func (s *Server) getContainersByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1210  	if vars == nil {
  1211  		return fmt.Errorf("Missing parameter")
  1212  	}
  1213  
  1214  	if version.LessThan("1.20") {
  1215  		containerJSONRaw, err := s.daemon.ContainerInspectPre120(vars["name"])
  1216  		if err != nil {
  1217  			return err
  1218  		}
  1219  		return writeJSON(w, http.StatusOK, containerJSONRaw)
  1220  	}
  1221  
  1222  	containerJSON, err := s.daemon.ContainerInspect(vars["name"])
  1223  	if err != nil {
  1224  		return err
  1225  	}
  1226  	return writeJSON(w, http.StatusOK, containerJSON)
  1227  }
  1228  
  1229  func (s *Server) getExecByID(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1230  	if vars == nil {
  1231  		return fmt.Errorf("Missing parameter 'id'")
  1232  	}
  1233  
  1234  	eConfig, err := s.daemon.ContainerExecInspect(vars["id"])
  1235  	if err != nil {
  1236  		return err
  1237  	}
  1238  
  1239  	return writeJSON(w, http.StatusOK, eConfig)
  1240  }
  1241  
  1242  func (s *Server) getImagesByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1243  	if vars == nil {
  1244  		return fmt.Errorf("Missing parameter")
  1245  	}
  1246  
  1247  	imageInspect, err := s.daemon.Repositories().Lookup(vars["name"])
  1248  	if err != nil {
  1249  		return err
  1250  	}
  1251  
  1252  	return writeJSON(w, http.StatusOK, imageInspect)
  1253  }
  1254  
  1255  func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1256  	var (
  1257  		authConfigs        = map[string]cliconfig.AuthConfig{}
  1258  		authConfigsEncoded = r.Header.Get("X-Registry-Config")
  1259  		buildConfig        = builder.NewBuildConfig()
  1260  	)
  1261  
  1262  	if authConfigsEncoded != "" {
  1263  		authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authConfigsEncoded))
  1264  		if err := json.NewDecoder(authConfigsJSON).Decode(&authConfigs); err != nil {
  1265  			// for a pull it is not an error if no auth was given
  1266  			// to increase compatibility with the existing api it is defaulting
  1267  			// to be empty.
  1268  		}
  1269  	}
  1270  
  1271  	w.Header().Set("Content-Type", "application/json")
  1272  
  1273  	if boolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
  1274  		buildConfig.Remove = true
  1275  	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
  1276  		buildConfig.Remove = true
  1277  	} else {
  1278  		buildConfig.Remove = boolValue(r, "rm")
  1279  	}
  1280  	if boolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
  1281  		buildConfig.Pull = true
  1282  	}
  1283  
  1284  	output := ioutils.NewWriteFlusher(w)
  1285  	buildConfig.Stdout = output
  1286  	buildConfig.Context = r.Body
  1287  
  1288  	buildConfig.RemoteURL = r.FormValue("remote")
  1289  	buildConfig.DockerfileName = r.FormValue("dockerfile")
  1290  	buildConfig.RepoName = r.FormValue("t")
  1291  	buildConfig.SuppressOutput = boolValue(r, "q")
  1292  	buildConfig.NoCache = boolValue(r, "nocache")
  1293  	buildConfig.ForceRemove = boolValue(r, "forcerm")
  1294  	buildConfig.AuthConfigs = authConfigs
  1295  	buildConfig.MemorySwap = int64ValueOrZero(r, "memswap")
  1296  	buildConfig.Memory = int64ValueOrZero(r, "memory")
  1297  	buildConfig.CPUShares = int64ValueOrZero(r, "cpushares")
  1298  	buildConfig.CPUPeriod = int64ValueOrZero(r, "cpuperiod")
  1299  	buildConfig.CPUQuota = int64ValueOrZero(r, "cpuquota")
  1300  	buildConfig.CPUSetCpus = r.FormValue("cpusetcpus")
  1301  	buildConfig.CPUSetMems = r.FormValue("cpusetmems")
  1302  	buildConfig.CgroupParent = r.FormValue("cgroupparent")
  1303  
  1304  	var buildUlimits = []*ulimit.Ulimit{}
  1305  	ulimitsJson := r.FormValue("ulimits")
  1306  	if ulimitsJson != "" {
  1307  		if err := json.NewDecoder(strings.NewReader(ulimitsJson)).Decode(&buildUlimits); err != nil {
  1308  			return err
  1309  		}
  1310  		buildConfig.Ulimits = buildUlimits
  1311  	}
  1312  
  1313  	// Job cancellation. Note: not all job types support this.
  1314  	if closeNotifier, ok := w.(http.CloseNotifier); ok {
  1315  		finished := make(chan struct{})
  1316  		defer close(finished)
  1317  		go func() {
  1318  			select {
  1319  			case <-finished:
  1320  			case <-closeNotifier.CloseNotify():
  1321  				logrus.Infof("Client disconnected, cancelling job: build")
  1322  				buildConfig.Cancel()
  1323  			}
  1324  		}()
  1325  	}
  1326  
  1327  	if err := builder.Build(s.daemon, buildConfig); err != nil {
  1328  		// Do not write the error in the http output if it's still empty.
  1329  		// This prevents from writing a 200(OK) when there is an interal error.
  1330  		if !output.Flushed() {
  1331  			return err
  1332  		}
  1333  		sf := streamformatter.NewJSONStreamFormatter()
  1334  		w.Write(sf.FormatError(err))
  1335  	}
  1336  	return nil
  1337  }
  1338  
  1339  // postContainersCopy is deprecated in favor of getContainersArchivePath.
  1340  func (s *Server) postContainersCopy(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1341  	if vars == nil {
  1342  		return fmt.Errorf("Missing parameter")
  1343  	}
  1344  
  1345  	if err := checkForJson(r); err != nil {
  1346  		return err
  1347  	}
  1348  
  1349  	cfg := types.CopyConfig{}
  1350  	if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
  1351  		return err
  1352  	}
  1353  
  1354  	if cfg.Resource == "" {
  1355  		return fmt.Errorf("Path cannot be empty")
  1356  	}
  1357  
  1358  	data, err := s.daemon.ContainerCopy(vars["name"], cfg.Resource)
  1359  	if err != nil {
  1360  		if strings.Contains(strings.ToLower(err.Error()), "no such id") {
  1361  			w.WriteHeader(http.StatusNotFound)
  1362  			return nil
  1363  		}
  1364  		if os.IsNotExist(err) {
  1365  			return fmt.Errorf("Could not find the file %s in container %s", cfg.Resource, vars["name"])
  1366  		}
  1367  		return err
  1368  	}
  1369  	defer data.Close()
  1370  
  1371  	w.Header().Set("Content-Type", "application/x-tar")
  1372  	if _, err := io.Copy(w, data); err != nil {
  1373  		return err
  1374  	}
  1375  
  1376  	return nil
  1377  }
  1378  
  1379  // // Encode the stat to JSON, base64 encode, and place in a header.
  1380  func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error {
  1381  	statJSON, err := json.Marshal(stat)
  1382  	if err != nil {
  1383  		return err
  1384  	}
  1385  
  1386  	header.Set(
  1387  		"X-Docker-Container-Path-Stat",
  1388  		base64.StdEncoding.EncodeToString(statJSON),
  1389  	)
  1390  
  1391  	return nil
  1392  }
  1393  
  1394  func (s *Server) headContainersArchive(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1395  	v, err := archiveFormValues(r, vars)
  1396  	if err != nil {
  1397  		return err
  1398  	}
  1399  
  1400  	stat, err := s.daemon.ContainerStatPath(v.name, v.path)
  1401  	if err != nil {
  1402  		return err
  1403  	}
  1404  
  1405  	return setContainerPathStatHeader(stat, w.Header())
  1406  }
  1407  
  1408  func (s *Server) getContainersArchive(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1409  	v, err := archiveFormValues(r, vars)
  1410  	if err != nil {
  1411  		return err
  1412  	}
  1413  
  1414  	tarArchive, stat, err := s.daemon.ContainerArchivePath(v.name, v.path)
  1415  	if err != nil {
  1416  		return err
  1417  	}
  1418  	defer tarArchive.Close()
  1419  
  1420  	if err := setContainerPathStatHeader(stat, w.Header()); err != nil {
  1421  		return err
  1422  	}
  1423  
  1424  	w.Header().Set("Content-Type", "application/x-tar")
  1425  	_, err = io.Copy(w, tarArchive)
  1426  
  1427  	return err
  1428  }
  1429  
  1430  func (s *Server) putContainersArchive(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1431  	v, err := archiveFormValues(r, vars)
  1432  	if err != nil {
  1433  		return err
  1434  	}
  1435  
  1436  	noOverwriteDirNonDir := boolValue(r, "noOverwriteDirNonDir")
  1437  	return s.daemon.ContainerExtractToDir(v.name, v.path, noOverwriteDirNonDir, r.Body)
  1438  }
  1439  
  1440  func (s *Server) postContainerExecCreate(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1441  	if err := parseForm(r); err != nil {
  1442  		return err
  1443  	}
  1444  	if err := checkForJson(r); err != nil {
  1445  		return err
  1446  	}
  1447  	name := vars["name"]
  1448  
  1449  	execConfig := &runconfig.ExecConfig{}
  1450  	if err := json.NewDecoder(r.Body).Decode(execConfig); err != nil {
  1451  		return err
  1452  	}
  1453  	execConfig.Container = name
  1454  
  1455  	if len(execConfig.Cmd) == 0 {
  1456  		return fmt.Errorf("No exec command specified")
  1457  	}
  1458  
  1459  	// Register an instance of Exec in container.
  1460  	id, err := s.daemon.ContainerExecCreate(execConfig)
  1461  	if err != nil {
  1462  		logrus.Errorf("Error setting up exec command in container %s: %s", name, err)
  1463  		return err
  1464  	}
  1465  
  1466  	return writeJSON(w, http.StatusCreated, &types.ContainerExecCreateResponse{
  1467  		ID: id,
  1468  	})
  1469  }
  1470  
  1471  // TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start.
  1472  func (s *Server) postContainerExecStart(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1473  	if err := parseForm(r); err != nil {
  1474  		return err
  1475  	}
  1476  	var (
  1477  		execName = vars["name"]
  1478  		stdin    io.ReadCloser
  1479  		stdout   io.Writer
  1480  		stderr   io.Writer
  1481  	)
  1482  
  1483  	execStartCheck := &types.ExecStartCheck{}
  1484  	if err := json.NewDecoder(r.Body).Decode(execStartCheck); err != nil {
  1485  		return err
  1486  	}
  1487  
  1488  	if !execStartCheck.Detach {
  1489  		// Setting up the streaming http interface.
  1490  		inStream, outStream, err := hijackServer(w)
  1491  		if err != nil {
  1492  			return err
  1493  		}
  1494  		defer closeStreams(inStream, outStream)
  1495  
  1496  		var errStream io.Writer
  1497  
  1498  		if _, ok := r.Header["Upgrade"]; ok {
  1499  			fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
  1500  		} else {
  1501  			fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
  1502  		}
  1503  
  1504  		if !execStartCheck.Tty {
  1505  			errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
  1506  			outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
  1507  		}
  1508  
  1509  		stdin = inStream
  1510  		stdout = outStream
  1511  		stderr = errStream
  1512  	}
  1513  	// Now run the user process in container.
  1514  
  1515  	if err := s.daemon.ContainerExecStart(execName, stdin, stdout, stderr); err != nil {
  1516  		logrus.Errorf("Error starting exec command in container %s: %s", execName, err)
  1517  		return err
  1518  	}
  1519  	w.WriteHeader(http.StatusNoContent)
  1520  
  1521  	return nil
  1522  }
  1523  
  1524  func (s *Server) postContainerExecResize(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1525  	if err := parseForm(r); err != nil {
  1526  		return err
  1527  	}
  1528  	if vars == nil {
  1529  		return fmt.Errorf("Missing parameter")
  1530  	}
  1531  
  1532  	height, err := strconv.Atoi(r.Form.Get("h"))
  1533  	if err != nil {
  1534  		return err
  1535  	}
  1536  	width, err := strconv.Atoi(r.Form.Get("w"))
  1537  	if err != nil {
  1538  		return err
  1539  	}
  1540  
  1541  	return s.daemon.ContainerExecResize(vars["name"], height, width)
  1542  }
  1543  
  1544  func (s *Server) optionsHandler(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1545  	w.WriteHeader(http.StatusOK)
  1546  	return nil
  1547  }
  1548  func writeCorsHeaders(w http.ResponseWriter, r *http.Request, corsHeaders string) {
  1549  	logrus.Debugf("CORS header is enabled and set to: %s", corsHeaders)
  1550  	w.Header().Add("Access-Control-Allow-Origin", corsHeaders)
  1551  	w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
  1552  	w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
  1553  }
  1554  
  1555  func (s *Server) ping(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  1556  	_, err := w.Write([]byte{'O', 'K'})
  1557  	return err
  1558  }
  1559  
  1560  func (s *Server) initTcpSocket(addr string) (l net.Listener, err error) {
  1561  	if s.cfg.TLSConfig == nil || s.cfg.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert {
  1562  		logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
  1563  	}
  1564  	if l, err = sockets.NewTcpSocket(addr, s.cfg.TLSConfig, s.start); err != nil {
  1565  		return nil, err
  1566  	}
  1567  	if err := allocateDaemonPort(addr); err != nil {
  1568  		return nil, err
  1569  	}
  1570  	return
  1571  }
  1572  
  1573  func makeHttpHandler(logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, corsHeaders string, dockerVersion version.Version) http.HandlerFunc {
  1574  	return func(w http.ResponseWriter, r *http.Request) {
  1575  		// log the request
  1576  		logrus.Debugf("Calling %s %s", localMethod, localRoute)
  1577  
  1578  		if logging {
  1579  			logrus.Infof("%s %s", r.Method, r.RequestURI)
  1580  		}
  1581  
  1582  		if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
  1583  			userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
  1584  
  1585  			// v1.20 onwards includes the GOOS of the client after the version
  1586  			// such as Docker/1.7.0 (linux)
  1587  			if len(userAgent) == 2 && strings.Contains(userAgent[1], " ") {
  1588  				userAgent[1] = strings.Split(userAgent[1], " ")[0]
  1589  			}
  1590  
  1591  			if len(userAgent) == 2 && !dockerVersion.Equal(version.Version(userAgent[1])) {
  1592  				logrus.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion)
  1593  			}
  1594  		}
  1595  		version := version.Version(mux.Vars(r)["version"])
  1596  		if version == "" {
  1597  			version = api.Version
  1598  		}
  1599  		if corsHeaders != "" {
  1600  			writeCorsHeaders(w, r, corsHeaders)
  1601  		}
  1602  
  1603  		if version.GreaterThan(api.Version) {
  1604  			http.Error(w, fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", version, api.Version).Error(), http.StatusBadRequest)
  1605  			return
  1606  		}
  1607  		if version.LessThan(api.MinVersion) {
  1608  			http.Error(w, fmt.Errorf("client is too old, minimum supported API version is %s, please upgrade your client to a newer version", api.MinVersion).Error(), http.StatusBadRequest)
  1609  			return
  1610  		}
  1611  
  1612  		w.Header().Set("Server", "Docker/"+dockerversion.VERSION+" ("+runtime.GOOS+")")
  1613  
  1614  		if err := handlerFunc(version, w, r, mux.Vars(r)); err != nil {
  1615  			logrus.Errorf("Handler for %s %s returned error: %s", localMethod, localRoute, err)
  1616  			httpError(w, err)
  1617  		}
  1618  	}
  1619  }
  1620  
  1621  // we keep enableCors just for legacy usage, need to be removed in the future
  1622  func createRouter(s *Server) *mux.Router {
  1623  	r := mux.NewRouter()
  1624  	if os.Getenv("DEBUG") != "" {
  1625  		ProfilerSetup(r, "/debug/")
  1626  	}
  1627  	m := map[string]map[string]HttpApiFunc{
  1628  		"HEAD": {
  1629  			"/containers/{name:.*}/archive": s.headContainersArchive,
  1630  		},
  1631  		"GET": {
  1632  			"/_ping":                          s.ping,
  1633  			"/events":                         s.getEvents,
  1634  			"/info":                           s.getInfo,
  1635  			"/version":                        s.getVersion,
  1636  			"/images/json":                    s.getImagesJSON,
  1637  			"/images/search":                  s.getImagesSearch,
  1638  			"/images/get":                     s.getImagesGet,
  1639  			"/images/{name:.*}/get":           s.getImagesGet,
  1640  			"/images/{name:.*}/history":       s.getImagesHistory,
  1641  			"/images/{name:.*}/json":          s.getImagesByName,
  1642  			"/containers/ps":                  s.getContainersJSON,
  1643  			"/containers/json":                s.getContainersJSON,
  1644  			"/containers/{name:.*}/export":    s.getContainersExport,
  1645  			"/containers/{name:.*}/changes":   s.getContainersChanges,
  1646  			"/containers/{name:.*}/json":      s.getContainersByName,
  1647  			"/containers/{name:.*}/top":       s.getContainersTop,
  1648  			"/containers/{name:.*}/logs":      s.getContainersLogs,
  1649  			"/containers/{name:.*}/stats":     s.getContainersStats,
  1650  			"/containers/{name:.*}/attach/ws": s.wsContainersAttach,
  1651  			"/exec/{id:.*}/json":              s.getExecByID,
  1652  			"/containers/{name:.*}/archive":   s.getContainersArchive,
  1653  		},
  1654  		"POST": {
  1655  			"/auth":                         s.postAuth,
  1656  			"/commit":                       s.postCommit,
  1657  			"/build":                        s.postBuild,
  1658  			"/images/create":                s.postImagesCreate,
  1659  			"/images/load":                  s.postImagesLoad,
  1660  			"/images/{name:.*}/push":        s.postImagesPush,
  1661  			"/images/{name:.*}/tag":         s.postImagesTag,
  1662  			"/containers/create":            s.postContainersCreate,
  1663  			"/containers/{name:.*}/kill":    s.postContainersKill,
  1664  			"/containers/{name:.*}/pause":   s.postContainersPause,
  1665  			"/containers/{name:.*}/unpause": s.postContainersUnpause,
  1666  			"/containers/{name:.*}/restart": s.postContainersRestart,
  1667  			"/containers/{name:.*}/start":   s.postContainersStart,
  1668  			"/containers/{name:.*}/stop":    s.postContainersStop,
  1669  			"/containers/{name:.*}/wait":    s.postContainersWait,
  1670  			"/containers/{name:.*}/resize":  s.postContainersResize,
  1671  			"/containers/{name:.*}/attach":  s.postContainersAttach,
  1672  			"/containers/{name:.*}/copy":    s.postContainersCopy,
  1673  			"/containers/{name:.*}/exec":    s.postContainerExecCreate,
  1674  			"/exec/{name:.*}/start":         s.postContainerExecStart,
  1675  			"/exec/{name:.*}/resize":        s.postContainerExecResize,
  1676  			"/containers/{name:.*}/rename":  s.postContainerRename,
  1677  		},
  1678  		"PUT": {
  1679  			"/containers/{name:.*}/archive": s.putContainersArchive,
  1680  		},
  1681  		"DELETE": {
  1682  			"/containers/{name:.*}": s.deleteContainers,
  1683  			"/images/{name:.*}":     s.deleteImages,
  1684  		},
  1685  		"OPTIONS": {
  1686  			"": s.optionsHandler,
  1687  		},
  1688  	}
  1689  
  1690  	// If "api-cors-header" is not given, but "api-enable-cors" is true, we set cors to "*"
  1691  	// otherwise, all head values will be passed to HTTP handler
  1692  	corsHeaders := s.cfg.CorsHeaders
  1693  	if corsHeaders == "" && s.cfg.EnableCors {
  1694  		corsHeaders = "*"
  1695  	}
  1696  
  1697  	for method, routes := range m {
  1698  		for route, fct := range routes {
  1699  			logrus.Debugf("Registering %s, %s", method, route)
  1700  			// NOTE: scope issue, make sure the variables are local and won't be changed
  1701  			localRoute := route
  1702  			localFct := fct
  1703  			localMethod := method
  1704  
  1705  			// build the handler function
  1706  			f := makeHttpHandler(s.cfg.Logging, localMethod, localRoute, localFct, corsHeaders, version.Version(s.cfg.Version))
  1707  
  1708  			// add the new route
  1709  			if localRoute == "" {
  1710  				r.Methods(localMethod).HandlerFunc(f)
  1711  			} else {
  1712  				r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
  1713  				r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
  1714  			}
  1715  		}
  1716  	}
  1717  
  1718  	return r
  1719  }