Replace GraphQL server with Connect RPC

This commit is contained in:
David Stotijn
2025-02-05 21:54:59 +01:00
parent 52c83a1989
commit 6889c9c183
53 changed files with 5875 additions and 11685 deletions

View File

@ -3,15 +3,13 @@ package reqlog
import (
"context"
"github.com/oklog/ulid"
"github.com/dstotijn/hetty/pkg/scope"
httppb "github.com/dstotijn/hetty/pkg/http"
)
type Repository interface {
FindRequestLogs(ctx context.Context, filter FindRequestsFilter, scope *scope.Scope) ([]RequestLog, error)
FindRequestLogByID(ctx context.Context, projectID, id ulid.ULID) (RequestLog, error)
StoreRequestLog(ctx context.Context, reqLog RequestLog) error
StoreResponseLog(ctx context.Context, projectID, reqLogID ulid.ULID, resLog ResponseLog) error
ClearRequestLogs(ctx context.Context, projectID ulid.ULID) error
FindRequestLogs(ctx context.Context, projectID string, filterFn func(*HttpRequestLog) (bool, error)) ([]*HttpRequestLog, error)
FindRequestLogByID(ctx context.Context, projectID, id string) (*HttpRequestLog, error)
StoreRequestLog(ctx context.Context, reqLog *HttpRequestLog) error
StoreResponseLog(ctx context.Context, projectID, reqLogID string, resLog *httppb.Response) error
ClearRequestLogs(ctx context.Context, projectID string) error
}

View File

