4

我正在尝试使用 IHttpAsyncHandler 在请求管道中注入解码过滤器,但发现 Request.Filter 属性被忽略。

有没有人成功使用 Request.Filter 和 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; 
    }
}

编辑:我找到了另一种不涉及 Request.Filter 的好方法,粘贴在下面。然而,令人费解的是 Request.Filter 根本不起作用。仅供参考,我的用例是在调用 3rd-party RequestHandler 之前进行 URL 解码。

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;
    }
} 
4

1 回答 1

0

在 httphandler 中有很多东西你不能改变,因为太晚了。您可以尝试在其中放置一个 HTTPModule 进行拦截,看看是否有帮助。请注意,如果我有时间在家,我还没有尝试过。

于 2012-03-30T16:06:21.997 回答