func (cli *DockerCli) streamHelper(method, path string, setRawTerminal bool, in io.Reader, stdout, stderr io.Writer, headers map[string][]string) error { if (method == "POST" || method == "PUT") && in == nil { in = bytes.NewReader([]byte{}) } req, err := http.NewRequest(method, fmt.Sprintf("http://v%s%s", api.APIVERSION, path), in) if err != nil { return err } req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION) req.URL.Host = cli.addr req.URL.Scheme = cli.scheme if method == "POST" { req.Header.Set("Content-Type", "plain/text") } if headers != nil { for k, v := range headers { req.Header[k] = v } } resp, err := cli.HTTPClient().Do(req) if err != nil { if strings.Contains(err.Error(), "connection refused") { return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?") } return err } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 400 { body, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if len(body) == 0 { return fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode)) } return fmt.Errorf("Error: %s", bytes.TrimSpace(body)) } if api.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") || api.MatchesContentType(resp.Header.Get("Content-Type"), "application/x-json-stream") { return utils.DisplayJSONMessagesStream(resp.Body, stdout, cli.outFd, cli.isTerminalOut) } if stdout != nil || stderr != nil { // When TTY is ON, use regular copy if setRawTerminal { _, err = io.Copy(stdout, resp.Body) } else { _, err = stdcopy.StdCopy(stdout, stderr, resp.Body) } log.Debugf("[stream] End of stdout") return err } return nil }
func postContainersStart(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } var ( name = vars["name"] job = eng.Job("start", name) ) // allow a nil body for backwards compatibility if r.Body != nil && r.ContentLength > 0 { if !api.MatchesContentType(r.Header.Get("Content-Type"), "application/json") { return fmt.Errorf("Content-Type of application/json is required") } if err := job.DecodeEnv(r.Body); err != nil { return err } } if err := job.Run(); err != nil { if err.Error() == "Container already started" { w.WriteHeader(http.StatusNotModified) return nil } return err } w.WriteHeader(http.StatusNoContent) return nil }
func postContainersSet(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } var ( setData engine.Env config []struct { Key string Value string } ) if contentType := r.Header.Get("Content-Type"); api.MatchesContentType(contentType, "application/json") { if err := setData.Decode(r.Body); err != nil { return err } } else { return fmt.Errorf("Content-Type not supported: %s", contentType) } if err := setData.GetJson("config", &config); err != nil { return err } job := eng.Job("container_set", vars["name"]) job.SetenvJson("config", config) job.Stdout.Add(w) if err := job.Run(); err != nil { return err } return nil }
// Check to make sure request's Content-Type is application/json func checkForJson(r *http.Request) error { ct := r.Header.Get("Content-Type") // No Content-Type header is ok as long as there's no Body if ct == "" { if r.Body == nil || r.ContentLength == 0 { return nil } } // Otherwise it better be json if api.MatchesContentType(ct, "application/json") { return nil } return fmt.Errorf("Content-Type specified (%s) must be 'application/json'", ct) }
func postContainersCgroup(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } saveToFile, err := getBoolParam(r.FormValue("w")) if err != nil { return err } var ( cgroupData engine.Env readSubsystem []string writeSubsystem []struct { Key string Value string } ) if contentType := r.Header.Get("Content-Type"); api.MatchesContentType(contentType, "application/json") { if err := cgroupData.Decode(r.Body); err != nil { return err } } else { return fmt.Errorf("Content-Type not supported: %s", contentType) } readSubsystem = cgroupData.GetList("ReadSubsystem") if err := cgroupData.GetJson("WriteSubsystem", &writeSubsystem); err != nil { return err } job := eng.Job("cgroup", vars["name"]) job.SetenvList("readSubsystem", readSubsystem) job.SetenvJson("writeSubsystem", writeSubsystem) job.SetenvBool("saveToFile", saveToFile) job.Stdout.Add(w) if err := job.Run(); err != nil { return err } return nil }
func (cli *DockerCli) streamBody(body io.ReadCloser, contentType string, rawTerminal bool, stdout, stderr io.Writer) error { defer body.Close() if api.MatchesContentType(contentType, "application/json") { return jsonmessage.DisplayJSONMessagesStream(body, stdout, cli.outFd, cli.isTerminalOut) } if stdout != nil || stderr != nil { // When TTY is ON, use regular copy var err error if rawTerminal { _, err = io.Copy(stdout, body) } else { _, err = stdcopy.StdCopy(stdout, stderr, body) } logrus.Debugf("[stream] End of stdout") return err } return nil }
func postContainersCopy(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } var copyData engine.Env if contentType := r.Header.Get("Content-Type"); api.MatchesContentType(contentType, "application/json") { if err := copyData.Decode(r.Body); err != nil { return err } } else { return fmt.Errorf("Content-Type not supported: %s", contentType) } if copyData.Get("Resource") == "" { return fmt.Errorf("Path cannot be empty") } origResource := copyData.Get("Resource") if copyData.Get("Resource")[0] == '/' { copyData.Set("Resource", copyData.Get("Resource")[1:]) } job := eng.Job("container_copy", vars["name"], copyData.Get("Resource")) job.Stdout.Add(w) w.Header().Set("Content-Type", "application/x-tar") if err := job.Run(); err != nil { log.Errorf("%s", err.Error()) if strings.Contains(err.Error(), "No such container") { w.WriteHeader(http.StatusNotFound) } else if strings.Contains(err.Error(), "no such file or directory") { return fmt.Errorf("Could not find the file %s in container %s", origResource, vars["name"]) } } return nil }
func (cli *KraneClientApi) streamHelper(method, path string, setRawTerminal bool, in io.Reader, stdout, stderr io.Writer, headers map[string][]string) error { if (method == "POST" || method == "PUT") && in == nil { in = bytes.NewReader([]byte{}) } var req *http.Request var err error if cli.strictAPIversionControl { req, err = http.NewRequest(method, fmt.Sprintf("%s://%s:%d/v%s%s", cli.ship.Port, dockerApi.APIVERSION, path), in) } else { req, err = http.NewRequest(method, fmt.Sprintf("%s://%s:%d%s", cli.ship.Schema, "127.0.0.1", cli.ship.LocalPort, path), in) } if err != nil { return err } req.Header.Set("User-Agent", "Docker-Client/"+dockerVersion.VERSION) if method == "POST" { req.Header.Set("Content-Type", "plain/text") } if headers != nil { for k, v := range headers { req.Header[k] = v } } resp, err := cli.HTTPClient().Do(req) if err != nil { if strings.Contains(err.Error(), "connection refused") { return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?") } return err } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 400 { body, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if len(body) == 0 { return fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode)) } return fmt.Errorf("Error: %s", bytes.TrimSpace(body)) } if dockerApi.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") { return dockerUtils.DisplayJSONMessagesStream(resp.Body, stdout, cli.terminalFd, cli.isTerminal) } if stdout != nil || stderr != nil { // When TTY is ON, use regular copy if setRawTerminal { _, err = io.Copy(stdout, resp.Body) } else { _, err = dockerPkgStdCopy.StdCopy(stdout, stderr, resp.Body) } fmt.Printf("[stream] End of stdout") // TODO: Look into this return err } return nil }