upgrade web/ to use protojson (#7995)

As part of #7881 it is recommended we upgrade to use `protojson` instead of `jsonPb`. This required a few additional changes in the code since the signature of `Marshal` changed so I've split this out into a separate change.

`Marshal` now returns the resulting bytes instead of taking an interface to write those bytes into. This means we have to handle the error separately and then write the JSON into the given writer.

Signed-off-by: Kevin Leimkuhler <kleimkuhler@icloud.com>
This commit is contained in:
Kevin Leimkuhler 2022-03-09 17:06:19 -07:00 committed by GitHub
parent b9001ba6b7
commit 4ab6b9a3b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 12 deletions

View File

@ -11,8 +11,6 @@ import (
"strings"
"time"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/gorilla/websocket"
"github.com/julienschmidt/httprouter"
"github.com/linkerd/linkerd2/pkg/healthcheck"
@ -23,6 +21,8 @@ import (
tapPb "github.com/linkerd/linkerd2/viz/tap/gen/tap"
tappkg "github.com/linkerd/linkerd2/viz/tap/pkg"
log "github.com/sirupsen/logrus"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
@ -40,7 +40,7 @@ type (
var (
defaultResourceType = k8s.Deployment
pbMarshaler = jsonpb.Marshaler{EmitDefaults: true}
pbMarshaler = protojson.MarshalOptions{EmitUnpopulated: true}
maxMessageSize = 2048
websocketUpgrader = websocket.Upgrader{
ReadBufferSize: maxMessageSize,
@ -76,9 +76,11 @@ func renderJSON(w http.ResponseWriter, resp interface{}) {
func renderJSONPb(w http.ResponseWriter, msg proto.Message) {
w.Header().Set("Content-Type", "application/json")
// Callers of renderJSONPb pass in msgs that can be serialized into JSON.
//nolint:errcheck
pbMarshaler.Marshal(w, msg)
json, err := pbMarshaler.Marshal(msg)
if err != nil {
renderJSONError(w, err, http.StatusBadRequest)
}
w.Write(json)
}
func renderJSONBytes(w http.ResponseWriter, b []byte) {
@ -170,11 +172,14 @@ func (h *handler) handleAPIStat(w http.ResponseWriter, req *http.Request, p http
}
// Marshal result into json and cache it
var resultJSON bytes.Buffer
if err := pbMarshaler.Marshal(&resultJSON, result); err != nil {
json, err := pbMarshaler.Marshal(result)
if err != nil {
renderJSONError(w, err, http.StatusInternalServerError)
return
}
var resultJSON bytes.Buffer
resultJSON.Write(json)
h.statCache.SetDefault(req.URL.RawQuery, resultJSON.Bytes())
renderJSONBytes(w, resultJSON.Bytes())
@ -297,12 +302,13 @@ func (h *handler) handleAPITap(w http.ResponseWriter, req *http.Request, p httpr
break
}
buf := new(bytes.Buffer)
err = pbMarshaler.Marshal(buf, &event)
json, err := pbMarshaler.Marshal(&event)
if err != nil {
websocketError(ws, websocket.CloseInternalServerErr, err)
break
}
buf := new(bytes.Buffer)
buf.Write(json)
if err := ws.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure) {

View File

@ -155,8 +155,13 @@ func TestHandleApiGateway(t *testing.T) {
if err != nil {
t.Fatalf("not expecting error compacting api check output golden file but got: %v", err)
}
if !bytes.Equal(body, apiGatewayOutputGoldenCompact.Bytes()) {
t.Errorf("expecting response body to be\n %s\n but got\n %s", apiGatewayOutputGoldenCompact.Bytes(), body)
bodyCompact := &bytes.Buffer{}
err = json.Compact(bodyCompact, body)
if err != nil {
t.Fatalf("failed to compact response body: %s", err)
}
if !bytes.Equal(bodyCompact.Bytes(), apiGatewayOutputGoldenCompact.Bytes()) {
t.Errorf("expecting response body to be\n %s\n but got\n %s", apiGatewayOutputGoldenCompact.Bytes(), bodyCompact.Bytes())
}
})