12

I need to write a URL Rewrite rule for my IIS 7.5 website that captures a value in a particular cookie, and then uses that value to construct a URL. For instance, the incoming requests looks like this:

GET http://myserver.com/test.aspx HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US
User-Agent: Mozilla/5.0
Host: myserver.com
Cookie: foo=bar; bat=bar

I'd like to route them to this (based on the "foo" cookie value):

http://myserver.com/bar/test.aspx

fter reviewing the documentation and searching for examples, I'm stumped! Thanks for your help.

Geoffrey McGrath
  • 1,663
  • 1
  • 14
  • 35

3 Answers3

16

Answering my own question, here's a working example. The pattern may need additional work depending on what characters require supporting, but the following rule will will use the discovered cookie value and route to the discovered server--and the server can be specified by IPv4 address or by name (alphanumeric-and-period).

<rule name="Route Base On Cookie" stopProcessing="true">
  <match url="^(.*)" />
    <conditions>
       <add input="{HTTP_COOKIE}" pattern="foo=(.*?);" />
    </conditions>
  <action type="Rewrite" url="http://{C:1}/{R:0}" />
</rule>
Geoffrey McGrath
  • 1,663
  • 1
  • 14
  • 35
  • 1
    I recommend `pattern="foo=[^;]*"` to make the pattern match any possible cookie value--your pattern is too restrictive. See [the original spec from Netscape.com](http://curl.haxx.se/rfc/cookie_spec.html) which says "this string is a sequence of characters excluding semi-colon, comma and white space. If there is a need to place such data in the name or value, some encoding method such as URL style %XX encoding is recommended, though no encoding is defined or required." You could take it literally with `pattern="foo=[^;,\s]*"` – ErikE Mar 21 '14 at 23:53
  • @Geoffrey - I am facing issue in similar area - Can you please answer this? - http://stackoverflow.com/questions/34506551/reading-cookie-value-using-url-rewrite-for-iis-wizard-unable-to-validate-at – kudlatiger Dec 30 '15 at 06:35
  • this was slightly annoying my cookie is at the end of the string and not terminated with a semi colon `/en/#accept-en-empty?cookie=ARRAffinity=201b1fd8d701339a2f00e0ee61740aea30fa71e70a108b56894fc119e397c038;%20locale=fr` – Ricardo Saracino May 13 '19 at 12:56
  • It won't work if `foo` is the only cookie or if it comes last in the list of cookies. Because of ";" in the pattern. – Vasiliy Zverev Dec 14 '21 at 22:23
3

@Geoffrey To make your code support returning any cookie value, I'd recommend this pattern:

<add input="{HTTP_COOKIE}" pattern="foo=(.*?);" />

As a reminder, the {HTTP_COOKIE} value looks like this for example:

Cookie: foo=myexamplevalue; expires=Wed, 03-May-2014 22:31:08 GMT; path=/; HttpOnly\r\n

Kevin
  • 603
  • 5
  • 7
  • I originally commented to correct your regex, come to find out, the `?` makes the `*` non-greedy. Well done. Though I prefer negated character classes as they're potentially faster (especially when given the possessive modifier `+`). – ErikE Mar 22 '14 at 00:13
  • `{HTTP_COOKIE}` which comes to a server (not from a server) doesn't have `expires=Wed, 03-May-2014 22:31:08 GMT; path=/; HttpOnly` part. It is like `Cookie: foo=myexamplevalue`. Without ';' at the end. You can peek it in Network tab of DevTools of browser. – Vasiliy Zverev Dec 14 '21 at 22:21
0

The following rule will use the discovered cookie value and route to the discovered path:

<rule name="Route Base On Cookie" stopProcessing="true">
  <match url=".*" />
  <conditions>
     <add input="{HTTP_COOKIE}" pattern="^(.+; )?foo=([^;]*)(;.+)?$" />
  </conditions>
  <action type="Rewrite" url="https://{HTTP_HOST}/{C:2}/{R:0}" />
</rule>

The pattern supports several cookies and doesn't depend on the order of foo in cookie (when it is the last, browser doesn't append ';'):
both foo=bar; bat=bar and bat=bar; foo=bar work fine.
It works correctly when you have another cookie with the same substring such as barfoo.
{C:2} corresponds to the second capture in cookie, i.e. value of foo in pattern="...";
{R:0} corresponds to whole url in <match url="...">. IIS uses path part only without host name, i.e. /test.aspx.

NB. It may be not secure to use value from cookie in path as is. Possibly you should match against the list of expected values (bar|bar2|bar3|bar4).

Vasiliy Zverev
  • 622
  • 5
  • 10