۱۳۸۸/۰۴/۲۲

فشرده سازي خروجي يك وب سرويس


جهت بهينه سازي روش ارائه شده در مقاله "بارگذاري يك يوزركنترل با استفاده از جي‌كوئري" ، مي‌توان مبحث فشرده سازي را نيز به آن افزود.
براي اين منظور نياز است تا بتوان response حاصل را كاملا كنترل كرد و اين مورد از طريق يك http module به خوبي قابل انجام است. مبحث http compression و پياده سازي آن‌را احتمالا بارها در سايت‌هاي مختلف نيز ديده‌ايد:

using System;
using System.IO;
using System.IO.Compression;
using System.Globalization;
using System.Web;


public class JsonCompressionModule : IHttpModule
{
public JsonCompressionModule()
{
}

public void Dispose()
{
}

public void Init(HttpApplication app)
{
app.PreRequestHandlerExecute += new EventHandler(Compress);
}

private void Compress(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
HttpResponse response = app.Response;

if (request.ContentType.ToLower(CultureInfo.InvariantCulture).StartsWith("application/json"))
{
if (!((request.Browser.IsBrowser("IE")) && (request.Browser.MajorVersion <= 6)))
{
string acceptEncoding = request.Headers["Accept-Encoding"];

if (!string.IsNullOrEmpty(acceptEncoding))
{
acceptEncoding = acceptEncoding.ToLower(CultureInfo.InvariantCulture);

if (acceptEncoding.Contains("gzip"))
{
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
response.AddHeader("Content-encoding", "gzip");
}
else if (acceptEncoding.Contains("deflate"))
{
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
response.AddHeader("Content-encoding", "deflate");
}
}
}
}
}
}
در اين ماژول تنها درخواست‌هايي از نوع application/json بررسي خواهند شد. هر چند اين فشرده سازي را بر روي خروجي هر نوع WebMethod ايي نيز مي‌توان اعمال كرد. در اين حالت، سطر بررسي json را حذف كرده و آن‌را به صورت زير تغيير دهيد:

if ( !request.Url.PathAndQuery.ToLower().Contains( ".asmx" ) )
return;
مرورگر IE6 و پايين‌تر نيز از اين فشرده سازي معاف شده‌اند (چون يا پشتيباني كاملي را ارائه نمي‌دهند يا بايد منتظر كرش مرورگر بود).

جهت اعمال اين ماژول به برنامه ASP.Net خود، كافي است سطر زير را به قسمت httpModules وب كانفيگ افزود:

<httpModules>
<add name="JsonCompressionModule" type="JsonCompressionModule"/>
</httpModules>
روش آزمايش ماژول تهيه شده:

متاسفانه افزونه‌ي فايرباگ فايرفاكس اندازه‌ي نهايي response را نمايش مي‌دهد و در گزارش آن حتي خبري از Content-encoding اضافه شده نيز نخواهد بود. بنابراين براي بررسي اين روش مناسب نيست.
ابزار ديگري كه اساسا براي اين نوع آزمايشات طراحي شد‌ه است، برنامه معروف فيدلر مي‌باشد (كه توسط مدير پروژه تيم IE برنامه نويسي شده است).
براي استفاده از فيدلر جهت ديباگ درخواست‌هاي local بايد يك نكته‌ي كوچك را رعايت كرد:
http://localhost.:25413/

همانطور كه در URL فوق مشاهده مي‌كنيد يك نقطه پس از localhost اضافه شده است تا خروجي محلي مربوطه قابل بررسي شود.



مطابق تصوير فوق، هم content-encoding اضافه شده مشخص است و هم حجم پاسخ دريافتي از 40 كيلوبايت (بر اساس يك تست معمولي روي صفحه‌اي مشخص) به نزديك يك كيلوبايت و اندي كاهش يافته است.