-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-introduce GetResponseHTTPHeaders method #667
Re-introduce GetResponseHTTPHeaders method #667
Conversation
Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
envoyauth/response.go
Outdated
|
||
takeResponseHeaders := func(headers map[string]interface{}) error { | ||
for key, value := range headers { | ||
switch values := value.(type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a structural duplicate to the transformation for the envoy HttpOption. Do you want to unify this more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes indeed. Addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant is that this switch statement in the for loop is essentially the same as in makeEnvoyHeaderValueOptionsFromHeadersMap
so you could model this with a transformer + collector function and then the same for loop and structural swich could be used...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for clarifying. I hope it is there now.
… methods Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
9ef00b5
to
9951c4e
Compare
Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
9951c4e
to
af9dbb4
Compare
case []string: | ||
hvo = slices.Grow(hvo, len(val)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing this might yield a small performance hit as the array will need to grow for each sub-element in the Envoy case.
uses a pre allocation function to reduce the performance overhead when it's done along with append. Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
envoyauth/response.go
Outdated
if *result == nil { | ||
*result = make(http.Header) | ||
*result = make(http.Header, additional) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this grows the map itself and not the values for a specific key.
Maybe that is also not easily possiblr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's true. Will ignore the additional value, but keep for the function signature to match.
Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
envoyauth/response_test.go
Outdated
@@ -455,6 +455,127 @@ func TestGetResponseHeaders(t *testing.T) { | |||
if len(result) != 2 { | |||
t.Fatalf("Expected two header but got %v", len(result)) | |||
} | |||
// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commented code to be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mistake, will uncomment it. Introduced it to valid the case of []interface{}
for header values.
LGTM in general! |
|
||
switch v := val.(type) { | ||
case map[string]interface{}: | ||
return []map[string]interface{}{v}, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, avoid additional allocations. We have a highload service based on OPA where each allocation drastically impacts the performance.
return getHeadersWithTransformation(result.Decision, fieldName, preallocateForHTTPHeaders, collectHTTPHeaders) | ||
} | ||
|
||
func getHeadersWithTransformation[T any]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO, a new approach looks a bit complicated and not easy to follow the logic.
Could you make just a function which converts the result from getHeadersFromDecision
into http.Header
?
func getHeadersWithTransformation[T any]( | |
func (result *EvalResult) getHTTPHeadersFromDecision(fieldName string) (http.Header, error) { | |
opts, err := result.getHeadersFromDecision(fieldName) | |
if err != nil { | |
return nil, err | |
} | |
header := make(http.Header, len(opts)) | |
for _, opt = range opts { | |
header.Add(opt.GetHeader().GetKey(), opt.GetHeader().GetValue()) | |
} | |
return header, nil | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's is an effort to balance complexity and performance for both cases of returning HeaderValueOption
and http.Header
.
This suggested approach introduces an unnecessary intermediate conversion to ext_core_v3.HeaderValueOption
for http.Header returning case affecting performance in that scenario.
This concern directs us towards the implemented approach which keep both the cases optimized for highload services.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you introduce the benchmark of getHeadersFromDecision
before and after your refactoring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, you already made an intermediate conversion using extractHeadersFromDecision
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@regeda I respect your requirements, but it's probably better to follow up with PRs of your own to improve performance where needed rather than making requests for that in others contributions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm kind of responsible for this breaking change.
I would help to set it back. PTAL #668
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair! Let's have this merged and follow up with additions based off of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you're interested in reducing allocations, you'll find a lot to like in OPA v1.2.0 🙂
Signed-off-by: Pushpalanka Jayawardhana <[email protected]>
return getHeadersWithTransformation(result.Decision, fieldName, preallocateForHTTPHeaders, collectHTTPHeaders) | ||
} | ||
|
||
func getHeadersWithTransformation[T any]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, you already made an intermediate conversion using extractHeadersFromDecision
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! LGTM 🎈
@@ -4,9 +4,6 @@ import ( | |||
"context" | |||
"encoding/json" | |||
"fmt" | |||
"net/http" | |||
"slices" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kind of appreciated the blocks here -- stdlib vs third-party. but that's not a blocker.
Context:
Re-introduce the removed method from #628 using separate transform functions following this comment from @mjungsbluth.
Both signatures will be available to use as required,