-
Notifications
You must be signed in to change notification settings - Fork 573
mixer: add header operation templates #612
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
Conversation
Signed-off-by: Kuat Yessenov <[email protected]>
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.
You say this is merging is easy, but what's the ordering semantics if multiple adapters request header mutations?
policy/v1beta1/cfg.proto
Outdated
enum Operation { | ||
REPLACE = 0; // replaces the header with the given name | ||
REMOVE = 1; // removes the header with the given name (the value is ignored) | ||
APPEND = 2; // appends the value to the header value, or sets it if not present |
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.
In this context, I don't quite understand the difference in semantics between REPLACE and APPEND. Can you elaborate? Also, the command says "appeands the value to the header value", and I'm not sure what "appends" means here. String concatenation?
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.
HTTP header pairs can be repeated. For example, the following is correct in the protocol:
x-forwarded-for: 10.0.0.1
x-forwarded-for: 10.0.0.2
...
It is usually up to the client to decide what to do with multiple values for a header. Typically, the values are comma-concatenated, e.g. the client would receive x-forwarded-for: 10.0.0.1, 10.0.0.2
. Append operation corresponds to inserting a new pair into the request headers, without regard whether a value is present or not for the same header.
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.
OK, so then what is the semantic of REPLACE and REMOVE given that there can be multiple headers with the same name? Do they remove all headers with the given name? What if you want to remove only the second instance of a particular named header?
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.
Operations are executed one by one. Semantically, there is just one header with the given name, but it can be represented on the wire as several "key: value" pairs. That means removing is really removing all pairs on the wire, yet appending is fast, since you can just add one more pair.
Removing a second value in a list is simply not supported (not in envoy, nor any other proxy I know of). Usually you want to append a header value, or to replace it entirely. Replacing is more intuitive, so I made it the default.
There are a few examples here: https://github.com/istio/istio/blob/master/mixer/test/client/route_directive/route_directive_test.go#L95
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.
Sorry to keep harping on this...
What you say here makes sense. So in this context, each header is thus a name with an array of values. In that context, I think the value field should be a []string instead of just a single string. Thus:
REMOVE. Remove a header with all its value
REPLACE. Replace a header and all its values with the new array of values
APPEND: Appends an array of values to a header's values.
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.
My intent was to optimize for the common case, which is just a single header key-value pair. If you insist we can change the value to be an array type. I am just worried this might confuse the user, since we would need to explain the semantics of HTTP headers again.
In terms of implementation, the two are interchangeable:
REMOVE_ARRAY(key, _) = REMOVE(key, _)
REPLACE_ARRAY(key, {"value1", "value2"}) = REPLACE(key, "value1, value2")
APPEND_ARRAY(key, {"value1", "value2"}) = APPEND(key, value1); APPEND(key, value2)
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 agree the patterns are isomorphic. I just find it confusing that the model is one header to multiple values, but the API just deals in terms of a single value like that's all there is.
Ultimately, it boils down to the syntax operators will use to manipulate this stuff. Do you have an idea how this would look in config?
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.
Here is an example from the doc:
actions:
- name: authorizer
handler: authorizer
instances: [“cookie”]
requestHeaderOperations:
- name: user-info
value: $authorizer.user
policy/v1beta1/cfg.proto
Outdated
APPEND = 2; // appends the value to the header value, or sets it if not present | ||
} | ||
|
||
// Optional. Header operation 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.
Optional? What's the behavior when not present?
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.
Default value is 0, which is REPLACE
.
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.
Then let's add a comment about the default behavior when not specified
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.
Done
policy/v1beta1/cfg.proto
Outdated
@@ -146,6 +174,9 @@ message Action { | |||
// Referenced instances are evaluated by resolving the attributes/literals for all the fields. | |||
// The constructed objects are then passed to the `handler` referenced within this action. | |||
repeated string instances = 3; | |||
|
|||
// Optional. A handle to refer to the results of the action application. |
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.
Remove "application"
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.
Done
Signed-off-by: Kuat Yessenov <[email protected]>
@geeknoid I think it is reasonable to expect no overlap between header operations for multiple rules for the same header keys. We can under-specify what happens if two rules apply operations on the same key. Mixer runtime may only need to guarantee a deterministic ordering of rule evaluation. |
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
OK, so if you want to add two values, you need to repeat a whole bunch of
stuff. If the value field is an array, it's a trivial thing instead. So to
me, it seems like a win to make the value field an array. Am I missing
something?
…On Thu, Aug 16, 2018 at 3:44 PM Kuat ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In policy/v1beta1/cfg.proto
<#612 (comment)>:
> @@ -124,6 +124,34 @@ message Rule {
// Optional. The actions that will be executed when match evaluates to `true`.
repeated Action actions = 2;
+
+ // A template for an HTTP header manipulation.
+ message HeaderOperationTemplate {
+
+ // Required. Header name.
+ string name = 1;
+
+ // Optional. Header value.
+ string value = 2;
+
+ // Header operation type.
+ enum Operation {
+ REPLACE = 0; // replaces the header with the given name
+ REMOVE = 1; // removes the header with the given name (the value is ignored)
+ APPEND = 2; // appends the value to the header value, or sets it if not present
Here is an example from the doc:
actions:
- name: authorizer
handler: authorizer
instances: [“cookie”]requestHeaderOperations:
- name: user-info
value: $denier.user
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#612 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AVucHaz6SsOAiMfGKQAVuVI1k2Yino7fks5uRfXDgaJpZM4WAN6_>
.
|
Signed-off-by: Kuat Yessenov <[email protected]>
Fair enough. Here is an updated example: actions:
- name: authorizer
handler: authorizer
instances: [“cookie”]
requestHeaderOperations:
- name: user-info
values:
- $authorizer.user |
Thanks. /lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: geeknoid The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This is a minimal addition to expose routing features from Mixer.
I've put the combinatorial expression problem out of scope for now, and only added the header template and action name.
With these two, we have a way to propagate adapter attributes out to the client. Header operations are easy to combine, so that is also orthogonal to the check rule combination discussion.
/assign @geeknoid
/assign @mandarjog
Signed-off-by: Kuat Yessenov [email protected]