|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article will show how to request for HTTP compression and handle a compressed response from a web server (or any appliance connected to the server) without changing the client application. The factory pattern of creating WebRequest instancesThe
The Because we can control the The The codeAs shown before, to add HTTP compression to our applications, we just have to build three classes: CompressibleHttpRequestCreator - implementing the IWebRequestCreate interface.
CompressibleHttpWebRequest - derived from WebRequest.
CompressibleHttpWebResponse - derived from WebResponse.
In order for the applications that use Fortunately, CompressibleHttpRequestCreatorThis is the class that will be implementing the As mentioned before, the only way to create an instance of a public class CompressibleHttpRequestCreator : IWebRequestCreate
{
WebRequest IWebRequestCreate.Create(Uri uri)
{
ISerializable httpWebRequest = Activator.CreateInstance(
typeof(HttpWebRequest),
BindingFlags.CreateInstance | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { uri },
null) as ISerializable;
if (httpWebRequest == null)
{
return null;
}
SerializationInfo serializationInfo = new SerializationInfo(
typeof(CompressibleHttpWebRequest), new FormatterConverter());
StreamingContext streamingContext =
new StreamingContext(StreamingContextStates.All);
httpWebRequest.GetObjectData(serializationInfo, streamingContext);
CompressibleHttpWebRequest webRequest = new
CompressibleHttpWebRequest(serializationInfo, streamingContext);
webRequest.Method = serializationInfo.GetString("_OriginVerb");
return webRequest;
}
}
CompressibleHttpWebRequestThis class will handle the setup of the HTTP request and the creation of the As with To specify what types of compression will be accepted in the response, the
[Serializable]
public class CompressibleHttpWebRequest : HttpWebRequest
{
private static FieldInfo m_UsesProxySemanticsFieldInfo =
typeof(HttpWebResponse).GetField("m_UsesProxySemantics",
BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo m_ConnectStreamFieldInfo =
typeof(HttpWebResponse).GetField("m_ConnectStream",
BindingFlags.NonPublic | BindingFlags.Instance);
private AcceptEncodings acceptEncodings = AcceptEncodings.GZip |
AcceptEncodings.Deflate | AcceptEncodings.Identity;
public AcceptEncodings AcceptEncodings
{
get
{
return this.acceptEncodings;
}
set
{
this.acceptEncodings = value;
}
}
protected internal CompressibleHttpWebRequest(SerializationInfo
serializationInfo, StreamingContext
streamingContext) : base(serializationInfo,
streamingContext)
{
}
public override IAsyncResult
BeginGetResponse(AsyncCallback callback, object state)
{
if (this.acceptEncodings != AcceptEncodings.Identity)
{
this.Headers.Add("Accept-Encoding",
(this.acceptEncodings &
~AcceptEncodings.Identity).ToString().ToLower());
}
return base.BeginGetResponse(callback, state);
}
public override WebResponse EndGetResponse(IAsyncResult asyncResult)
{
ISerializable httpWebResponse =
base.EndGetResponse(asyncResult) as ISerializable;
if (httpWebResponse == null)
{
return null;
}
SerializationInfo serializationInfo = new
SerializationInfo(typeof(CompressibleHttpWebResponse),
new FormatterConverter());
StreamingContext streamingContext = new
StreamingContext(StreamingContextStates.All);
httpWebResponse.GetObjectData(serializationInfo, streamingContext);
CompressibleHttpWebResponse webResponse = new
CompressibleHttpWebResponse(serializationInfo,
streamingContext);
m_UsesProxySemanticsFieldInfo.SetValue(webResponse,
m_UsesProxySemanticsFieldInfo.GetValue(httpWebResponse));
m_ConnectStreamFieldInfo.SetValue(webResponse,
m_ConnectStreamFieldInfo.GetValue(httpWebResponse));
return webResponse;
}
}
CompressibleHttpWebResponseThis is the easiest one. All that's needed is to handle the response stream accordingly to the [Serializable] public class CompressibleHttpWebResponse : HttpWebResponse { public CompressibleHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { } public override Stream GetResponseStream() { Stream stream = base.GetResponseStream(); if (stream == null) { return Stream.Null; } if (string.Compare(ContentEncoding, "gzip", true) == 0) { return new GZipInputStream(stream); } else if (string.Compare(ContentEncoding, "deflate", true) == 0) { return new InflaterInputStream(stream); } else { return stream; } } } ConfigurationNow, to add HTTP compression support to any application, all that's needed is to add the corresponding entry to the <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<webRequestModules>
<add prefix="http"
type="PaJoCoMo.Net.CompressibleHttpRequestCreator, PaJoCoMo" />
</webRequestModules>
</system.net>
</configuration>
| ||||||||||||||||||||||