mirror of
https://github.com/dstotijn/hetty.git
synced 2025-07-01 18:47:29 -04:00
Finish first working version of reqlog
This commit is contained in:
@ -42,19 +42,26 @@ type DirectiveRoot struct {
|
||||
}
|
||||
|
||||
type ComplexityRoot struct {
|
||||
Query struct {
|
||||
GetRequests func(childComplexity int) int
|
||||
}
|
||||
|
||||
Request struct {
|
||||
HTTPRequest struct {
|
||||
Body func(childComplexity int) int
|
||||
Method func(childComplexity int) int
|
||||
Response func(childComplexity int) int
|
||||
Timestamp func(childComplexity int) int
|
||||
URL func(childComplexity int) int
|
||||
}
|
||||
|
||||
HTTPResponse struct {
|
||||
Body func(childComplexity int) int
|
||||
StatusCode func(childComplexity int) int
|
||||
}
|
||||
|
||||
Query struct {
|
||||
GetHTTPRequests func(childComplexity int) int
|
||||
}
|
||||
}
|
||||
|
||||
type QueryResolver interface {
|
||||
GetRequests(ctx context.Context) ([]Request, error)
|
||||
GetHTTPRequests(ctx context.Context) ([]HTTPRequest, error)
|
||||
}
|
||||
|
||||
type executableSchema struct {
|
||||
@ -72,33 +79,61 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
_ = ec
|
||||
switch typeName + "." + field {
|
||||
|
||||
case "Query.getRequests":
|
||||
if e.complexity.Query.GetRequests == nil {
|
||||
case "HttpRequest.body":
|
||||
if e.complexity.HTTPRequest.Body == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Query.GetRequests(childComplexity), true
|
||||
return e.complexity.HTTPRequest.Body(childComplexity), true
|
||||
|
||||
case "Request.method":
|
||||
if e.complexity.Request.Method == nil {
|
||||
case "HttpRequest.method":
|
||||
if e.complexity.HTTPRequest.Method == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Request.Method(childComplexity), true
|
||||
return e.complexity.HTTPRequest.Method(childComplexity), true
|
||||
|
||||
case "Request.timestamp":
|
||||
if e.complexity.Request.Timestamp == nil {
|
||||
case "HttpRequest.response":
|
||||
if e.complexity.HTTPRequest.Response == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Request.Timestamp(childComplexity), true
|
||||
return e.complexity.HTTPRequest.Response(childComplexity), true
|
||||
|
||||
case "Request.url":
|
||||
if e.complexity.Request.URL == nil {
|
||||
case "HttpRequest.timestamp":
|
||||
if e.complexity.HTTPRequest.Timestamp == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Request.URL(childComplexity), true
|
||||
return e.complexity.HTTPRequest.Timestamp(childComplexity), true
|
||||
|
||||
case "HttpRequest.url":
|
||||
if e.complexity.HTTPRequest.URL == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HTTPRequest.URL(childComplexity), true
|
||||
|
||||
case "HttpResponse.body":
|
||||
if e.complexity.HTTPResponse.Body == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HTTPResponse.Body(childComplexity), true
|
||||
|
||||
case "HttpResponse.statusCode":
|
||||
if e.complexity.HTTPResponse.StatusCode == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HTTPResponse.StatusCode(childComplexity), true
|
||||
|
||||
case "Query.getHttpRequests":
|
||||
if e.complexity.Query.GetHTTPRequests == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Query.GetHTTPRequests(childComplexity), true
|
||||
|
||||
}
|
||||
return 0, false
|
||||
@ -150,23 +185,37 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er
|
||||
}
|
||||
|
||||
var sources = []*ast.Source{
|
||||
&ast.Source{Name: "pkg/api/schema.graphql", Input: `type Request {
|
||||
&ast.Source{Name: "pkg/api/schema.graphql", Input: `type HttpRequest {
|
||||
url: String!
|
||||
method: HttpMethod!
|
||||
body: String
|
||||
timestamp: Time!
|
||||
response: HttpResponse
|
||||
}
|
||||
|
||||
type HttpResponse {
|
||||
statusCode: Int!
|
||||
body: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
getRequests: [Request!]!
|
||||
getHttpRequests: [HttpRequest!]!
|
||||
}
|
||||
|
||||
enum HttpMethod {
|
||||
GET
|
||||
HEAD
|
||||
POST
|
||||
PUT
|
||||
DELETE
|
||||
CONNECT
|
||||
OPTIONS
|
||||
TRACE
|
||||
PATCH
|
||||
}
|
||||
|
||||
scalar Time`, BuiltIn: false},
|
||||
scalar Time
|
||||
`, BuiltIn: false},
|
||||
}
|
||||
var parsedSchema = gqlparser.MustLoadSchema(sources...)
|
||||
|
||||
@ -224,7 +273,236 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg
|
||||
|
||||
// region **************************** field.gotpl *****************************
|
||||
|
||||
func (ec *executionContext) _Query_getRequests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _HttpRequest_url(ctx context.Context, field graphql.CollectedField, obj *HTTPRequest) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "HttpRequest",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.URL, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HttpRequest_method(ctx context.Context, field graphql.CollectedField, obj *HTTPRequest) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "HttpRequest",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Method, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(HTTPMethod)
|
||||
fc.Result = res
|
||||
return ec.marshalNHttpMethod2githubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPMethod(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HttpRequest_body(ctx context.Context, field graphql.CollectedField, obj *HTTPRequest) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "HttpRequest",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Body, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HttpRequest_timestamp(ctx context.Context, field graphql.CollectedField, obj *HTTPRequest) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "HttpRequest",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Timestamp, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(time.Time)
|
||||
fc.Result = res
|
||||
return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HttpRequest_response(ctx context.Context, field graphql.CollectedField, obj *HTTPRequest) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "HttpRequest",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Response, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*HTTPResponse)
|
||||
fc.Result = res
|
||||
return ec.marshalOHttpResponse2ᚖgithubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPResponse(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HttpResponse_statusCode(ctx context.Context, field graphql.CollectedField, obj *HTTPResponse) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "HttpResponse",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.StatusCode, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(int)
|
||||
fc.Result = res
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HttpResponse_body(ctx context.Context, field graphql.CollectedField, obj *HTTPResponse) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "HttpResponse",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Body, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_getHttpRequests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
@ -241,7 +519,7 @@ func (ec *executionContext) _Query_getRequests(ctx context.Context, field graphq
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Query().GetRequests(rctx)
|
||||
return ec.resolvers.Query().GetHTTPRequests(rctx)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@ -253,9 +531,9 @@ func (ec *executionContext) _Query_getRequests(ctx context.Context, field graphq
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]Request)
|
||||
res := resTmp.([]HTTPRequest)
|
||||
fc.Result = res
|
||||
return ec.marshalNRequest2ᚕgithubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐRequestᚄ(ctx, field.Selections, res)
|
||||
return ec.marshalNHttpRequest2ᚕgithubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPRequestᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
@ -327,108 +605,6 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C
|
||||
return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Request_url(ctx context.Context, field graphql.CollectedField, obj *Request) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Request",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.URL, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Request_method(ctx context.Context, field graphql.CollectedField, obj *Request) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Request",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Method, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(HTTPMethod)
|
||||
fc.Result = res
|
||||
return ec.marshalNHttpMethod2githubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPMethod(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Request_timestamp(ctx context.Context, field graphql.CollectedField, obj *Request) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Request",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Timestamp, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(time.Time)
|
||||
fc.Result = res
|
||||
return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -1492,6 +1668,76 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co
|
||||
|
||||
// region **************************** object.gotpl ****************************
|
||||
|
||||
var httpRequestImplementors = []string{"HttpRequest"}
|
||||
|
||||
func (ec *executionContext) _HttpRequest(ctx context.Context, sel ast.SelectionSet, obj *HTTPRequest) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, httpRequestImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("HttpRequest")
|
||||
case "url":
|
||||
out.Values[i] = ec._HttpRequest_url(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "method":
|
||||
out.Values[i] = ec._HttpRequest_method(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "body":
|
||||
out.Values[i] = ec._HttpRequest_body(ctx, field, obj)
|
||||
case "timestamp":
|
||||
out.Values[i] = ec._HttpRequest_timestamp(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "response":
|
||||
out.Values[i] = ec._HttpRequest_response(ctx, field, obj)
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var httpResponseImplementors = []string{"HttpResponse"}
|
||||
|
||||
func (ec *executionContext) _HttpResponse(ctx context.Context, sel ast.SelectionSet, obj *HTTPResponse) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, httpResponseImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("HttpResponse")
|
||||
case "statusCode":
|
||||
out.Values[i] = ec._HttpResponse_statusCode(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "body":
|
||||
out.Values[i] = ec._HttpResponse_body(ctx, field, obj)
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var queryImplementors = []string{"Query"}
|
||||
|
||||
func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {
|
||||
@ -1507,7 +1753,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("Query")
|
||||
case "getRequests":
|
||||
case "getHttpRequests":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
@ -1515,7 +1761,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_getRequests(ctx, field)
|
||||
res = ec._Query_getHttpRequests(ctx, field)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
@ -1536,43 +1782,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
return out
|
||||
}
|
||||
|
||||
var requestImplementors = []string{"Request"}
|
||||
|
||||
func (ec *executionContext) _Request(ctx context.Context, sel ast.SelectionSet, obj *Request) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, requestImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("Request")
|
||||
case "url":
|
||||
out.Values[i] = ec._Request_url(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "method":
|
||||
out.Values[i] = ec._Request_method(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "timestamp":
|
||||
out.Values[i] = ec._Request_timestamp(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var __DirectiveImplementors = []string{"__Directive"}
|
||||
|
||||
func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler {
|
||||
@ -1841,11 +2050,11 @@ func (ec *executionContext) marshalNHttpMethod2githubᚗcomᚋdstotijnᚋgurpᚋ
|
||||
return v
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNRequest2githubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐRequest(ctx context.Context, sel ast.SelectionSet, v Request) graphql.Marshaler {
|
||||
return ec._Request(ctx, sel, &v)
|
||||
func (ec *executionContext) marshalNHttpRequest2githubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPRequest(ctx context.Context, sel ast.SelectionSet, v HTTPRequest) graphql.Marshaler {
|
||||
return ec._HttpRequest(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNRequest2ᚕgithubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []Request) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalNHttpRequest2ᚕgithubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []HTTPRequest) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
@ -1869,7 +2078,7 @@ func (ec *executionContext) marshalNRequest2ᚕgithubᚗcomᚋdstotijnᚋgurpᚋ
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.marshalNRequest2githubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐRequest(ctx, sel, v[i])
|
||||
ret[i] = ec.marshalNHttpRequest2githubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPRequest(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
@ -1882,6 +2091,20 @@ func (ec *executionContext) marshalNRequest2ᚕgithubᚗcomᚋdstotijnᚋgurpᚋ
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {
|
||||
return graphql.UnmarshalInt(v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {
|
||||
res := graphql.MarshalInt(v)
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {
|
||||
return graphql.UnmarshalString(v)
|
||||
}
|
||||
@ -2159,6 +2382,17 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast
|
||||
return ec.marshalOBoolean2bool(ctx, sel, *v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOHttpResponse2githubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPResponse(ctx context.Context, sel ast.SelectionSet, v HTTPResponse) graphql.Marshaler {
|
||||
return ec._HttpResponse(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOHttpResponse2ᚖgithubᚗcomᚋdstotijnᚋgurpᚋpkgᚋapiᚐHTTPResponse(ctx context.Context, sel ast.SelectionSet, v *HTTPResponse) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._HttpResponse(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) {
|
||||
return graphql.UnmarshalString(v)
|
||||
}
|
||||
|
@ -9,27 +9,48 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
URL string `json:"url"`
|
||||
Method HTTPMethod `json:"method"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
type HTTPRequest struct {
|
||||
URL string `json:"url"`
|
||||
Method HTTPMethod `json:"method"`
|
||||
Body *string `json:"body"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Response *HTTPResponse `json:"response"`
|
||||
}
|
||||
|
||||
type HTTPResponse struct {
|
||||
StatusCode int `json:"statusCode"`
|
||||
Body *string `json:"body"`
|
||||
}
|
||||
|
||||
type HTTPMethod string
|
||||
|
||||
const (
|
||||
HTTPMethodGet HTTPMethod = "GET"
|
||||
HTTPMethodPost HTTPMethod = "POST"
|
||||
HTTPMethodGet HTTPMethod = "GET"
|
||||
HTTPMethodHead HTTPMethod = "HEAD"
|
||||
HTTPMethodPost HTTPMethod = "POST"
|
||||
HTTPMethodPut HTTPMethod = "PUT"
|
||||
HTTPMethodDelete HTTPMethod = "DELETE"
|
||||
HTTPMethodConnect HTTPMethod = "CONNECT"
|
||||
HTTPMethodOptions HTTPMethod = "OPTIONS"
|
||||
HTTPMethodTrace HTTPMethod = "TRACE"
|
||||
HTTPMethodPatch HTTPMethod = "PATCH"
|
||||
)
|
||||
|
||||
var AllHTTPMethod = []HTTPMethod{
|
||||
HTTPMethodGet,
|
||||
HTTPMethodHead,
|
||||
HTTPMethodPost,
|
||||
HTTPMethodPut,
|
||||
HTTPMethodDelete,
|
||||
HTTPMethodConnect,
|
||||
HTTPMethodOptions,
|
||||
HTTPMethodTrace,
|
||||
HTTPMethodPatch,
|
||||
}
|
||||
|
||||
func (e HTTPMethod) IsValid() bool {
|
||||
switch e {
|
||||
case HTTPMethodGet, HTTPMethodPost:
|
||||
case HTTPMethodGet, HTTPMethodHead, HTTPMethodPost, HTTPMethodPut, HTTPMethodDelete, HTTPMethodConnect, HTTPMethodOptions, HTTPMethodTrace, HTTPMethodPatch:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -1,5 +1,7 @@
|
||||
package api
|
||||
|
||||
//go:generate go run github.com/99designs/gqlgen
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
@ -8,27 +10,44 @@ import (
|
||||
)
|
||||
|
||||
type Resolver struct {
|
||||
RequestLogStore *reqlog.RequestLogStore
|
||||
RequestLogService *reqlog.Service
|
||||
}
|
||||
|
||||
type queryResolver struct{ *Resolver }
|
||||
|
||||
func (r *Resolver) Query() QueryResolver { return &queryResolver{r} }
|
||||
|
||||
func (r *queryResolver) GetRequests(ctx context.Context) ([]Request, error) {
|
||||
reqs := r.RequestLogStore.Requests()
|
||||
resp := make([]Request, len(reqs))
|
||||
func (r *queryResolver) GetHTTPRequests(ctx context.Context) ([]HTTPRequest, error) {
|
||||
logs := r.RequestLogService.Requests()
|
||||
reqs := make([]HTTPRequest, len(logs))
|
||||
|
||||
for i := range resp {
|
||||
method := HTTPMethod(reqs[i].Request.Method)
|
||||
for i, log := range logs {
|
||||
method := HTTPMethod(log.Request.Method)
|
||||
if !method.IsValid() {
|
||||
return nil, fmt.Errorf("request has invalid method: %v", method)
|
||||
}
|
||||
resp[i] = Request{
|
||||
URL: reqs[i].Request.URL.String(),
|
||||
Method: method,
|
||||
|
||||
reqs[i] = HTTPRequest{
|
||||
URL: log.Request.URL.String(),
|
||||
Method: method,
|
||||
Timestamp: log.Timestamp,
|
||||
}
|
||||
|
||||
if len(log.Body) > 0 {
|
||||
reqBody := string(log.Body)
|
||||
reqs[i].Body = &reqBody
|
||||
}
|
||||
|
||||
if log.Response != nil {
|
||||
reqs[i].Response = &HTTPResponse{
|
||||
StatusCode: log.Response.Response.StatusCode,
|
||||
}
|
||||
if len(log.Response.Body) > 0 {
|
||||
resBody := string(log.Response.Body)
|
||||
reqs[i].Response.Body = &resBody
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return reqs, nil
|
||||
}
|
||||
|
@ -1,17 +1,30 @@
|
||||
type Request {
|
||||
type HttpRequest {
|
||||
url: String!
|
||||
method: HttpMethod!
|
||||
body: String
|
||||
timestamp: Time!
|
||||
response: HttpResponse
|
||||
}
|
||||
|
||||
type HttpResponse {
|
||||
statusCode: Int!
|
||||
body: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
getRequests: [Request!]!
|
||||
getHttpRequests: [HttpRequest!]!
|
||||
}
|
||||
|
||||
enum HttpMethod {
|
||||
GET
|
||||
HEAD
|
||||
POST
|
||||
PUT
|
||||
DELETE
|
||||
CONNECT
|
||||
OPTIONS
|
||||
TRACE
|
||||
PATCH
|
||||
}
|
||||
|
||||
scalar Time
|
||||
scalar Time
|
||||
|
@ -10,8 +10,14 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type contextKey int
|
||||
|
||||
const ReqIDKey contextKey = 0
|
||||
|
||||
// Proxy implements http.Handler and offers MITM behaviour for modifying
|
||||
// HTTP requests and responses.
|
||||
type Proxy struct {
|
||||
@ -46,6 +52,11 @@ func NewProxy(ca *x509.Certificate, key crypto.PrivateKey) (*Proxy, error) {
|
||||
}
|
||||
|
||||
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Add a unique request ID, to be used for correlating responses to requests.
|
||||
reqID := uuid.New()
|
||||
ctx := context.WithValue(r.Context(), ReqIDKey, reqID)
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
if r.Method == http.MethodConnect {
|
||||
p.handleConnect(w, r)
|
||||
return
|
||||
@ -69,6 +80,10 @@ func (p *Proxy) modifyRequest(r *http.Request) {
|
||||
r.URL.Scheme = "https"
|
||||
}
|
||||
|
||||
// Setting `X-Forwarded-For` to `nil` ensures that http.ReverseProxy doesn't
|
||||
// set this header.
|
||||
r.Header["X-Forwarded-For"] = nil
|
||||
|
||||
fn := nopReqModifier
|
||||
|
||||
for i := len(p.reqModifiers) - 1; i >= 0; i-- {
|
||||
@ -119,7 +134,7 @@ func (p *Proxy) handleConnect(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
l := &OnceAcceptListener{clientConnNotify.Conn}
|
||||
|
||||
err = http.Serve(l, p.handler)
|
||||
err = http.Serve(l, p)
|
||||
if err != nil && err != ErrAlreadyAccepted {
|
||||
log.Printf("[ERROR] Serving HTTP request failed: %v", err)
|
||||
}
|
||||
|
@ -1,51 +1,150 @@
|
||||
package reqlog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/dstotijn/gurp/pkg/proxy"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
Request http.Request
|
||||
Body []byte
|
||||
ID uuid.UUID
|
||||
Request http.Request
|
||||
Body []byte
|
||||
Timestamp time.Time
|
||||
Response *Response
|
||||
}
|
||||
|
||||
type response struct {
|
||||
res http.Response
|
||||
body []byte
|
||||
type Response struct {
|
||||
Response http.Response
|
||||
Body []byte
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
type RequestLogStore struct {
|
||||
reqStore []Request
|
||||
resStore []response
|
||||
reqMu sync.Mutex
|
||||
resMu sync.Mutex
|
||||
type Service struct {
|
||||
store []Request
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewRequestLogStore() RequestLogStore {
|
||||
return RequestLogStore{
|
||||
reqStore: make([]Request, 0),
|
||||
resStore: make([]response, 0),
|
||||
func NewService() Service {
|
||||
return Service{
|
||||
store: make([]Request, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (store *RequestLogStore) AddRequest(req http.Request, body []byte) {
|
||||
store.reqMu.Lock()
|
||||
defer store.reqMu.Unlock()
|
||||
func (svc *Service) Requests() []Request {
|
||||
// TODO(?): Is locking necessary here?
|
||||
svc.mu.Lock()
|
||||
defer svc.mu.Unlock()
|
||||
|
||||
store.reqStore = append(store.reqStore, Request{req, body})
|
||||
return svc.store
|
||||
}
|
||||
|
||||
func (store *RequestLogStore) Requests() []Request {
|
||||
store.reqMu.Lock()
|
||||
defer store.reqMu.Unlock()
|
||||
func (svc *Service) addRequest(reqID uuid.UUID, req http.Request, body []byte) Request {
|
||||
svc.mu.Lock()
|
||||
defer svc.mu.Unlock()
|
||||
|
||||
return store.reqStore
|
||||
reqLog := Request{
|
||||
ID: reqID,
|
||||
Request: req,
|
||||
Body: body,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
svc.store = append(svc.store, reqLog)
|
||||
|
||||
return reqLog
|
||||
}
|
||||
|
||||
func (store *RequestLogStore) AddResponse(res http.Response, body []byte) {
|
||||
store.resMu.Lock()
|
||||
defer store.resMu.Unlock()
|
||||
func (svc *Service) addResponse(reqID uuid.UUID, res http.Response, body []byte) error {
|
||||
svc.mu.Lock()
|
||||
defer svc.mu.Unlock()
|
||||
|
||||
store.resStore = append(store.resStore, response{res, body})
|
||||
for i := range svc.store {
|
||||
if svc.store[i].ID == reqID {
|
||||
svc.store[i].Response = &Response{
|
||||
Response: res,
|
||||
Body: body,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("no request found with ID: %s", reqID)
|
||||
}
|
||||
|
||||
func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestModifyFunc {
|
||||
return func(req *http.Request) {
|
||||
next(req)
|
||||
|
||||
clone := req.Clone(req.Context())
|
||||
var body []byte
|
||||
if req.Body != nil {
|
||||
// TODO: Use io.LimitReader.
|
||||
var err error
|
||||
body, err = ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Could not read request body for logging: %v", err)
|
||||
return
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
}
|
||||
|
||||
reqID, _ := req.Context().Value(proxy.ReqIDKey).(uuid.UUID)
|
||||
if reqID == uuid.Nil {
|
||||
log.Println("[ERROR] Request is missing a related request ID")
|
||||
return
|
||||
}
|
||||
|
||||
_ = svc.addRequest(reqID, *clone, body)
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc {
|
||||
return func(res *http.Response) error {
|
||||
if err := next(res); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clone := *res
|
||||
|
||||
// TODO: Use io.LimitReader.
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reqlog: could not read response body: %v", err)
|
||||
}
|
||||
res.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
|
||||
if res.Header.Get("Content-Encoding") == "gzip" {
|
||||
gzipReader, err := gzip.NewReader(bytes.NewBuffer(body))
|
||||
if err != nil {
|
||||
return fmt.Errorf("reqlog: could not create gzip reader: %v", err)
|
||||
}
|
||||
defer gzipReader.Close()
|
||||
body, err = ioutil.ReadAll(gzipReader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reqlog: could not read gzipped response body: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
reqID, _ := res.Request.Context().Value(proxy.ReqIDKey).(uuid.UUID)
|
||||
if reqID == uuid.Nil {
|
||||
return errors.New("reqlog: request is missing ID")
|
||||
}
|
||||
|
||||
if err := svc.addResponse(reqID, clone, body); err != nil {
|
||||
return fmt.Errorf("reqlog: could not add response: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user