@ -0,0 +1,167 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: reqlog/reqlog.proto
package reqlog
import (
connect "connectrpc.com/connect"
context "context"
errors "errors"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect.IsAtLeastVersion1_13_0
const (
// HttpRequestLogServiceName is the fully-qualified name of the HttpRequestLogService service.
HttpRequestLogServiceName = "hetty.reqlog.v1.HttpRequestLogService"
)
// These constants are the fully-qualified names of the RPCs defined in this package. They're
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
//
// Note that these are different from the fully-qualified method names used by
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
// period.
const (
// HttpRequestLogServiceGetHttpRequestLogProcedure is the fully-qualified name of the
// HttpRequestLogService's GetHttpRequestLog RPC.
HttpRequestLogServiceGetHttpRequestLogProcedure = "/hetty.reqlog.v1.HttpRequestLogService/GetHttpRequestLog"
// HttpRequestLogServiceListHttpRequestLogsProcedure is the fully-qualified name of the
// HttpRequestLogService's ListHttpRequestLogs RPC.
HttpRequestLogServiceListHttpRequestLogsProcedure = "/hetty.reqlog.v1.HttpRequestLogService/ListHttpRequestLogs"
// HttpRequestLogServiceClearHttpRequestLogsProcedure is the fully-qualified name of the
// HttpRequestLogService's ClearHttpRequestLogs RPC.
HttpRequestLogServiceClearHttpRequestLogsProcedure = "/hetty.reqlog.v1.HttpRequestLogService/ClearHttpRequestLogs"
)
// HttpRequestLogServiceClient is a client for the hetty.reqlog.v1.HttpRequestLogService service.
type HttpRequestLogServiceClient interface {
GetHttpRequestLog(context.Context, *connect.Request[GetHttpRequestLogRequest]) (*connect.Response[GetHttpRequestLogResponse], error)
ListHttpRequestLogs(context.Context, *connect.Request[ListHttpRequestLogsRequest]) (*connect.Response[ListHttpRequestLogsResponse], error)
ClearHttpRequestLogs(context.Context, *connect.Request[ClearHttpRequestLogsRequest]) (*connect.Response[ClearHttpRequestLogsResponse], error)
}
// NewHttpRequestLogServiceClient constructs a client for the hetty.reqlog.v1.HttpRequestLogService
// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for
// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply
// the connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewHttpRequestLogServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) HttpRequestLogServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
httpRequestLogServiceMethods := File_reqlog_reqlog_proto.Services().ByName("HttpRequestLogService").Methods()
return &httpRequestLogServiceClient{
getHttpRequestLog: connect.NewClient[GetHttpRequestLogRequest, GetHttpRequestLogResponse](
httpClient,
baseURL+HttpRequestLogServiceGetHttpRequestLogProcedure,
connect.WithSchema(httpRequestLogServiceMethods.ByName("GetHttpRequestLog")),
connect.WithClientOptions(opts...),
),
listHttpRequestLogs: connect.NewClient[ListHttpRequestLogsRequest, ListHttpRequestLogsResponse](
httpClient,
baseURL+HttpRequestLogServiceListHttpRequestLogsProcedure,
connect.WithSchema(httpRequestLogServiceMethods.ByName("ListHttpRequestLogs")),
connect.WithClientOptions(opts...),
),
clearHttpRequestLogs: connect.NewClient[ClearHttpRequestLogsRequest, ClearHttpRequestLogsResponse](
httpClient,
baseURL+HttpRequestLogServiceClearHttpRequestLogsProcedure,
connect.WithSchema(httpRequestLogServiceMethods.ByName("ClearHttpRequestLogs")),
connect.WithClientOptions(opts...),
),
}
}
// httpRequestLogServiceClient implements HttpRequestLogServiceClient.
type httpRequestLogServiceClient struct {
getHttpRequestLog *connect.Client[GetHttpRequestLogRequest, GetHttpRequestLogResponse]
listHttpRequestLogs *connect.Client[ListHttpRequestLogsRequest, ListHttpRequestLogsResponse]
clearHttpRequestLogs *connect.Client[ClearHttpRequestLogsRequest, ClearHttpRequestLogsResponse]
}
// GetHttpRequestLog calls hetty.reqlog.v1.HttpRequestLogService.GetHttpRequestLog.
func (c *httpRequestLogServiceClient) GetHttpRequestLog(ctx context.Context, req *connect.Request[GetHttpRequestLogRequest]) (*connect.Response[GetHttpRequestLogResponse], error) {
return c.getHttpRequestLog.CallUnary(ctx, req)
}
// ListHttpRequestLogs calls hetty.reqlog.v1.HttpRequestLogService.ListHttpRequestLogs.
func (c *httpRequestLogServiceClient) ListHttpRequestLogs(ctx context.Context, req *connect.Request[ListHttpRequestLogsRequest]) (*connect.Response[ListHttpRequestLogsResponse], error) {
return c.listHttpRequestLogs.CallUnary(ctx, req)
}
// ClearHttpRequestLogs calls hetty.reqlog.v1.HttpRequestLogService.ClearHttpRequestLogs.
func (c *httpRequestLogServiceClient) ClearHttpRequestLogs(ctx context.Context, req *connect.Request[ClearHttpRequestLogsRequest]) (*connect.Response[ClearHttpRequestLogsResponse], error) {
return c.clearHttpRequestLogs.CallUnary(ctx, req)
}
// HttpRequestLogServiceHandler is an implementation of the hetty.reqlog.v1.HttpRequestLogService
// service.
type HttpRequestLogServiceHandler interface {
GetHttpRequestLog(context.Context, *connect.Request[GetHttpRequestLogRequest]) (*connect.Response[GetHttpRequestLogResponse], error)
ListHttpRequestLogs(context.Context, *connect.Request[ListHttpRequestLogsRequest]) (*connect.Response[ListHttpRequestLogsResponse], error)
ClearHttpRequestLogs(context.Context, *connect.Request[ClearHttpRequestLogsRequest]) (*connect.Response[ClearHttpRequestLogsResponse], error)
}
// NewHttpRequestLogServiceHandler builds an HTTP handler from the service implementation. It
// returns the path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewHttpRequestLogServiceHandler(svc HttpRequestLogServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
httpRequestLogServiceMethods := File_reqlog_reqlog_proto.Services().ByName("HttpRequestLogService").Methods()
httpRequestLogServiceGetHttpRequestLogHandler := connect.NewUnaryHandler(
HttpRequestLogServiceGetHttpRequestLogProcedure,
svc.GetHttpRequestLog,
connect.WithSchema(httpRequestLogServiceMethods.ByName("GetHttpRequestLog")),
connect.WithHandlerOptions(opts...),
)
httpRequestLogServiceListHttpRequestLogsHandler := connect.NewUnaryHandler(
HttpRequestLogServiceListHttpRequestLogsProcedure,
svc.ListHttpRequestLogs,
connect.WithSchema(httpRequestLogServiceMethods.ByName("ListHttpRequestLogs")),
connect.WithHandlerOptions(opts...),
)
httpRequestLogServiceClearHttpRequestLogsHandler := connect.NewUnaryHandler(
HttpRequestLogServiceClearHttpRequestLogsProcedure,
svc.ClearHttpRequestLogs,
connect.WithSchema(httpRequestLogServiceMethods.ByName("ClearHttpRequestLogs")),
connect.WithHandlerOptions(opts...),
)
return "/hetty.reqlog.v1.HttpRequestLogService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case HttpRequestLogServiceGetHttpRequestLogProcedure:
httpRequestLogServiceGetHttpRequestLogHandler.ServeHTTP(w, r)
case HttpRequestLogServiceListHttpRequestLogsProcedure:
httpRequestLogServiceListHttpRequestLogsHandler.ServeHTTP(w, r)
case HttpRequestLogServiceClearHttpRequestLogsProcedure:
httpRequestLogServiceClearHttpRequestLogsHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
})
}
// UnimplementedHttpRequestLogServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedHttpRequestLogServiceHandler struct{}
func (UnimplementedHttpRequestLogServiceHandler) GetHttpRequestLog(context.Context, *connect.Request[GetHttpRequestLogRequest]) (*connect.Response[GetHttpRequestLogResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hetty.reqlog.v1.HttpRequestLogService.GetHttpRequestLog is not implemented"))
}
func (UnimplementedHttpRequestLogServiceHandler) ListHttpRequestLogs(context.Context, *connect.Request[ListHttpRequestLogsRequest]) (*connect.Response[ListHttpRequestLogsResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hetty.reqlog.v1.HttpRequestLogService.ListHttpRequestLogs is not implemented"))
}
func (UnimplementedHttpRequestLogServiceHandler) ClearHttpRequestLogs(context.Context, *connect.Request[ClearHttpRequestLogsRequest]) (*connect.Response[ClearHttpRequestLogsResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hetty.reqlog.v1.HttpRequestLogService.ClearHttpRequestLogs is not implemented"))
}

View File

@ -6,13 +6,13 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"github.com/oklog/ulid"
"connectrpc.com/connect"
"github.com/oklog/ulid/v2"
"github.com/dstotijn/hetty/pkg/filter"
httppb "github.com/dstotijn/hetty/pkg/http"
"github.com/dstotijn/hetty/pkg/log"
"github.com/dstotijn/hetty/pkg/proxy"
"github.com/dstotijn/hetty/pkg/scope"
@ -26,48 +26,21 @@ const (
)
var (
ErrRequestNotFound = errors.New("reqlog: request not found")
ErrRequestLogNotFound = errors.New("reqlog: request not found")
ErrProjectIDMustBeSet = errors.New("reqlog: project ID must be set")
)
type RequestLog struct {
ID ulid.ULID
ProjectID ulid.ULID
URL *url.URL
Method string
Proto string
Header http.Header
Body []byte
Response *ResponseLog
}
type ResponseLog struct {
Proto string
StatusCode int
Status string
Header http.Header
Body []byte
}
type Service struct {
bypassOutOfScopeRequests bool
findReqsFilter FindRequestsFilter
activeProjectID ulid.ULID
reqsFilter *RequestLogsFilter
activeProjectID string
scope *scope.Scope
repo Repository
logger log.Logger
}
type FindRequestsFilter struct {
ProjectID ulid.ULID
OnlyInScope bool
SearchExpr filter.Expression
}
type Config struct {
ActiveProjectID ulid.ULID
ActiveProjectID string
Scope *scope.Scope
Repository Repository
Logger log.Logger
@ -88,25 +61,92 @@ func NewService(cfg Config) *Service {
return s
}
func (svc *Service) FindRequests(ctx context.Context) ([]RequestLog, error) {
return svc.repo.FindRequestLogs(ctx, svc.findReqsFilter, svc.scope)
func (svc *Service) ListHttpRequestLogs(ctx context.Context, req *connect.Request[ListHttpRequestLogsRequest]) (*connect.Response[ListHttpRequestLogsResponse], error) {
projectID := svc.activeProjectID
if projectID == "" {
return nil, connect.NewError(connect.CodeFailedPrecondition, ErrProjectIDMustBeSet)
}
reqLogs, err := svc.repo.FindRequestLogs(ctx, projectID, svc.filterRequestLog)
if err != nil {
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("reqlog: failed to find request logs: %w", err))
}
return connect.NewResponse(&ListHttpRequestLogsResponse{
HttpRequestLogs: reqLogs,
}), nil
}
func (svc *Service) FindRequestLogByID(ctx context.Context, id ulid.ULID) (RequestLog, error) {
func (svc *Service) filterRequestLog(reqLog *HttpRequestLog) (bool, error) {
if svc.reqsFilter.GetOnlyInScope() && svc.scope != nil && !reqLog.MatchScope(svc.scope) {
return false, nil
}
var f filter.Expression
var err error
if expr := svc.reqsFilter.GetSearchExpr(); expr != "" {
f, err = filter.ParseQuery(expr)
if err != nil {
return false, fmt.Errorf("failed to parse search expression: %w", err)
}
}
if f == nil {
return true, nil
}
match, err := reqLog.Matches(f)
if err != nil {
return false, fmt.Errorf("failed to match search expression for request log (id: %v): %w", reqLog.Id, err)
}
return match, nil
}
func (svc *Service) FindRequestLogByID(ctx context.Context, id string) (*HttpRequestLog, error) {
if svc.activeProjectID == "" {
return nil, connect.NewError(connect.CodeFailedPrecondition, ErrProjectIDMustBeSet)
}
return svc.repo.FindRequestLogByID(ctx, svc.activeProjectID, id)
}
func (svc *Service) ClearRequests(ctx context.Context, projectID ulid.ULID) error {
return svc.repo.ClearRequestLogs(ctx, projectID)
// GetHttpRequestLog implements HttpRequestLogServiceHandler.
func (svc *Service) GetHttpRequestLog(ctx context.Context, req *connect.Request[GetHttpRequestLogRequest]) (*connect.Response[GetHttpRequestLogResponse], error) {
id, err := ulid.Parse(req.Msg.Id)
if err != nil {
return nil, connect.NewError(connect.CodeInvalidArgument, err)
}
reqLog, err := svc.repo.FindRequestLogByID(ctx, svc.activeProjectID, id.String())
if errors.Is(err, ErrRequestLogNotFound) {
return nil, connect.NewError(connect.CodeNotFound, err)
}
if err != nil {
return nil, connect.NewError(connect.CodeInternal, err)
}
return connect.NewResponse(&GetHttpRequestLogResponse{
HttpRequestLog: reqLog,
}), nil
}
func (svc *Service) storeResponse(ctx context.Context, reqLogID ulid.ULID, res *http.Response) error {
resLog, err := ParseHTTPResponse(res)
func (svc *Service) ClearHttpRequestLogs(ctx context.Context, req *connect.Request[ClearHttpRequestLogsRequest]) (*connect.Response[ClearHttpRequestLogsResponse], error) {
err := svc.repo.ClearRequestLogs(ctx, svc.activeProjectID)
if err != nil {
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("reqlog: failed to clear request logs: %w", err))
}
return connect.NewResponse(&ClearHttpRequestLogsResponse{}), nil
}
func (svc *Service) storeResponse(ctx context.Context, reqLogID string, res *http.Response) error {
respb, err := httppb.ParseHTTPResponse(res)
if err != nil {
return err
}
return svc.repo.StoreResponseLog(ctx, svc.activeProjectID, reqLogID, resLog)
return svc.repo.StoreResponseLog(ctx, svc.activeProjectID, reqLogID, respb)
}
func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestModifyFunc {
@ -121,19 +161,19 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM
// TODO: Use io.LimitReader.
var err error
body, err = ioutil.ReadAll(req.Body)
body, err = io.ReadAll(req.Body)
if err != nil {
svc.logger.Errorw("Failed to read request body for logging.",
"error", err)
return
}
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
clone.Body = ioutil.NopCloser(bytes.NewBuffer(body))
req.Body = io.NopCloser(bytes.NewBuffer(body))
clone.Body = io.NopCloser(bytes.NewBuffer(body))
}
// Bypass logging if no project is active.
if svc.activeProjectID.Compare(ulid.ULID{}) == 0 {
if svc.activeProjectID == "" {
ctx := context.WithValue(req.Context(), LogBypassedKey, true)
*req = *req.WithContext(ctx)
@ -161,14 +201,37 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM
return
}
reqLog := RequestLog{
ID: reqID,
ProjectID: svc.activeProjectID,
Method: clone.Method,
URL: clone.URL,
Proto: clone.Proto,
Header: clone.Header,
Body: body,
proto, ok := httppb.ProtoMap[clone.Proto]
if !ok {
svc.logger.Errorw("Bypassed logging: request has an invalid protocol.",
"proto", clone.Proto)
return
}
method, ok := httppb.MethodMap[clone.Method]
if !ok {
svc.logger.Errorw("Bypassed logging: request has an invalid method.",
"method", clone.Method)
return
}
headers := []*httppb.Header{}
for k, v := range clone.Header {
for _, vv := range v {
headers = append(headers, &httppb.Header{Key: k, Value: vv})
}
}
reqLog := &HttpRequestLog{
Id: reqID.String(),
ProjectId: svc.activeProjectID,
Request: &httppb.Request{
Url: clone.URL.String(),
Method: method,
Protocol: proto,
Headers: headers,
Body: body,
},
}
err := svc.repo.StoreRequestLog(req.Context(), reqLog)
@ -179,10 +242,10 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM
}
svc.logger.Debugw("Stored request log.",
"reqLogID", reqLog.ID.String(),
"url", reqLog.URL.String())
ctx := context.WithValue(req.Context(), ReqLogIDKey, reqLog.ID)
"reqLogID", reqLog.Id,
"url", reqLog.Request.Url,
)
ctx := context.WithValue(req.Context(), ReqLogIDKey, reqID)
*req = *req.WithContext(ctx)
}
}
@ -216,7 +279,7 @@ func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.Respon
}
go func() {
if err := svc.storeResponse(context.Background(), reqLogID, &clone); err != nil {
if err := svc.storeResponse(context.Background(), reqLogID.String(), &clone); err != nil {
svc.logger.Errorw("Failed to store response log.",
"error", err)
} else {
@ -229,20 +292,16 @@ func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.Respon
}
}
func (svc *Service) SetActiveProjectID(id ulid.ULID) {
func (svc *Service) SetActiveProjectID(id string) {
svc.activeProjectID = id
}
func (svc *Service) ActiveProjectID() ulid.ULID {
func (svc *Service) ActiveProjectID() string {
return svc.activeProjectID
}
func (svc *Service) SetFindReqsFilter(filter FindRequestsFilter) {
svc.findReqsFilter = filter
}
func (svc *Service) FindReqsFilter() FindRequestsFilter {
return svc.findReqsFilter
func (svc *Service) SetRequestLogsFilter(filter *RequestLogsFilter) {
svc.reqsFilter = filter
}
func (svc *Service) SetBypassOutOfScopeRequests(bypass bool) {
@ -252,18 +311,3 @@ func (svc *Service) SetBypassOutOfScopeRequests(bypass bool) {
func (svc *Service) BypassOutOfScopeRequests() bool {
return svc.bypassOutOfScopeRequests
}
func ParseHTTPResponse(res *http.Response) (ResponseLog, error) {
body, err := io.ReadAll(res.Body)
if err != nil {
return ResponseLog{}, fmt.Errorf("reqlog: could not read body: %w", err)
}
return ResponseLog{
Proto: res.Proto,
StatusCode: res.StatusCode,
Status: res.Status,
Header: res.Header,
Body: body,
}, nil
}

533
pkg/reqlog/reqlog.pb.go Normal file
View File

@ -0,0 +1,533 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.3
// protoc (unknown)
// source: reqlog/reqlog.proto
package reqlog
import (
http "github.com/dstotijn/hetty/pkg/http"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type HttpRequestLog struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
ProjectId string `protobuf:"bytes,2,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"`
RemoteIp string `protobuf:"bytes,3,opt,name=remote_ip,json=remoteIp,proto3" json:"remote_ip,omitempty"`
Request *http.Request `protobuf:"bytes,4,opt,name=request,proto3" json:"request,omitempty"`
Response *http.Response `protobuf:"bytes,5,opt,name=response,proto3" json:"response,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *HttpRequestLog) Reset() {
*x = HttpRequestLog{}
mi := &file_reqlog_reqlog_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *HttpRequestLog) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HttpRequestLog) ProtoMessage() {}
func (x *HttpRequestLog) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HttpRequestLog.ProtoReflect.Descriptor instead.
func (*HttpRequestLog) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{0}
}
func (x *HttpRequestLog) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *HttpRequestLog) GetProjectId() string {
if x != nil {
return x.ProjectId
}
return ""
}
func (x *HttpRequestLog) GetRemoteIp() string {
if x != nil {
return x.RemoteIp
}
return ""
}
func (x *HttpRequestLog) GetRequest() *http.Request {
if x != nil {
return x.Request
}
return nil
}
func (x *HttpRequestLog) GetResponse() *http.Response {
if x != nil {
return x.Response
}
return nil
}
type GetHttpRequestLogRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetHttpRequestLogRequest) Reset() {
*x = GetHttpRequestLogRequest{}
mi := &file_reqlog_reqlog_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetHttpRequestLogRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetHttpRequestLogRequest) ProtoMessage() {}
func (x *GetHttpRequestLogRequest) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetHttpRequestLogRequest.ProtoReflect.Descriptor instead.
func (*GetHttpRequestLogRequest) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{1}
}
func (x *GetHttpRequestLogRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type GetHttpRequestLogResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
HttpRequestLog *HttpRequestLog `protobuf:"bytes,1,opt,name=http_request_log,json=httpRequestLog,proto3" json:"http_request_log,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetHttpRequestLogResponse) Reset() {
*x = GetHttpRequestLogResponse{}
mi := &file_reqlog_reqlog_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetHttpRequestLogResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetHttpRequestLogResponse) ProtoMessage() {}
func (x *GetHttpRequestLogResponse) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetHttpRequestLogResponse.ProtoReflect.Descriptor instead.
func (*GetHttpRequestLogResponse) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{2}
}
func (x *GetHttpRequestLogResponse) GetHttpRequestLog() *HttpRequestLog {
if x != nil {
return x.HttpRequestLog
}
return nil
}
type ListHttpRequestLogsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListHttpRequestLogsRequest) Reset() {
*x = ListHttpRequestLogsRequest{}
mi := &file_reqlog_reqlog_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListHttpRequestLogsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListHttpRequestLogsRequest) ProtoMessage() {}
func (x *ListHttpRequestLogsRequest) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListHttpRequestLogsRequest.ProtoReflect.Descriptor instead.
func (*ListHttpRequestLogsRequest) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{3}
}
type ListHttpRequestLogsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
HttpRequestLogs []*HttpRequestLog `protobuf:"bytes,1,rep,name=http_request_logs,json=httpRequestLogs,proto3" json:"http_request_logs,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListHttpRequestLogsResponse) Reset() {
*x = ListHttpRequestLogsResponse{}
mi := &file_reqlog_reqlog_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListHttpRequestLogsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListHttpRequestLogsResponse) ProtoMessage() {}
func (x *ListHttpRequestLogsResponse) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListHttpRequestLogsResponse.ProtoReflect.Descriptor instead.
func (*ListHttpRequestLogsResponse) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{4}
}
func (x *ListHttpRequestLogsResponse) GetHttpRequestLogs() []*HttpRequestLog {
if x != nil {
return x.HttpRequestLogs
}
return nil
}
type RequestLogsFilter struct {
state protoimpl.MessageState `protogen:"open.v1"`
OnlyInScope bool `protobuf:"varint,1,opt,name=only_in_scope,json=onlyInScope,proto3" json:"only_in_scope,omitempty"`
SearchExpr string `protobuf:"bytes,2,opt,name=search_expr,json=searchExpr,proto3" json:"search_expr,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RequestLogsFilter) Reset() {
*x = RequestLogsFilter{}
mi := &file_reqlog_reqlog_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RequestLogsFilter) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RequestLogsFilter) ProtoMessage() {}
func (x *RequestLogsFilter) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RequestLogsFilter.ProtoReflect.Descriptor instead.
func (*RequestLogsFilter) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{5}
}
func (x *RequestLogsFilter) GetOnlyInScope() bool {
if x != nil {
return x.OnlyInScope
}
return false
}
func (x *RequestLogsFilter) GetSearchExpr() string {
if x != nil {
return x.SearchExpr
}
return ""
}
type ClearHttpRequestLogsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ClearHttpRequestLogsRequest) Reset() {
*x = ClearHttpRequestLogsRequest{}
mi := &file_reqlog_reqlog_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ClearHttpRequestLogsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ClearHttpRequestLogsRequest) ProtoMessage() {}
func (x *ClearHttpRequestLogsRequest) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ClearHttpRequestLogsRequest.ProtoReflect.Descriptor instead.
func (*ClearHttpRequestLogsRequest) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{6}
}
type ClearHttpRequestLogsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ClearHttpRequestLogsResponse) Reset() {
*x = ClearHttpRequestLogsResponse{}
mi := &file_reqlog_reqlog_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ClearHttpRequestLogsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ClearHttpRequestLogsResponse) ProtoMessage() {}
func (x *ClearHttpRequestLogsResponse) ProtoReflect() protoreflect.Message {
mi := &file_reqlog_reqlog_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ClearHttpRequestLogsResponse.ProtoReflect.Descriptor instead.
func (*ClearHttpRequestLogsResponse) Descriptor() ([]byte, []int) {
return file_reqlog_reqlog_proto_rawDescGZIP(), []int{7}
}
var File_reqlog_reqlog_proto protoreflect.FileDescriptor
var file_reqlog_reqlog_proto_rawDesc = []byte{
0x0a, 0x13, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2f, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e, 0x72, 0x65, 0x71,
0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x1a, 0x0f, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x68, 0x74, 0x74,
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x01, 0x0a, 0x0e, 0x48, 0x74, 0x74, 0x70,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72,
0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x6d,
0x6f, 0x74, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65,
0x6d, 0x6f, 0x74, 0x65, 0x49, 0x70, 0x12, 0x30, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e,
0x68, 0x74, 0x74, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x65, 0x74,
0x74, 0x79, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a,
0x18, 0x47, 0x65, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c,
0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x66, 0x0a, 0x19, 0x47, 0x65, 0x74,
0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x10, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1f, 0x2e, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2e,
0x76, 0x31, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f,
0x67, 0x52, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f,
0x67, 0x22, 0x1c, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
0x6a, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b,
0x0a, 0x11, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6c,
0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x65, 0x74, 0x74,
0x79, 0x2e, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x74, 0x74, 0x70,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x52, 0x0f, 0x68, 0x74, 0x74, 0x70,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x58, 0x0a, 0x11, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72,
0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x63, 0x6f, 0x70,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6f, 0x6e, 0x6c, 0x79, 0x49, 0x6e, 0x53,
0x63, 0x6f, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x65,
0x78, 0x70, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63,
0x68, 0x45, 0x78, 0x70, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, 0x74,
0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x22, 0x1e, 0x0a, 0x1c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, 0x74, 0x74,
0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x32, 0xf0, 0x02, 0x0a, 0x15, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6c,
0x0a, 0x11, 0x47, 0x65, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x4c, 0x6f, 0x67, 0x12, 0x29, 0x2e, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e, 0x72, 0x65, 0x71, 0x6c,
0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
0x2e, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31,
0x2e, 0x47, 0x65, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c,
0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13,
0x4c, 0x69, 0x73, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c,
0x6f, 0x67, 0x73, 0x12, 0x2b, 0x2e, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e, 0x72, 0x65, 0x71, 0x6c,
0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x2c, 0x2e, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2e,
0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
0x12, 0x75, 0x0a, 0x14, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x2c, 0x2e, 0x68, 0x65, 0x74, 0x74, 0x79,
0x2e, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x72,
0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x65, 0x74, 0x74, 0x79, 0x2e, 0x72,
0x65, 0x71, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x48, 0x74,
0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x73, 0x74, 0x6f, 0x74, 0x69, 0x6a, 0x6e, 0x2f, 0x68,
0x65, 0x74, 0x74, 0x79, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x72, 0x65, 0x71, 0x6c, 0x6f, 0x67, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_reqlog_reqlog_proto_rawDescOnce sync.Once
file_reqlog_reqlog_proto_rawDescData = file_reqlog_reqlog_proto_rawDesc
)
func file_reqlog_reqlog_proto_rawDescGZIP() []byte {
file_reqlog_reqlog_proto_rawDescOnce.Do(func() {
file_reqlog_reqlog_proto_rawDescData = protoimpl.X.CompressGZIP(file_reqlog_reqlog_proto_rawDescData)
})
return file_reqlog_reqlog_proto_rawDescData
}
var file_reqlog_reqlog_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_reqlog_reqlog_proto_goTypes = []any{
(*HttpRequestLog)(nil), // 0: hetty.reqlog.v1.HttpRequestLog
(*GetHttpRequestLogRequest)(nil), // 1: hetty.reqlog.v1.GetHttpRequestLogRequest
(*GetHttpRequestLogResponse)(nil), // 2: hetty.reqlog.v1.GetHttpRequestLogResponse
(*ListHttpRequestLogsRequest)(nil), // 3: hetty.reqlog.v1.ListHttpRequestLogsRequest
(*ListHttpRequestLogsResponse)(nil), // 4: hetty.reqlog.v1.ListHttpRequestLogsResponse
(*RequestLogsFilter)(nil), // 5: hetty.reqlog.v1.RequestLogsFilter
(*ClearHttpRequestLogsRequest)(nil), // 6: hetty.reqlog.v1.ClearHttpRequestLogsRequest
(*ClearHttpRequestLogsResponse)(nil), // 7: hetty.reqlog.v1.ClearHttpRequestLogsResponse
(*http.Request)(nil), // 8: hetty.http.v1.Request
(*http.Response)(nil), // 9: hetty.http.v1.Response
}
var file_reqlog_reqlog_proto_depIdxs = []int32{
8, // 0: hetty.reqlog.v1.HttpRequestLog.request:type_name -> hetty.http.v1.Request
9, // 1: hetty.reqlog.v1.HttpRequestLog.response:type_name -> hetty.http.v1.Response
0, // 2: hetty.reqlog.v1.GetHttpRequestLogResponse.http_request_log:type_name -> hetty.reqlog.v1.HttpRequestLog
0, // 3: hetty.reqlog.v1.ListHttpRequestLogsResponse.http_request_logs:type_name -> hetty.reqlog.v1.HttpRequestLog
1, // 4: hetty.reqlog.v1.HttpRequestLogService.GetHttpRequestLog:input_type -> hetty.reqlog.v1.GetHttpRequestLogRequest
3, // 5: hetty.reqlog.v1.HttpRequestLogService.ListHttpRequestLogs:input_type -> hetty.reqlog.v1.ListHttpRequestLogsRequest
6, // 6: hetty.reqlog.v1.HttpRequestLogService.ClearHttpRequestLogs:input_type -> hetty.reqlog.v1.ClearHttpRequestLogsRequest
2, // 7: hetty.reqlog.v1.HttpRequestLogService.GetHttpRequestLog:output_type -> hetty.reqlog.v1.GetHttpRequestLogResponse
4, // 8: hetty.reqlog.v1.HttpRequestLogService.ListHttpRequestLogs:output_type -> hetty.reqlog.v1.ListHttpRequestLogsResponse
7, // 9: hetty.reqlog.v1.HttpRequestLogService.ClearHttpRequestLogs:output_type -> hetty.reqlog.v1.ClearHttpRequestLogsResponse
7, // [7:10] is the sub-list for method output_type
4, // [4:7] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_reqlog_reqlog_proto_init() }
func file_reqlog_reqlog_proto_init() {
if File_reqlog_reqlog_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_reqlog_reqlog_proto_rawDesc,
NumEnums: 0,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_reqlog_reqlog_proto_goTypes,
DependencyIndexes: file_reqlog_reqlog_proto_depIdxs,
MessageInfos: file_reqlog_reqlog_proto_msgTypes,
}.Build()
File_reqlog_reqlog_proto = out.File
file_reqlog_reqlog_proto_rawDesc = nil
file_reqlog_reqlog_proto_goTypes = nil
file_reqlog_reqlog_proto_depIdxs = nil
}

View File

@ -3,27 +3,24 @@ package reqlog_test
import (
"context"
"io"
"math/rand"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/oklog/ulid"
"github.com/oklog/ulid/v2"
"go.etcd.io/bbolt"
"github.com/dstotijn/hetty/pkg/db/bolt"
httppb "github.com/dstotijn/hetty/pkg/http"
"github.com/dstotijn/hetty/pkg/proj"
"github.com/dstotijn/hetty/pkg/proxy"
"github.com/dstotijn/hetty/pkg/reqlog"
"github.com/dstotijn/hetty/pkg/scope"
"github.com/dstotijn/hetty/pkg/testutil"
)
//nolint:gosec
var ulidEntropy = rand.New(rand.NewSource(time.Now().UnixNano()))
//nolint:paralleltest
func TestRequestModifier(t *testing.T) {
path := t.TempDir() + "bolt.db"
@ -39,9 +36,9 @@ func TestRequestModifier(t *testing.T) {
}
defer db.Close()
projectID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy)
err = db.UpsertProject(context.Background(), proj.Project{
ID: projectID,
projectID := ulid.Make().String()
err = db.UpsertProject(context.Background(), &proj.Project{
Id: projectID,
})
if err != nil {
t.Fatalf("unexpected error upserting project: %v", err)
@ -58,34 +55,39 @@ func TestRequestModifier(t *testing.T) {
}
reqModFn := svc.RequestModifier(next)
req := httptest.NewRequest("GET", "https://example.com/", strings.NewReader("bar"))
reqID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy)
req.Header.Add("X-Yolo", "swag")
reqID := ulid.Make()
req = req.WithContext(proxy.WithRequestID(req.Context(), reqID))
reqModFn(req)
t.Run("request log was stored in repository", func(t *testing.T) {
exp := reqlog.RequestLog{
ID: reqID,
ProjectID: svc.ActiveProjectID(),
Method: req.Method,
URL: req.URL,
Proto: req.Proto,
Header: req.Header,
Body: []byte("modified body"),
exp := &reqlog.HttpRequestLog{
Id: reqID.String(),
ProjectId: svc.ActiveProjectID(),
Request: &httppb.Request{
Url: "https://example.com/",
Method: httppb.Method_METHOD_GET,
Protocol: httppb.Protocol_PROTOCOL_HTTP11,
Headers: []*httppb.Header{
{
Key: "X-Yolo",
Value: "swag",
},
},
Body: []byte("modified body"),
},
}
got, err := svc.FindRequestLogByID(context.Background(), reqID)
got, err := db.FindRequestLogByID(context.Background(), svc.ActiveProjectID(), reqID.String())
if err != nil {
t.Fatalf("failed to find request by id: %v", err)
}
if diff := cmp.Diff(exp, got); diff != "" {
t.Fatalf("request log not equal (-exp, +got):\n%v", diff)
}
testutil.ProtoDiff(t, "request log not equal", exp, got)
})
}
//nolint:paralleltest
func TestResponseModifier(t *testing.T) {
path := t.TempDir() + "bolt.db"
boltDB, err := bbolt.Open(path, 0o600, nil)
@ -100,9 +102,9 @@ func TestResponseModifier(t *testing.T) {
}
defer db.Close()
projectID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy)
err = db.UpsertProject(context.Background(), proj.Project{
ID: projectID,
projectID := "foobar-project-id"
err = db.UpsertProject(context.Background(), &proj.Project{
Id: projectID,
})
if err != nil {
t.Fatalf("unexpected error upserting project: %v", err)
@ -120,39 +122,44 @@ func TestResponseModifier(t *testing.T) {
resModFn := svc.ResponseModifier(next)
req := httptest.NewRequest("GET", "https://example.com/", strings.NewReader("bar"))
reqLogID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy)
reqLogID := ulid.Make()
req = req.WithContext(context.WithValue(req.Context(), reqlog.ReqLogIDKey, reqLogID))
err = db.StoreRequestLog(context.Background(), reqlog.RequestLog{
ID: reqLogID,
ProjectID: projectID,
err = db.StoreRequestLog(context.Background(), &reqlog.HttpRequestLog{
Id: reqLogID.String(),
ProjectId: projectID,
})
if err != nil {
t.Fatalf("failed to store request log: %v", err)
}
res := &http.Response{
Request: req,
Body: io.NopCloser(strings.NewReader("bar")),
Request: req,
Proto: "HTTP/1.1",
Status: "200 OK",
StatusCode: 200,
Body: io.NopCloser(strings.NewReader("bar")),
}
if err := resModFn(res); err != nil {
t.Fatalf("unexpected error (expected: nil, got: %v)", err)
}
t.Run("request log was stored in repository", func(t *testing.T) {
// Dirty (but simple) wait for other goroutine to finish calling repository.
time.Sleep(10 * time.Millisecond)
// Dirty (but simple) wait for other goroutine to finish calling repository.
time.Sleep(10 * time.Millisecond)
got, err := svc.FindRequestLogByID(context.Background(), reqLogID)
if err != nil {
t.Fatalf("failed to find request by id: %v", err)
}
got, err := db.FindRequestLogByID(context.Background(), svc.ActiveProjectID(), reqLogID.String())
if err != nil {
t.Fatalf("failed to find request by id: %v", err)
}
t.Run("ran next modifier first, before calling repository", func(t *testing.T) {
if exp := "modified body"; exp != string(got.Response.Body) {
t.Fatalf("incorrect `ResponseLog.Body` value (expected: %v, got: %v)", exp, string(got.Response.Body))
}
})
})
exp := &httppb.Response{
Protocol: httppb.Protocol_PROTOCOL_HTTP11,
Status: "200 OK",
StatusCode: 200,
Headers: []*httppb.Header{},
Body: []byte("modified body"),
}
testutil.ProtoDiff(t, "response not equal", exp, got.GetResponse())
}

View File

@ -3,40 +3,34 @@ package reqlog
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/oklog/ulid"
"github.com/oklog/ulid/v2"
"github.com/dstotijn/hetty/pkg/filter"
"github.com/dstotijn/hetty/pkg/http"
"github.com/dstotijn/hetty/pkg/scope"
)
var reqLogSearchKeyFns = map[string]func(rl RequestLog) string{
"req.id": func(rl RequestLog) string { return rl.ID.String() },
"req.proto": func(rl RequestLog) string { return rl.Proto },
"req.url": func(rl RequestLog) string {
if rl.URL == nil {
var reqLogSearchKeyFns = map[string]func(rl *HttpRequestLog) string{
"req.id": func(rl *HttpRequestLog) string { return rl.GetId() },
"req.proto": func(rl *HttpRequestLog) string { return rl.GetRequest().GetProtocol().String() },
"req.url": func(rl *HttpRequestLog) string { return rl.GetRequest().GetUrl() },
"req.method": func(rl *HttpRequestLog) string { return rl.GetRequest().GetMethod().String() },
"req.body": func(rl *HttpRequestLog) string { return string(rl.GetRequest().GetBody()) },
"req.timestamp": func(rl *HttpRequestLog) string {
id, err := ulid.Parse(rl.GetId())
if err != nil {
return ""
}
return rl.URL.String()
return ulid.Time(id.Time()).String()
},
"req.method": func(rl RequestLog) string { return rl.Method },
"req.body": func(rl RequestLog) string { return string(rl.Body) },
"req.timestamp": func(rl RequestLog) string { return ulid.Time(rl.ID.Time()).String() },
}
var ResLogSearchKeyFns = map[string]func(rl ResponseLog) string{
"res.proto": func(rl ResponseLog) string { return rl.Proto },
"res.statusCode": func(rl ResponseLog) string { return strconv.Itoa(rl.StatusCode) },
"res.statusReason": func(rl ResponseLog) string { return rl.Status },
"res.body": func(rl ResponseLog) string { return string(rl.Body) },
}
// TODO: Request and response headers search key functions.
// Matches returns true if the supplied search expression evaluates to true.
func (reqLog RequestLog) Matches(expr filter.Expression) (bool, error) {
func (reqLog *HttpRequestLog) Matches(expr filter.Expression) (bool, error) {
switch e := expr.(type) {
case filter.PrefixExpression:
return reqLog.matchPrefixExpr(e)
@ -49,7 +43,7 @@ func (reqLog RequestLog) Matches(expr filter.Expression) (bool, error) {
}
}
func (reqLog RequestLog) matchPrefixExpr(expr filter.PrefixExpression) (bool, error) {
func (reqLog *HttpRequestLog) matchPrefixExpr(expr filter.PrefixExpression) (bool, error) {
switch expr.Operator {
case filter.TokOpNot:
match, err := reqLog.Matches(expr.Right)
@ -63,7 +57,7 @@ func (reqLog RequestLog) matchPrefixExpr(expr filter.PrefixExpression) (bool, er
}
}
func (reqLog RequestLog) matchInfixExpr(expr filter.InfixExpression) (bool, error) {
func (reqLog *HttpRequestLog) matchInfixExpr(expr filter.InfixExpression) (bool, error) {
switch expr.Operator {
case filter.TokOpAnd:
left, err := reqLog.Matches(expr.Left)
@ -99,7 +93,7 @@ func (reqLog RequestLog) matchInfixExpr(expr filter.InfixExpression) (bool, erro
leftVal := reqLog.getMappedStringLiteral(left.Value)
if leftVal == "req.headers" {
match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Header)
match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Request.Headers)
if err != nil {
return false, fmt.Errorf("failed to match request HTTP headers: %w", err)
}
@ -108,7 +102,7 @@ func (reqLog RequestLog) matchInfixExpr(expr filter.InfixExpression) (bool, erro
}
if leftVal == "res.headers" && reqLog.Response != nil {
match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Response.Header)
match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Response.Headers)
if err != nil {
return false, fmt.Errorf("failed to match response HTTP headers: %w", err)
}
@ -159,7 +153,7 @@ func (reqLog RequestLog) matchInfixExpr(expr filter.InfixExpression) (bool, erro
}
}
func (reqLog RequestLog) getMappedStringLiteral(s string) string {
func (reqLog *HttpRequestLog) getMappedStringLiteral(s string) string {
switch {
case strings.HasPrefix(s, "req."):
fn, ok := reqLogSearchKeyFns[s]
@ -167,28 +161,22 @@ func (reqLog RequestLog) getMappedStringLiteral(s string) string {
return fn(reqLog)
}
case strings.HasPrefix(s, "res."):
if reqLog.Response == nil {
return ""
}
fn, ok := ResLogSearchKeyFns[s]
fn, ok := http.ResponseSearchKeyFns[s]
if ok {
return fn(*reqLog.Response)
return fn(reqLog.GetResponse())
}
}
return s
}
func (reqLog RequestLog) matchStringLiteral(strLiteral filter.StringLiteral) (bool, error) {
for key, values := range reqLog.Header {
for _, value := range values {
if strings.Contains(
strings.ToLower(fmt.Sprintf("%v: %v", key, value)),
strings.ToLower(strLiteral.Value),
) {
return true, nil
}
func (reqLog *HttpRequestLog) matchStringLiteral(strLiteral filter.StringLiteral) (bool, error) {
for _, header := range reqLog.GetRequest().GetHeaders() {
if strings.Contains(
strings.ToLower(fmt.Sprintf("%v: %v", header.Key, header.Value)),
strings.ToLower(strLiteral.Value),
) {
return true, nil
}
}
@ -201,21 +189,19 @@ func (reqLog RequestLog) matchStringLiteral(strLiteral filter.StringLiteral) (bo
}
}
if reqLog.Response != nil {
for key, values := range reqLog.Response.Header {
for _, value := range values {
if strings.Contains(
strings.ToLower(fmt.Sprintf("%v: %v", key, value)),
strings.ToLower(strLiteral.Value),
) {
return true, nil
}
if res := reqLog.GetResponse(); res != nil {
for _, header := range res.Headers {
if strings.Contains(
strings.ToLower(fmt.Sprintf("%v: %v", header.Key, header.Value)),
strings.ToLower(strLiteral.Value),
) {
return true, nil
}
}
for _, fn := range ResLogSearchKeyFns {
for _, fn := range http.ResponseSearchKeyFns {
if strings.Contains(
strings.ToLower(fn(*reqLog.Response)),
strings.ToLower(fn(reqLog.GetResponse())),
strings.ToLower(strLiteral.Value),
) {
return true, nil
@ -226,29 +212,25 @@ func (reqLog RequestLog) matchStringLiteral(strLiteral filter.StringLiteral) (bo
return false, nil
}
func (reqLog RequestLog) MatchScope(s *scope.Scope) bool {
func (reqLog *HttpRequestLog) MatchScope(s *scope.Scope) bool {
for _, rule := range s.Rules() {
if rule.URL != nil && reqLog.URL != nil {
if matches := rule.URL.MatchString(reqLog.URL.String()); matches {
if rule.URL != nil {
if matches := rule.URL.MatchString(reqLog.GetRequest().GetUrl()); matches {
return true
}
}
for key, values := range reqLog.Header {
for _, header := range reqLog.GetRequest().GetHeaders() {
var keyMatches, valueMatches bool
if rule.Header.Key != nil {
if matches := rule.Header.Key.MatchString(key); matches {
keyMatches = true
}
if matches := rule.Header.Key.MatchString(header.Key); matches {
keyMatches = true
}
if rule.Header.Value != nil {
for _, value := range values {
if matches := rule.Header.Value.MatchString(value); matches {
valueMatches = true
break
}
if matches := rule.Header.Value.MatchString(header.Value); matches {
valueMatches = true
break
}
}
// When only key or value is set, match on whatever is set.
@ -264,7 +246,7 @@ func (reqLog RequestLog) MatchScope(s *scope.Scope) bool {
}
if rule.Body != nil {
if matches := rule.Body.Match(reqLog.Body); matches {
if matches := rule.Body.Match(reqLog.GetRequest().GetBody()); matches {
return true
}
}

View File

@ -4,6 +4,7 @@ import (
"testing"
"github.com/dstotijn/hetty/pkg/filter"
"github.com/dstotijn/hetty/pkg/http"
"github.com/dstotijn/hetty/pkg/reqlog"
)
@ -13,15 +14,17 @@ func TestRequestLogMatch(t *testing.T) {
tests := []struct {
name string
query string
requestLog reqlog.RequestLog
requestLog *reqlog.HttpRequestLog
expectedMatch bool
expectedError error
}{
{
name: "infix expression, equal operator, match",
query: "req.body = foo",
requestLog: reqlog.RequestLog{
Body: []byte("foo"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("foo"),
},
},
expectedMatch: true,
expectedError: nil,
@ -29,8 +32,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, not equal operator, match",
query: "req.body != bar",
requestLog: reqlog.RequestLog{
Body: []byte("foo"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("foo"),
},
},
expectedMatch: true,
expectedError: nil,
@ -38,8 +43,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, greater than operator, match",
query: "req.body > a",
requestLog: reqlog.RequestLog{
Body: []byte("b"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("b"),
},
},
expectedMatch: true,
expectedError: nil,
@ -47,8 +54,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, less than operator, match",
query: "req.body < b",
requestLog: reqlog.RequestLog{
Body: []byte("a"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("a"),
},
},
expectedMatch: true,
expectedError: nil,
@ -56,8 +65,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, greater than or equal operator, match greater than",
query: "req.body >= a",
requestLog: reqlog.RequestLog{
Body: []byte("b"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("b"),
},
},
expectedMatch: true,
expectedError: nil,
@ -65,8 +76,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, greater than or equal operator, match equal",
query: "req.body >= a",
requestLog: reqlog.RequestLog{
Body: []byte("a"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("a"),
},
},
expectedMatch: true,
expectedError: nil,
@ -74,8 +87,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, less than or equal operator, match less than",
query: "req.body <= b",
requestLog: reqlog.RequestLog{
Body: []byte("a"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("a"),
},
},
expectedMatch: true,
expectedError: nil,
@ -83,8 +98,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, less than or equal operator, match equal",
query: "req.body <= b",
requestLog: reqlog.RequestLog{
Body: []byte("b"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("b"),
},
},
expectedMatch: true,
expectedError: nil,
@ -92,8 +109,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, regular expression operator, match",
query: `req.body =~ "^foo(.*)$"`,
requestLog: reqlog.RequestLog{
Body: []byte("foobar"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("foobar"),
},
},
expectedMatch: true,
expectedError: nil,
@ -101,8 +120,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, negate regular expression operator, match",
query: `req.body !~ "^foo(.*)$"`,
requestLog: reqlog.RequestLog{
Body: []byte("xoobar"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("xoobar"),
},
},
expectedMatch: true,
expectedError: nil,
@ -110,9 +131,11 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, and operator, match",
query: "req.body = bar AND res.body = yolo",
requestLog: reqlog.RequestLog{
Body: []byte("bar"),
Response: &reqlog.ResponseLog{
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("bar"),
},
Response: &http.Response{
Body: []byte("yolo"),
},
},
@ -122,9 +145,11 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "infix expression, or operator, match",
query: "req.body = bar OR res.body = yolo",
requestLog: reqlog.RequestLog{
Body: []byte("foo"),
Response: &reqlog.ResponseLog{
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("foo"),
},
Response: &http.Response{
Body: []byte("yolo"),
},
},
@ -134,8 +159,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "prefix expression, not operator, match",
query: "NOT (req.body = bar)",
requestLog: reqlog.RequestLog{
Body: []byte("foo"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("foo"),
},
},
expectedMatch: true,
expectedError: nil,
@ -143,8 +170,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "string literal expression, match in request log",
query: "foo",
requestLog: reqlog.RequestLog{
Body: []byte("foo"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("foo"),
},
},
expectedMatch: true,
expectedError: nil,
@ -152,8 +181,10 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "string literal expression, no match",
query: "foo",
requestLog: reqlog.RequestLog{
Body: []byte("bar"),
requestLog: &reqlog.HttpRequestLog{
Request: &http.Request{
Body: []byte("bar"),
},
},
expectedMatch: false,
expectedError: nil,
@ -161,8 +192,8 @@ func TestRequestLogMatch(t *testing.T) {
{
name: "string literal expression, match in response log",
query: "foo",
requestLog: reqlog.RequestLog{
Response: &reqlog.ResponseLog{
requestLog: &reqlog.HttpRequestLog{
Response: &http.Response{
Body: []byte("foo"),
},
},