Don't pretty-print by default. Saves an allocation (or more) and a copy.

This commit is contained in:
Brendan Burns 2015-06-08 16:33:58 -07:00
parent b68e08f55f
commit b68ddbaf75
8 changed files with 2603 additions and 19 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -409,6 +409,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.GET(action.Path).To(handler).
Filter(m).
Doc("read the specified "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Operation("read"+kind).
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), "application/json")...).
Returns(http.StatusOK, "OK", versionedObject).
@ -424,6 +425,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, false, a.minRequestTimeout)).
Filter(m).
Doc("list objects of kind "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Operation("list"+kind).
Produces("application/json").
Returns(http.StatusOK, "OK", versionedList).
@ -443,6 +445,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.PUT(action.Path).To(UpdateResource(updater, reqScope, a.group.Typer, admit)).
Filter(m).
Doc("replace the specified "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Operation("replace"+kind).
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), "application/json")...).
Returns(http.StatusOK, "OK", versionedObject).
@ -454,6 +457,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.PATCH(action.Path).To(PatchResource(patcher, reqScope, a.group.Typer, admit, mapping.ObjectConvertor)).
Filter(m).
Doc("partially update the specified "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Consumes(string(api.JSONPatchType), string(api.MergePatchType), string(api.StrategicMergePatchType)).
Operation("patch"+kind).
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), "application/json")...).
@ -472,6 +476,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.POST(action.Path).To(handler).
Filter(m).
Doc("create a "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Operation("create"+kind).
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), "application/json")...).
Returns(http.StatusOK, "OK", versionedObject).
@ -483,6 +488,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.DELETE(action.Path).To(DeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit)).
Filter(m).
Doc("delete a "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Operation("delete"+kind).
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), "application/json")...).
Writes(versionedStatus).
@ -497,6 +503,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, true, a.minRequestTimeout)).
Filter(m).
Doc("watch changes to an object of kind "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Operation("watch"+kind).
Produces("application/json").
Returns(http.StatusOK, "OK", watchjson.WatchEvent{}).
@ -511,6 +518,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, true, a.minRequestTimeout)).
Filter(m).
Doc("watch individual changes to a list of "+kind).
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
Operation("watch"+kind+"list").
Produces("application/json").
Returns(http.StatusOK, "OK", watchjson.WatchEvent{}).

View File

@ -273,32 +273,49 @@ func write(statusCode int, apiVersion string, codec runtime.Codec, object runtim
io.Copy(writer, out)
return
}
writeJSON(statusCode, codec, object, w)
writeJSON(statusCode, codec, object, w, isPrettyPrint(req))
}
func isPrettyPrint(req *http.Request) bool {
pp := req.URL.Query().Get("pretty")
if len(pp) > 0 {
pretty, _ := strconv.ParseBool(pp)
return pretty
}
userAgent := req.UserAgent()
// This covers basic all browers and cli http tools
if strings.HasPrefix(userAgent, "curl") || strings.HasPrefix(userAgent, "Wget") || strings.HasPrefix(userAgent, "Mozilla/5.0") {
return true
}
return false
}
// writeJSON renders an object as JSON to the response.
func writeJSON(statusCode int, codec runtime.Codec, object runtime.Object, w http.ResponseWriter) {
func writeJSON(statusCode int, codec runtime.Codec, object runtime.Object, w http.ResponseWriter, pretty bool) {
output, err := codec.Encode(object)
if err != nil {
errorJSONFatal(err, codec, w)
return
}
// PR #2243: Pretty-print JSON by default.
formatted := &bytes.Buffer{}
err = json.Indent(formatted, output, "", " ")
if err != nil {
errorJSONFatal(err, codec, w)
return
if pretty {
// PR #2243: Pretty-print JSON by default.
formatted := &bytes.Buffer{}
err = json.Indent(formatted, output, "", " ")
if err != nil {
errorJSONFatal(err, codec, w)
return
}
output = formatted.Bytes()
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
w.Write(formatted.Bytes())
w.Write(output)
}
// errorJSON renders an error to the response. Returns the HTTP status code of the error.
func errorJSON(err error, codec runtime.Codec, w http.ResponseWriter) int {
status := errToAPIStatus(err)
writeJSON(status.Code, codec, status, w)
writeJSON(status.Code, codec, status, w, true)
return status.Code
}

View File

@ -2239,7 +2239,7 @@ func (*UnregisteredAPIObject) IsAnAPIObject() {}
func TestWriteJSONDecodeError(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
writeJSON(http.StatusOK, codec, &UnregisteredAPIObject{"Undecodable"}, w)
writeJSON(http.StatusOK, codec, &UnregisteredAPIObject{"Undecodable"}, w, false)
}))
defer server.Close()
status := expectApiStatus(t, "GET", server.URL, nil, http.StatusInternalServerError)

View File

@ -111,7 +111,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if err != nil {
httplog.LogOf(req, w).Addf("Error getting ResourceLocation: %v", err)
status := errToAPIStatus(err)
writeJSON(status.Code, r.codec, status, w)
writeJSON(status.Code, r.codec, status, w, true)
httpCode = status.Code
return
}
@ -146,7 +146,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
newReq, err := http.NewRequest(req.Method, location.String(), req.Body)
if err != nil {
status := errToAPIStatus(err)
writeJSON(status.Code, r.codec, status, w)
writeJSON(status.Code, r.codec, status, w, true)
notFound(w, req)
httpCode = status.Code
return
@ -196,11 +196,10 @@ func (r *ProxyHandler) tryUpgrade(w http.ResponseWriter, req, newReq *http.Reque
if !httpstream.IsUpgradeRequest(req) {
return false
}
backendConn, err := dialURL(location, transport)
if err != nil {
status := errToAPIStatus(err)
writeJSON(status.Code, r.codec, status, w)
writeJSON(status.Code, r.codec, status, w, true)
return true
}
defer backendConn.Close()
@ -211,14 +210,14 @@ func (r *ProxyHandler) tryUpgrade(w http.ResponseWriter, req, newReq *http.Reque
requestHijackedConn, _, err := w.(http.Hijacker).Hijack()
if err != nil {
status := errToAPIStatus(err)
writeJSON(status.Code, r.codec, status, w)
writeJSON(status.Code, r.codec, status, w, true)
return true
}
defer requestHijackedConn.Close()
if err = newReq.Write(backendConn); err != nil {
status := errToAPIStatus(err)
writeJSON(status.Code, r.codec, status, w)
writeJSON(status.Code, r.codec, status, w, true)
return true
}

View File

@ -82,7 +82,7 @@ func (r *RedirectHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
location, _, err := redirector.ResourceLocation(ctx, id)
if err != nil {
status := errToAPIStatus(err)
writeJSON(status.Code, r.codec, status, w)
writeJSON(status.Code, r.codec, status, w, true)
httpCode = status.Code
return
}

View File

@ -505,7 +505,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType
if wasCreated {
status = http.StatusCreated
}
writeJSON(status, scope.Codec, result, w)
writeJSON(status, scope.Codec, result, w, isPrettyPrint(req.Request))
}
}