Files
releases/runtime/logging_test.go
T
Stephan Renatus 1df27c789b runtime/logging: only suppress payloads for handlers that compress responses (#4502)
* runtime/logging: only suppress payloads for handlers that compress responses

To get compressed responses, two things need to be true:

1. The client must accept compressed responses
2. The handler must reply with a compressed response

For general API requests, (1) holds most of the time. (2) is only true
for the metrics endpoint at them moment, since the 3rd party library we
use for serving the prometheus endpoint will do compression.

* runtime/logging: remove dead code

The http.Hijack stuff was related to a watch feature removed in
https://github.com/open-policy-agent/opa/commit/186ef99ffaa3b32e4ae2b4a8c6c59182e06770e4

dropInputParam was only used by its tests.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
2022-03-30 10:01:34 +02:00

173 lines
4.4 KiB
Go

// Copyright 2016 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
// nolint: goconst // string duplication is for test readability.
package runtime
import (
"context"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/open-policy-agent/opa/logging"
"github.com/open-policy-agent/opa/logging/test"
)
func TestValidateGzipHeader(t *testing.T) {
httpHeader := http.Header{}
httpHeader.Add("Accept", "*/*")
if result, expected := gzipAccepted(httpHeader), false; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
httpHeader.Add("Accept-Encoding", "gzip")
if result, expected := gzipAccepted(httpHeader), true; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
httpHeader.Set("Accept-Encoding", "gzip, deflate, br")
if result, expected := gzipAccepted(httpHeader), true; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
httpHeader.Set("Accept-Encoding", "br;q=1.0, gzip;q=0.8, *;q=0.1")
if result, expected := gzipAccepted(httpHeader), true; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
}
func TestValidatePprofUrl(t *testing.T) {
req := http.Request{}
req.URL = &url.URL{Path: "/metrics"}
if result, expected := isPprofEndpoint(&req), false; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
req.URL = &url.URL{Path: "/debug/pprof/"}
if result, expected := isPprofEndpoint(&req), true; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
}
func TestValidateMetricsUrl(t *testing.T) {
req := http.Request{}
req.URL = &url.URL{Path: "/metrics"}
if result, expected := isMetricsEndpoint(&req), true; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
req.URL = &url.URL{Path: "/debug/pprof/"}
if result, expected := isMetricsEndpoint(&req), false; result != expected {
t.Errorf("Expected %v but got: %v", expected, result)
}
}
func TestRequestLogging(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
logger := test.New()
logger.SetLevel(logging.Debug)
shutdownSeconds := 1
params := NewParams()
params.Addrs = &[]string{":0"}
params.Logger = logger
params.PprofEnabled = true
params.GracefulShutdownPeriod = shutdownSeconds // arbitrary, must be non-zero
rt, err := NewRuntime(ctx, params)
if err != nil {
t.Fatal(err)
}
initChannel := rt.Manager.ServerInitializedChannel()
go func() {
if err := rt.Serve(ctx); err != nil {
t.Error(err)
}
}()
<-initChannel
tests := []struct {
path string
acceptEncoding string
expected string
}{
{
"/metrics", "gzip", "[compressed payload]",
},
{
"/metrics", "*/*", "HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.", // rest omitted
},
{ // accept-encoding does not matter for "our" handlers -- they don't compress
"/v1/data", "gzip", "{\"result\":{}}",
},
{ // accept-encoding does not matter for pprof: it's always protobuf
"/debug/pprof/cmdline", "*/*", "[binary payload]",
},
}
// execute all the requests
for _, tc := range tests {
rec := httptest.NewRecorder()
req, err := http.NewRequest("GET", tc.path, nil)
if err != nil {
t.Fatal(err)
}
req.Header.Set("Accept-Encoding", tc.acceptEncoding)
rt.server.Handler.ServeHTTP(rec, req)
if exp, act := http.StatusOK, rec.Result().StatusCode; exp != act {
t.Errorf("GET %s: expected HTTP %d, got %d", tc.path, exp, act)
}
}
cancel()
// check the logs
ents := logger.Entries()
for j, tc := range tests {
i := uint64(j + 1)
found := false
for _, ent := range entriesForReq(ents, i) {
if ent.Message == "Sent response." {
act := ent.Fields["resp_body"].(string)
if !strings.Contains(act, tc.expected) {
t.Errorf("expected %q in resp_body field, got %q", tc.expected, act)
}
found = true
}
}
if !found {
t.Errorf("Expected \"Sent response.\" log for request %d (path %s)", j, tc.path)
}
}
if t.Failed() {
t.Logf("logs: %v", ents)
}
}
func entriesForReq(ents []test.LogEntry, n uint64) []test.LogEntry {
var ret []test.LogEntry
for _, e := range ents {
if r, ok := e.Fields["req_id"]; ok {
if i, ok := r.(uint64); ok {
if i == n {
ret = append(ret, e)
}
}
}
}
return ret
}