Azure website as a caching reverse proxy using ARR - caching

We are migrating one of our websites to Azure which was previously setup using ARR (Application Request Routing) as a caching reverse proxy. It was setup as a reverse proxy which would honor the cache headers of the site it was proxying.
I've followed this guide on using an Azure website as a reverse proxy and it all works fine except that it doesn't honor the cache headers of the site it is proxying. I tried adding some more pertinent elements to my applicationHost.xdt, but nothing I do seems to have any effect.
Here is the relevant section from my applicationHost.xdt:
<system.webServer>
<caching xdt:Transform="Replace" enabled="true" enableKernelCache="true" maxResponseSize="1000000"></caching>
<proxy xdt:Transform="InsertIfMissing" enabled="true" reverseRewriteHostInResponseHeaders="true" minResponseBuffer="4096" responseBufferLimit="12392">
<cache enabled="true" queryStringHandling="Accept" validationInterval="00:01:00" />
</proxy>
</system.webServer>
and here is my web.config:
<system.webServer>
<rewrite>
<rules>
<rule name="CurrentTime" stopProcessing="true">
<match url="^times/?(.*)" />
<action type="Rewrite" url="http://example.com/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
The web.config just routes all requests to /times to example.com. That part is working great. It is just ignoring the cache headers of example.com and not caching anything which is the main use case of why we want to setup a reverse proxy.
This same configuration works just fine on a normal machine with IIS and ARR installed.
I'd really like to get this working in azure websites without having to use a web role in a cloud service. I'm hoping this is possible.

Did you try to specify the preserveHostHeader="true" flag as follows?
<proxy xdt:Transform="InsertIfMissing" enabled="true" preserveHostHeader="true" reverseRewriteHostInResponseHeaders="true" />

Related

keep URL same and load content of different website

I have first.abc.com/xyz (xyz being an application under main domain abc.com) that needs to load content off of a different website second.abc.com/whatever/xyz while keeping the URL same to first.abc.com/xyz how is this possible? I have looked into a couple videos for reverseproxy with ARR, but I am not an expert on servers. Hope I am clear on the issue at hand. Any help would be great.
you need to install
IIS URL rewrite module
IIS ARR routing for reverse proxy using
then add the routing in web.config ,or add in the applicationhost.config
here is the example
<rule name="ReverseProxy" enabled="true" stopProcessing="true">
<match url="(xyz)$" />
<action type="Rewrite" url="http://first.abc.com/xyz" appendQueryString="false" logRewrittenUrl="true" />
</rule>

Cache busting in IIS using query string for static content

my site is a static site and I serve the content from a IIS 8 web server. I used to use Apache and I have the following configuration for cache busting, which I'd like to implement in IIS:
# Extend cache expiry for fingerprinted URLs
RewriteCond %{QUERY_STRING} ^[0-9a-fA-F]{8,}$
RewriteRule ^ - [E=revved:1]
And then I set Cache-Control based on whether the environment variable "revved" is set:
# (For HTTP/1.1 clients)
Header set Cache-Control "max-age=1200" env=!revved
Header set Cache-Control "max-age=31536000" env=revved
My JS and CSS is bundled and I attach the hash to the query string. I do the same for images.
So far what I have been available to do is use the <clientCache /> element and attach cacheControlMode="UseMaxAge and cacheControlMaxAge="00:20:00" to it.
What you can see in the Apache config is that when the "revved" variable is set then the proxy server (CDN) and the client should cache the files for 365 days. Otherwise, it should only cache for 20 minutes. I'd like to have the same behaviour in my web.config.
I read about "Output Caching" in IIS, but from what I understand that is designed for dynamic pages using PHP or ASP.
I would be very grateful, if someone can guide me in the right direction.
I believe that I came up with a solution that is working. I got some hints from this post on MSDN "Change or modify a Response Header value using URL Rewrite".
<outboundRules>
<rule name="ChangeCacheControlHeaderOneYear">
<match serverVariable="RESPONSE_CacheControl" />
<conditions>
<add input="{QUERY_STRING}" pattern="^[0-9a-fA-F]{8,}$" />
</conditions>
<action type="Rewrite" value="max-age=31536000" />
</rule>
<rule name="ChangeCacheControlHeader20Minutes">
<match serverVariable="RESPONSE_CacheControl" />
<conditions>
<add input="{QUERY_STRING}" pattern="^[0-9a-fA-F]{8,}$" negate="true" />
</conditions>
<action type="Rewrite" value="max-age=1200" />
</rule>
</outboundRules>

How to configure web.config to load resources form external server

I'm developing a web application in Visual Studio 2013 and am getting my data from an external server. For this reason I disable the web securtiy in my browser and define absolute URLs in my application. Now whenever I'm deploying the applicaiton, I have to adopt the URLs (which of course get's forgotten the first time) and also I have to explain the setup to evey person new in the porject.
After getting a bit fimilar with the web.config file, I tried to setup some rules, to rewirte this urls to the data webserver, but failed.
All my relative urls start with the same identifyer, and should be mapped to an external server. This is what I have so far:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
<system.webServer>
<rewrite>
<rules>
<rule name="Rewrite calls to rest.oms to the actuall webserver">
<match url="^/IDENTFIER/([_0-9a-z-]+)" />
<action type="Rewrite" url="http://EXTERNAL_SERVER/IDENTFIER/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
However, it is not working so far. Can somebody help me please.
Best Regards,
Stefan
It is possible to rewrite from external url, if you have ARR module.
1) You need to install ARR module for your IIS
2) In IIS manager you should enable reverse proxy
2.1) On server node click "Application Request Routing Cache"
2.2) Click "Server proxy settings" and click "Enable proxy", then "Apply"
3) Slightly fix your rewrite rule regexp (remove starting slash):
<rule name="Rewrite calls to rest.oms to the actuall webserver">
<match url="^IDENTFIER/([_0-9a-z-]+)" />
<action type="Rewrite" url="http://EXTERNAL_SERVER/IDENTFIER/{R:1}" />
</rule>
Then your rule should work.

