We are developing a Silverlight application since some months ago. As you may know, an RTM of Silverlight 2 has been released recently, so we decided to migrate our project to it. Surprisingly, it stopped to work in IE 6 after the migration. The exception raised by Silverlight looked like:
[BrowserHttpWebRequest_WebException_RemoteServer] Arguments:NotFound Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=2.0.31005.0&File=System.Windows.dll&Key=BrowserHttpWebRequest_WebException_RemoteServer
Pretty mysterious, isn't it? Well, fortunately I googled it, and I found the following thread in the official Silverlight forum:
According to Vijay Devatha, from the Silverlight team:
This is a known issue that, unfortunately, currently has no workaround. We definitely plan to fix it in the following release; but like I said, for the time being, to get this scenario to work in on IE6, you're going to have to either disable compressing the content (on the server side), or have the server not set the Cache header to no-cache.
I didn't have the Cache-Control header field set to no-cache, so that wasn't the problem. Then I tried disabling GZip compression and it worked!
Great but... GZip compression was there for a good reason. Having to disable it for Firefox, Safari and even IE7 just because it didn't work with IE6 didn't sound like a great deal... So the most reasonable workaround seemed to disable GZip just for IE6.
Using an exclusion list of user agents to disable GZip in Jetty for some browsers
In the second part of this post, I'll show how to disable GZip compression for a fixed list of browsers. It is simple, but I had to figure it out from scratch, because I didn't find much documentation on the subject.
If you want to implement GZip in Jetty, you just have to add a GZipFilter to the filter chain of your Jetty context. Usually, this is done as follows:
context.addFilter(GZipFilter.class, "/*", 0);
Now, we want GZipFilter to be applied just when the request comes from some browsers. There's an initialization parameter which allows us to do that: excludeUserAgents.
So the above code now will look as follows:
GzipFilter gzipFilter = new GzipFilter(); FilterHolder filterHolder = new FilterHolder(gzipFilter); filterHolder.setInitParameter("userAgent", "(?:Mozilla[^\(]*\(compatible; \s*+([^;]*);.*)|(?:.*?([^\s]+/[^\s]+).*)"); filterHolder.setInitParameter("excludedAgents", "MSIE 6.0"); context.addFilter(filterHolder, "/*", 0);
Since we need to customize some parameters from GzipFilter, we can't let the Jetty Context instantiate it anymore.
There's an overload of addFilter which expects a FilterHolder object instead of a Class. The FilterHolder will act as a proxy and will set up the GzipFilter instance for us when a request has to be satisfied.
So we inject the GzipFilter instance into the FilterHolder constructor and set up the custom parameters we need. The "userAgent" parameter is mandatory, it states which user agents will be processed. The regex I'm using should match any of the main browsers out there.
Now we just need to exclude the browsers we don't want to receive gzipped content. This is done by setting the "excludedAgents" parameter. It expects a comma separated list of user agent ids. In my case, I just needed to filter out IE6, so I set "MSIE 6.0"
This way we can have our application working on IE6 while we wait for the problem to be fixed.