Introduction
This article describes the implementation of a utility class that will allow
HTTP requests informing the server (or any appliance in the network between the
client and the server) what types of compression it can handle and uncompress the
response from the server (if any) without changing the client application.
HTTP compression is very useful when the cost of the connection is high.
The factory pattern of creating WebRequest instances
The
WebRequest
supplies two methods to create instances:
The
WebRequest
class uses instances of classes that implement the
IWebRequestCreate
interface and are registered in the
webRequestModules
section in the configuration files. The
Create
method (called by both
CreateDefault
and
Create
) returns an initialized instance of a
WebRequest
descendent class capable of performing a standard request/response
transaction for the protocol without needing any protocol-specific fields modified.
On the other hand, the previously created
WebRequest
derived instances will return
WebResponse
derived instances that will handle the HTTP response.
Because of the way the factory pattern is implemented, we can change the
behavior of already built applications (our applications or even the .NET Framework)
to request and handle HTTP compression, changing only the configuration files.
Since in versions 2.0 and above of the .NET framework already support compression,
there is no need to supply
WebRequest
and
WebResponse
derived class implementations. All that's needed is
a class that implements the
IWebRequestCreate
interface to create the
WebRequest
derived instance and set it up.
The code
As shown before, to add HTTP compression to our applications, we just have to
build three classes:
CompressibleHttpRequestCreator
In order for the applications that use
HttpWebRequest
and
HttpWebResponse
to work without any changes, CompressibleHttpRequestCreator.Create
has to return a
HttpWebRequest
instance. Unfortunately, there is no public construtor
for
HttpWebRequest
or publicly accessible implementation of
IWebRequestCreate.Create
that creates a
HttpWebRequest
instance, so some reflection will be needed.
The implementation of
IWebRequestCreate.Create
just creates an instance of
HttpWebRequest
and sets its
HttpWebRequest.AutomaticDecompression
to accept all types of
compression.
public class CompressibleHttpRequestCreator : IWebRequestCreate
{
public CompressibleHttpRequestCreator()
{
}
WebRequest IWebRequestCreate.Create(Uri uri)
{
HttpWebRequest httpWebRequest =
Activator.CreateInstance(typeof(HttpWebRequest),
BindingFlags.CreateInstance | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance,
null, new object[] { uri, null }, null) as HttpWebRequest;
if (httpWebRequest == null)
{
return null;
}
httpWebRequest.AutomaticDecompression =DecompressionMethods.GZip |
DecompressionMethods.Deflate;
return httpWebRequest;
}
}
Configuration
Now, to add HTTP compression support to any application, all that's needed is
to add the corresponding entries to the
webRequestModules
section in the configuration file.
<configuration>
<system.net>
<webRequestModules>
<remove prefix="http:"/>
<add prefix="http:"
type="Pajocomo.Net.CompressibleHttpRequestCreator, Pajocomo" />
</webRequestModules>
</system.net>
</configuration>
History
When I first ported this
from .NET 1.1, I completely missed the fact that
HttpWebRequest
and
HttpWebResponse
already implemented compression.
Thanks to
Bj�rn to point that out to me.