How do you properly install an ASP.NET MVC app as a child of another MVC app?

I have a main website app written in ASP.NET's MVC 3. Now, what I would like to do on occasion, is add a subdirectory, mark it as an application and run a whole different MVC 3 app from that directory. For instance, my site is at http://sol3.net. I am working on a small MVC app for a client and I'd like to publish it on my site so he can take a look at the progress, offer feedback, etc. So, their site would be at http://sol3.net/projectA. Having done this with a test app all I am getting is a 500 error.
Are there any best practices on how to set this up?
And yes, I already know about web.config inheritance problems. Fortunately my web.configs are not too large and I think I have most everything handled there.
NOTE: What I am trying to do is temporarily run a MVC app (App B) from within an app folder on an already active site (App A). App A and App B do not share anything in common and App B will eventually be moved to its own hosting site.
NOTE #2: The Answer...
I believe it is IIS7 and higher that allows you to add a redirection in your root web.config. Here is what I ended up doing instead of doing it via IIS Manager:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<rewrite>
<rules>
<rule name="APP 1 - Sub domain to sub folder" enabled="true">
<match url="(.*)" ignoreCase="true" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^(www\.)?app1\.sol3\.net$" ignoreCase="true" />
</conditions>
<action type="Rewrite" url="app1/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
You would add a subdomain via an alias in your DNS records. Some registrars will let you do this yourself, but some sell this as a feature. A whois on your domain says it's registered with GoDaddy. Check this out. http://help.godaddy.com/article/4652#addsubdomain1
Edit - OrcsWeb allows for remote management of your web site via IIS 7 Manager. This should allow you to edit the host header. http://www.orcsweb.com/blog/brad/iis-7-manager-for-remote-administration-installing-and-connecting-to-a-site/

Proxy - ASP.NET with or without MVC

I'm working on one multi-tenancy application, where each tenant will have access to 1 or more "sub applications" (different ASP.NET MVC websites).
http://v1.app1.domain.com
http://v1.app2.domain.com
http://v1.app3.domain.com
Later in time, I'll have new versions for each sub application and I will end with:
http://v1.app1.domain.com
http://v2.app1.domain.com
http://v3.app1.domain.com
http://v1.app2.domain.com
http://v2.app2.domain.com
http://v1.app3.domain.com
Some tenants will want to have access to the latest versions, and some will still be using old ones.
This is what I've done.
Now I would like to keep "the subdomain versions" hidden for them. They will only access the domain: app1.domain.com
This "internal smart proxy" will have the core to know which version this tenant has access.
Anyone knows how I can do this? In a way that all my internal urls (links, images, JS, css, etc...), AJAX,etc, will work correcly?
Or point me to some tutorials/blog/forums where i can find that can help me?
Thank you very much.
What you are trying to build is in essence an HTTP proxy. The difference to most other proxies is just that the actual URL is built on the server side.
There many different ways to do this. I'd choose one of the following:
Create an HTTP handler, in which case you could use this code project article as a starting point.
Use ASP.NET MVC. Create a "catch all" route and pipe that through one single action method.
Either way, you will have to
Analyze the HttpContext.Current.Request object and build a suitable outgoing URL
Use a HttpWebRequest to fetch the data from the actual website. Remember to mimic the original request header plus request content (usually POST parameters) if applicable.
Output the Response Header from the server and then output the data you just fetched.
Application Request Routing (ARR) could be a workable solution if you are using IIS 7 or 7.5.
You would have an additional web site defined in IIS acting as the proxy, which would be separate to the web site(s) your application uses.
The rules about which tenant is on which version would have to be written to a web.config for ARR to read. Is this acceptable? If you have a small number of tenants changing infrequently, you may be happy to edit this file by hand. If you need more automation, you could programatically generate this web.config file. Because this web.config is only for your ARR proxy site, editing it will not cause your application sites to restart.
A sample configuration might use the following IIS Sites:
proxy - binding for your public IP address. *.domain.com resolves to this address
v1app - binding for 127.0.0.101
v2app - binding for 127.0.0.102
IIS server-level settings: ARR cache -> Server Proxy Settings -> enable proxy. (Set the timeout here if your app needs long timeouts.)
And in your "proxy" site's web.config, the following rewrite rules:
<rewrite>
<rules>
<rule name="V1 tenants" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://127.0.0.101/{R:1}" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="app1.domain.com" />
<add input="{HTTP_HOST}" pattern="app3.domain.com" />
</conditions>
</rule>
<rule name="V2 tenants" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://127.0.0.102/{R:1}" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="app2.domain.com" />
</conditions>
</rule>
</rules>
</rewrite>
When a request comes in, it will hit your proxy site, then those rules will look at the hostname and redirect to the appropriate internal site.
If your ARR site is running on the same server as your content sites, you may want to remove the line
<add name="ApplicationRequestRouting" />
from C:\windows\system32\inetsrv\config\applicationHost.config, and add it as a module in your proxy site's web.config. This will apply ARR only to your proxy site, instead of the whole server.

Resources