我正在尝试使用 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;
}
}