Skip to content
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

Unclear how to use set-header with multiple headers #115946

Closed
nathankitchen opened this issue Oct 13, 2023 · 2 comments
Closed

Unclear how to use set-header with multiple headers #115946

nathankitchen opened this issue Oct 13, 2023 · 2 comments

Comments

@nathankitchen
Copy link

A key use case for set-header is rewriting cookies. In many applications there is more than one cookie being set, so this would involve multiple "Set-Cookie" headers. Here, I attempt to simply replay the outbound cookies in a new header:

<set-header name="Test-Cookie" exists-action="override">
   <value>@{
      return context.Response.Headers.GetValueOrDefault("Set-Cookie", "");
   }</value>
</set-header>

This results in a single header being output, with comma-separated cookies. This approach isn't helpful because cookies set with an expiry date have a comma in the date portion, as noted by these docs. However this statement:

In case of those exceptions, multiple header values will not be concatenated into one string and will be passed as separate headers, for example...

Doesn't appear to be true because the above example XML policy snippet results in all "Set-Cookie" headers being string joined into a comma-separated string, even though some of those cookies contain dates with commas in them. This is a nightmare for parsing.

Finally, simply setting the header value as above doesn't replicate the Set-Cookie behaviour in the Test-Cookie header: instead of multiple instances of "Test-Cookie" header, we have a single instance with all the cookies concatenated together. It's none-obvious that returning a header value would not result in the same header structure.

There's an implication in the docs that:

Exceptions include standardized headers whose values ... may contain date (Cookie, Set-Cookie, Warning)

But it's not clear what the nature of that exception is. Should I not use GetValueOrDefault with Set-Cookie?

Finally, the following guidance could do with an example for how you set these from an expression:

<!-- Copy this snippet into the inbound element to forward some context information, user id and the region the gateway is hosted in, to the backend service for logging or evaluation -->
<set-header name="x-request-context-data" exists-action="override">
  <value>@(context.User.Id)</value>
  <value>@(context.Deployment.Region)</value>
</set-header>

It doesn't appear that you can return a string array from an expression here. Would a yield return work? Remove the "value" field and put the expression returning an array there? To be clear, what I'd like to achieve is:

<!--Fix any cookies by rewriting their path -->
<set-header name="Test-Cookie" exists-action="override">
   <value>@{
      var headerValue = context.Response.Headers.GetValueOrDefault("Set-Cookie", "");
      var inputCookies = headerValue.Split(',');
      var outputCookies = new List<string>();
      foreach (var inputCookie in inputCookies) {
         outputCookies.Add(inputCookie.Replace("path=/;", "path=/api;"));
      }
      return outputCookies;
   }</value>
</set-header>

This fails validation because outputCookies is of the wrong type, and also wouldn't work because the string.Split would break over a cookie's expiry date, but it gives an idea of what I'm trying to accomplish. I also don't think this is a crazy outlandish scenario.

Please could the docs be updated to make it clearer how to deal with multi-instance headers?


Document Details

Do not edit this section. It is required for learn.microsoft.com ➟ GitHub issue linking.

@AjayBathini-MSFT
Copy link
Contributor

@nathankitchen
Thanks for your feedback! We will investigate and update as appropriate.

@mumurug-MSFT mumurug-MSFT added escalated-product-team used when escalating an issue to product team awaiting-product-team-response labels Oct 16, 2023
@mumurug-MSFT
Copy link
Contributor

@nathankitchen Thanks again for sharing your feedback here. I provided an answer and code snippet regarding your questions in https://learn.microsoft.com/en-us/answers/questions/1390333/how-to-use-apim-set-header-policy-to-manage-set-co thread.

To summarize,

  1. GetValueOrDefault returns comma-separated response header values as described in the doc.
  2. Exceptions include standardized headers whose values ... may contain date (Cookie, Set-Cookie, Warning) works as expected and shared the output in the thread. Need to make sure the backend API returns as multiple header values instead of comma separated values.
  3. Set Header doc covers more about the policy, attributes and usage etc. We try to cover use cases, scenario-based policy snippets in https://github.com/Azure/api-management-policy-snippets repo and this will be a good addition there. I see we have an open item regarding this (we can use it for tracking) and will pass the feedback to our product team to add it there.

I hope this helps and if you have any questions, please feel free to reach out or add a comment. Would be happy to answer any. We will proceed to close this thread for now.

@mumurug-MSFT mumurug-MSFT removed awaiting-product-team-response escalated-product-team used when escalating an issue to product team labels Oct 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants