ASHX continues to be cool
2008-04-07 @ 10:45#
i really like working with ASHX files. and i especially like 'scripting' them (no compiled code). using ASHX files lets me write 'ground-level' HTTP code without all the muss and fuss of pages, etc. and since it's scripted, i can make changes with only minor 'costs.'
below is a quick high-level view of a recent script to serve up summarized server logs. note the use of the SetCompression() call and support for ETags. also, though it's not shown in this code, i have support for local caching, too (using ASP.NET's Cache class. this reduces CPU load.
public class LogData : IHttpHandler
{
HttpContext ctx = null;
string etag = string.Empty;
string data_folder = "~/log-data/";
public void ProcessRequest(HttpContext context)
{
ctx = context;
SetCompression(ctx);
switch (ctx.Request.HttpMethod.ToLower())
{
case "get":
Get();
break;
case "head":
Head();
break;
default:
throw new HttpException(405, "Method Not Allowed");
}
}
public bool IsReusable
{
get
{
return false;
}
}
private void Head()
{
Get(true);
}
private void Get()
{
Get(false);
}
private void Get(bool headCall)
{
string out_text = string.Empty;
string ifnonematch = string.Empty;
string file = string.Empty;
// get the file arg
file = (ctx.Request["file"] != null ? ctx.Request["file"] : string.Empty);
// get data to send
if (file != string.Empty)
{
out_text = HandleFile(file);
}
else
{
out_text = HandleFileList();
}
// check for not-modified
ifnonematch = (ctx.Request.Headers["if-none-match"] != null ? ctx.Request.Headers["if-none-match"] : string.Empty);
if (ifnonematch == etag)
{
ctx.Response.StatusCode = 304;
ctx.Response.StatusDescription = "Not Modified";
}
else
{
// ok, send the response
ctx.Response.AddHeader("etag", etag);
ctx.Response.ContentType = "text/html";
ctx.Response.StatusCode = 200;
// only send body if this is not "head" call
if (!headCall)
{
ctx.Response.Write(out_text);
}
}
}
// lots of important stuff goes here...
}