如果发生exception,“Content-encoding”标头将从HttpHandler响应中消失
我有一个自定义的HttpHandler,我在其中手动启用输出压缩,如下所示:
context.Response.AppendHeader("Content-encoding", "gzip"); context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
这适用于大多数请求,但遇到exception时,“内容编码”标头会从响应中消失,而压缩filter仍保留在原位。 结果是错误页面被gzip压缩,但是浏览器没有收到表示该事实的标题。 然后浏览器尝试将仍然压缩的数据显示为文本,即gobbledygook 。
完整的测试用例代码如下所示。 尝试交替禁用压缩或不抛出exception。
有人可以解释为什么“内容编码”标题消失了吗?
我想我可以简单地启用压缩作为处理程序的最后一件事,因此如果遇到exception,它永远不会到达添加压缩filter的点; 但我看到的行为让我感到害怕。 谁能确认一下?
public class TestHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { CompressResponse(context); context.Response.Write("Hello world"); // Throw an exception for testing purposes throw new Exception("Just testing..."); } private void CompressResponse(HttpContext context) { string acceptEncoding = context.Request.Headers["Accept-Encoding"]; if (String.IsNullOrEmpty(acceptEncoding)) { return; } // gzip or wildcard if (acceptEncoding.ToLower().Contains("gzip") || acceptEncoding.Contains("*")) { context.Response.AppendHeader("Content-encoding", "gzip"); context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress); return; } // Also handles deflate (not shown here) // } public bool IsReusable { get { return true; } } }
编辑:我在测试用例中看到的仍然编码的响应的屏幕截图: http : //i.imgur.com/49Vcl.png
如果你有一个例外,那么服务器将刷新当前设置的标题和内容,因为它们是错误的,就像你有一个例外。
至少,很明显你要发送的200状态(因为所有不改变状态的成功响应发送200,而未处理的exception不再成功)是错误的,但其他一切都是相关的对于你将会做但却未能实现的事情,所以这一切都是错的,一切都会好起来的。
但是filter不会重置。
如果适当,可以重置错误页面中的标题,或者除非您确定所有内容都已准备好进行刷新,否则不要设置filter。 我会选择前者,没有理由为什么错误页面也无法压缩。
如果你打电话给Flush()
,你就不能发送标题,因为你已经刷新了。 标题将去哪里?
我也遇到了这个问题。 追踪是很复杂的。 我不确定这整个情况的具体细节,但我认为发生的是内存泄漏。
当你第一次这样做时:
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
您正在为Filter
分配非托管资源 。 通常情况下,这将包含在using
语句中,以便在出现任何问题时妥善处理。
所以,当出现问题时,就会出现问题。 Filter
包含一个仍然打开的流,即使响应是用死黄色屏幕写入的。 随之而来的是疯狂(如屏幕截图所示)。
不要害怕! 实际上有一种简单的方法可以解决这个问题。 处理filter。 幸运的是,已有一个地方可以应用此全局检查filter处理。
的global.asax.cs
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute());//default handler filters.Add(new HandleErrorEncodingAttribute());//extra check for filter disposal }
error handling程序名称
public class HandleErrorEncodingAttribute : FilterAttribute, IExceptionFilter { public virtual void OnException(ExceptionContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } if (filterContext.IsChildAction) { return; } // If custom errors are disabled, we need to let the normal ASP.NET exception handler // execute so that the user can see useful debugging information. if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) { filterContext.HttpContext.Response.Filter.Dispose();//fixes response stream return; } } }
在WebForms应用程序上强制使用gzip时,我遇到了同样的事情。 为了解决这个问题,我必须清除Global.asax.cs中Application_Error方法中的filter
protected void Application_Error(Object sender, EventArgs e) { Response.Filter = null; }
发生这种情况的原因是b / c在应用程序出错之前设置了filter。 由于某种原因,黄屏错误消息清除了内容编码标题,但对响应filter没有任何作用。
我测试你的代码,我找不到任何问题。 是的,没有设置gzip,但是还没有设置filter,asp获取控件并发送错误。
强制标题刷新会产生真正的问题
CompressResponse(context); context.Response.Flush();
如果我强制使用gzip标头,则页面无法正确呈现。
两个人认为这可能是你的问题。 您没有设置页面编码
context.Response.ContentEncoding = new UTF8Encoding();
并且您没有设置ContentType
context.Response.ContentType = "text/plain";
也许其中一些原因是您没有更正页面渲染。 在我的测试中,即使你所描述的问题没有出现。
上述就是C#学习教程:如果发生exception,“Content-encoding”标头将从HttpHandler响应中消失分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1007423.html