Modifying Context in Request/Response Modifier

20 views
Skip to first unread message

Fattah Illahi

unread,
Jul 3, 2024, 4:55:57 AMJul 3
to KrakenD Community
Hi krakend community,

We are using krakend community edition and are interested to upgrade our krakend version to v2.6.3 because of this note on the changelog 

Request and response modifier plugins have now access to the HTTP context. Response modifiers have also access to the internal request, knowing low-level details like which backend was selected.

We also noticed that there is a new method exposed in both request and response wrapper called Context() that returns context in the example repo.

However there's no method to set the context of the input.

Now we are wondering if we can do the following:
- Set new value to the context in the request modifier plugin.
- Read the custom value that we set in the context the previous request modifier in the next request modifier or response modifier.

We are aware that we can't set value directly in the existing context, so here's what we have tried

- Create "DoubleWrapper" interface that extends the RequestWrapper interface
```
type reqDoubleWrapper struct {
reqres.RequestWrapper
context context.Context
}

type DoubleWrapper interface {
reqres.RequestWrapper
Context() context.Context
}

func (dw *reqDoubleWrapper) Context() context.Context {
return dw.context
}

```
- Create new context with value from the existing context and pass it into doubleWrapper object
```
return func(input interface{}) (interface{}, error) {
req, ok := input.(reqres.RequestWrapper)
if !ok {
return nil, unknownTypeErr
}

...
newctx := context.WithValue(req.Context(), "fatt", "lisa")
newInput := &reqDoubleWrapper{req, newctx}
return newInput, nil
// return input, nil
}
```
- Print the entire context in the response modifier plugin
```
return func(input interface{}) (interface{}, error) {
resp, ok := input.(reqres.ResponseWrapper)
if !ok {
return nil, unknownTypeErr
}

...
printContextInternals(resp.Context(), false)
...
return input, nil
}
```

However we did not see the newly set value in the context there
```
Fields for context.valueCtx
field name: cancelCtx
value: {Context:0xc000a92300 mu:{state:0 sema:0} done:{v:0xc0025a2180} children:map[] err:<nil> cause:<nil>}
field name: timer
value: &{C:<nil> r:{pp:824634180872 when:12530039488831 period:0 f:0x11a35a0 arg:0x11b2460 seq:0 nextwhen:0 status:1}}
field name: deadline
value: 2024-07-03 08:14:12.981681554 +0000 UTC m=+193.737829798
field name: key
value: 0
field name: val
value: &{Span:<nil> mu:{state:0 sema:0} parent:{traceID:[43 102 124 68 101 235 47 159 247 245 176 140 190 122 28 165] spanID:[25 137 33 121 184 15 211 129] traceFlags:1 traceState:{list:[]} remote:false} spanKind:1 name:/hello_world/:business_id startTime:{wall:13950286763185707327 ext:133737916754 loc:0x5582220} endTime:{wall:0 ext:0 loc:<nil>} status:{Code:0 Description:} childSpanCount:1 spanContext:{traceID:[43 102 124 68 101 235 47 159 247 245 176 140 190 122 28 165] spanID:[138 23 43 33 76 236 12 44] traceFlags:1 traceState:{list:[]} remote:false} attributes:[{Key:http.request.method Value:{vtype:4 numeric:0 stringly:POST slice:<nil>}} {Key:http.route Value:{vtype:4 numeric:0 stringly:/hello_world/:business_id slice:<nil>}} {Key:krakend.stage Value:{vtype:4 numeric:0 stringly:proxy slice:<nil>}}] droppedAttributes:0 events:{queue:[] capacity:128 droppedCount:0} links:{queue:[] capacity:128 droppedCount:0} executionTracerTaskEnd:<nil> tracer:0xc00016b680}
data: map[]
is complete: true
headers: map[Connection:[keep-alive] Content-Length:[1913] Content-Type:[application/json; charset=utf-8] Date:[Wed, 03 Jul 2024 08:13:14 GMT] Etag:[W/"779-i16KTTmbjtlOyce6mv9Ybw4dR/E"] Server:[nginx/1.22.0] X-Powered-By:[Express]]
```

Is this something that is possible to do using this new release of krakend-ce?
Could you help?


Regard,

Fattah

David Hontecillas

unread,
Jul 4, 2024, 4:03:03 AMJul 4
to KrakenD Community, fat...@xendit.co
Hi, 

With the current implementation is not possible to achieve what you want. Mostly because even the `interface{}` you return, is a "DoubleWrapper" , KrakenD will cast the returned value to a RequestWrapper: at that point, is already referencing the internal structure, and your created context is gone.

What you can do is try to add your custom values to the headers, and access that . 
Reply all
Reply to author
Forward
0 new messages