func (r *errorResponse) Render(w http.ResponseWriter) error { var output io.Writer buf := &bytes.Buffer{} output = buf var captured *bytes.Buffer if debug { captured = &bytes.Buffer{} output = io.MultiWriter(buf, captured) } err := json.NewEncoder(output).Encode(shared.Jmap{"type": lxd.Error, "error": r.msg, "error_code": r.code}) if err != nil { return err } if debug { shared.DebugJson(captured) } w.Header().Set("Content-Type", "application/json") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(r.code) fmt.Fprintln(w, buf.String()) return nil }
func WriteJSON(w http.ResponseWriter, body interface{}) error { var output io.Writer var captured *bytes.Buffer output = w if *debug { captured = &bytes.Buffer{} output = io.MultiWriter(w, captured) } err := json.NewEncoder(output).Encode(body) if captured != nil { shared.DebugJson(captured) } return err }
func (r *ErrorResponse) Render(w http.ResponseWriter) error { var output io.Writer buf := &bytes.Buffer{} output = buf var captured *bytes.Buffer if *debug { captured = &bytes.Buffer{} output = io.MultiWriter(buf, captured) } err := json.NewEncoder(output).Encode(shared.Jmap{"type": lxd.Error, "error": r.msg, "error_code": r.code}) if err != nil { return err } if *debug { shared.DebugJson(captured) } http.Error(w, buf.String(), r.code) return nil }
func (d *Daemon) createCmd(version string, c Command) { var uri string if c.name == "" { uri = fmt.Sprintf("/%s", version) } else { uri = fmt.Sprintf("/%s/%s", version, c.name) } d.mux.HandleFunc(uri, func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") if d.isTrustedClient(r) { shared.Log.Info( "handling", log.Ctx{"method": r.Method, "url": r.URL.RequestURI(), "ip": r.RemoteAddr}) } else if r.Method == "GET" && c.untrustedGet { shared.Log.Info( "allowing untrusted GET", log.Ctx{"url": r.URL.RequestURI(), "ip": r.RemoteAddr}) } else if r.Method == "POST" && c.untrustedPost { shared.Log.Info( "allowing untrusted POST", log.Ctx{"url": r.URL.RequestURI(), "ip": r.RemoteAddr}) } else { shared.Log.Warn( "rejecting request from untrusted client", log.Ctx{"ip": r.RemoteAddr}) Forbidden.Render(w) return } if debug && r.Method != "GET" && isJSONRequest(r) { newBody := &bytes.Buffer{} captured := &bytes.Buffer{} multiW := io.MultiWriter(newBody, captured) if _, err := io.Copy(multiW, r.Body); err != nil { InternalError(err).Render(w) return } r.Body = shared.BytesReadCloser{Buf: newBody} shared.DebugJson(captured) } var resp Response resp = NotImplemented switch r.Method { case "GET": if c.get != nil { resp = c.get(d, r) } case "PUT": if c.put != nil { resp = c.put(d, r) } case "POST": if c.post != nil { resp = c.post(d, r) } case "DELETE": if c.delete != nil { resp = c.delete(d, r) } default: resp = NotFound } if err := resp.Render(w); err != nil { err := InternalError(err).Render(w) if err != nil { shared.Log.Error("Failed writing error for error, giving up") } } /* * When we create a new lxc.Container, it adds a finalizer (via * SetFinalizer) that frees the struct. However, it sometimes * takes the go GC a while to actually free the struct, * presumably since it is a small amount of memory. * Unfortunately, the struct also keeps the log fd open, so if * we leave too many of these around, we end up running out of * fds. So, let's explicitly do a GC to collect these at the * end of each request. */ runtime.GC() }) }