4

I'm attempting to inject a decoding filter in the request pipeline using IHttpAsyncHandler, but am finding that the Request.Filter property is being ignored.

Has anyone successfully used Request.Filter along with IHttpAsyncHandler?

public class DecodeHttpHandler : IHttpAsyncHandler {
    public void ProcessRequest(HttpContext context) {
        context.Request.Filter = new DecodeStream(context.Request.Filter);
    }
    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {
        var decodeContext = new DecodeContext(context);
        var w = new HttpContextWrapper(context);
        w.Request.Filter = new DecodeStream(w.Request.Filter);
        return RequestHandler.BeginProcessRequestBase(w, cb, extraData);
    }
    public void EndProcessRequest(IAsyncResult result){
        RequestHandler.EndProcessRequestBase(result);
    }
    public bool IsReusable {
        get {
            return true;
        }
    }
}
public class DecodeStream : Stream {
    ... details ...
    public override int Read(byte[] buffer, int offset, int count) {
        // never gets here
        int c = _sink.Read(buffer, offset, count); 
        return c; 
    }
}

EDIT: I found another good way to do this not involving Request.Filter, pasted below. However, it's puzzling that Request.Filter simply doesn't work. FYI, my use case was to do URL decoding prior to calling a 3rd-party RequestHandler.

public class UrlDecodeHttpHandler : IHttpAsyncHandler {
    public void ProcessRequest(HttpContext context) {
        throw new NotImplementedException();
    }
    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {
        var decodeContext = new DecodeContext(context);
        return RequestHandler.BeginProcessRequestBase(decodeContext, cb, extraData);
    }
    public void EndProcessRequest(IAsyncResult result){
        RequestHandler.EndProcessRequestBase(result);
    }
    public bool IsReusable {
        get {
            return false;
        }
    }
}
public class DecodeContext : HttpContextWrapper {
    private readonly HttpContext _context;       
    public DecodeContext(HttpContext httpContext) : base(httpContext){
        _context = httpContext;
    }
    public override HttpRequestBase Request {
        get { return new DecodeRequest(_context.Request); }
    }        
}
public class DecodeRequest : HttpRequestWrapper {
    public DecodeRequest(HttpRequest request) : base(request) {}
    public override Stream InputStream {
        get {
            string result;
            using (var sr = new StreamReader(base.InputStream)) {
                result = HttpUtility.UrlDecode(sr.ReadToEnd());
            }
            return GenerateStreamFromString(result);
        }
    }
    private static Stream GenerateStreamFromString(string s) {
        var stream = new MemoryStream();
        var writer = new StreamWriter(stream);
        writer.Write(s);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }
} 
dcpar
  • 273
  • 2
  • 10

1 Answers1

0

There are a lot of things you can't change in a httphandler because it's too late. You could try put an HTTPModule in there to intercept and see if that helps. Note I haven't tried this yet if I get time at home I will..

Dave Walker
  • 3,498
  • 1
  • 24
  • 25