3

I'm working with a client who has a mobile site setup through a third party. Currently, we check through IIS whether a user agent matches any of your standard mobile agents in which case we redirect the user to the mobile version m.whatever.com.

One of the rules we have requires us to set the cookie to a value of 0 when the user wants to see the mobile site again.

<rules>
    <rule name="if httpcookie is , set it to 0" stopProcessing="true">
        <match url="^(.*)$" />
        <conditions>
            <add input="{HTTP_COOKIE}" pattern="mobileoptout=1" />
        </conditions>
        <serverVariables>
            <set name="HTTP_COOKIE" value="mobileoptout=0" />
        </serverVariables>
        <action type="None" />
    </rule>
</rules>

As per the above, we're matching on the URL and the cookie value. I have tested these independently and they work as expected. However, at the end of this rule, the value for the cookie MobileOptOut is still 1 and not 0.

I've searched and tried all the examples available on numerous sites but have been completely unable to understand why the value of the cookie is not being changed.

The domain for the cookie is [whatever.com] which is the same as www.whatever.com and based on previous tests it can read from the cookie to validate a condition.

Any ideas?

Including an additional attempt which does not work either:

<rules>
   <rule name="set cookie">
     <match url="(.*)" />
     <serverVariables>
       <set name="HTTP_COOKIE" value="optout=1" />
       <set name="{HTTP_COOKIE}" value="optout=2" />
     </serverVariables>
     <action type="None" />
   </rule>
</rules>
Nick
  • 103
  • 1
  • 1
  • 12

2 Answers2

3

Thanks to @cheesemacfly I looked into using the outbound rules, which for some reason I completely overlooked.

The solution uses a single inbound rule to check two conditions.

<rule name="MobileOptOut=1 Stop Processing Rules" stopProcessing="true">
  <match url="(.*)" />
  <conditions logicalGrouping="MatchAny" trackAllCaptures="false">
    <add input="{QUERY_STRING}" pattern="mobileoptout=1" />
    <add input="{HTTP_COOKIE}" pattern="MobileOptOut=1" />
  </conditions>
  <action type="None" />
</rule>

This will handle the first request with the querystring and all subsequent requests with the cookie that will be created after this rule finishes.

The outbound rule is as follows:

<outboundRules>
  <rule name="if querystring=1" preCondition="If mobileoptout query = 1">
    <match serverVariable="RESPONSE_Set_Cookie" pattern="." />
    <action type="Rewrite" value="mobileoptout=1; Domain=site.local; Path=/;" />
  </rule>
  <preConditions>
    <preCondition name="If mobileoptout query = 1">
      <add input="{QUERY_STRING}" pattern="mobileoptout=1" />
    </preCondition>
  </preConditions>
</outboundRules>

This will check that first condition of if querystring is mobileoptout=1. If true, it will set a cookie in the response named 'mobileoptout' with a value of 1 in the root domain that will expire with the session.

This is exactly what I was overlooking.

Nick
  • 103
  • 1
  • 1
  • 12
  • If needed, I think you can replace `value="mobileoptout=1; Domain=site.local; Path=/;"` with `value="mobileoptout=1; Domain={HTTP_HOST}; Path=/;"`. But anyway, great answer! :) – cheesemacfly May 31 '13 at 17:43
  • Thanks, can you help here - http://stackoverflow.com/questions/34506551/reading-cookie-value-using-url-rewrite-for-iis-wizard-unable-to-validate-at – kudlatiger Dec 29 '15 at 11:38
1

First, to make sure your rule can work, you have to setup the allowed server variables.

To do so, in the iis manager, under the URL Rewrite section, click on View Server Variables...:

menu

You then can add a new variable by clicking Add... on the right.
In your case, you want to add HTTP_COOKIE:

http_cookie

From here, your rule (as following) should be working:

<rules>
    <rule name="if httpcookie is , set it to 0" stopProcessing="true">
        <match url="^(.*)$" />
        <conditions>
            <add input="{HTTP_COOKIE}" pattern="mobileoptout=1" />
        </conditions>
        <serverVariables>
            <set name="HTTP_COOKIE" value="mobileoptout=0" />
        </serverVariables>
        <action type="None" />
    </rule>
</rules>

Note that the cookie is rewritten only for the request.
Meaning the client cookies won't be changed but the request hitting the page will have the new cookie values when the rule is triggered.

cheesemacfly
  • 11,622
  • 11
  • 53
  • 72
  • Thanks @cheesemacfly! So if I understand this correctly, this doesn't seem to be a viable option to handle mobile optout this way. This was originally setup so that when a user came with a querystring of `mobileoptout=1` IIS would set a client cookie to `mobileoptout=1` which would expire after the session ended. It seems I'll have to remove those rules and handle this programmatically instead. – Nick May 30 '13 at 16:18
  • @Nick Ok, can't get anything close to what you want even with the output rules. Guess you should handle this programmatically! – cheesemacfly May 30 '13 at 21:09
  • I got it working, with help from your answer. For some reason I completely overlooked the outbound rules. I'll post the solution I used – Nick May 31 '13 at 16:42