一个关于 net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 的BUG,在chrome与ajax请求的情况下

本文介绍了在使用Chrome浏览器进行AJAX请求时遇到的net::ERR_INCOMPLETE_CHUNKED_ENCODING 200错误。问题发生在TOMCAT8.5和SPRING MVC 3.2.4的环境中。错误源于DispatcherServlet处理异步请求时,由于响应已提交,尝试创建session导致的异常。解决方案是修改HandlerInterceptor,在preHandle方法中创建session,从而避免在postHandle中触发异常。
部署运行你感兴趣的模型镜像

BUG的环境,WEB服务器是TOMCAT8.5, 框架是SPRING MVC 3.2.4 ,开发环境IDEA 2020,JDK1.8 ; 这是个老项目改造,我也帮同事定位的。

1. 异常情况描述:

       通过chrome浏览器或ajax请求时,chrome能接收到服务段返回的数据,ajax请求直接抛network error的错误信息。网上主要又两种说法:

一种说法是返回JSON格式数据不完整导致。

另一种说法是 Transfer-Encoding:chunked 块传输有BUG。

2. BUG处理过程:

      处理过程一波三折,一开始总是各种怀疑与验证。认为前端同事的问题,认为请求头的问题,认为返回头的问题。然后搜索相同的BUG情况,网i上说的两种情况也不符合。但是那天晚上在加时用 BING搜英文确实有搜到说,Tomcat 8对Spring MVC的异步处理有BUG。接着排除了前端的问题才把注意力集中在后端上来,我知道 Spring MVC DispatcherServlet 的请求时异步处理的,DispatcherServlet 的 doDispath 的部分源码:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = processedRequest != request;

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest, false);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						String requestUri = urlPathHelper.getRequestUri(request);
						logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				try {
					// Actually invoke the handler.
					mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				}
				finally {
					if (asyncManager.isConcurrentHandlingStarted()) {
						return;
					}
				}

				applyDefaultViewName(request, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Error err) {
			triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				return;
			}
			// Clean up any resources used by a multipart request.
			if (multipartRequestParsed) {
				cleanupMultipart(processedRequest);
			}
		}
	}

代码中 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 就是获取处理异步请求的对象。并且发现请求过来后TOMCAT 确实有异常:

java.lang.IllegalStateException: Cannot create a session after the response has been committed
    at org.apache.catalina.connector.Requisest.doGetSession(Request.java:3034)
    at org.apache.catalina.connector.Request.getSession(Request.java:2468)
    at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:896)
    at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:908)
    at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:240)

报异常也很明确,说response 已经是提交的状态,所以不能创建session 了,根据异常的字面意思,就是非法的状态异常。这个异常会抛到 DispatcherServlet 里,所以导致前端报了 ERR_INCOMPLETE_CHUNKED_ENCODING  的异常。而这个创建 session 是项目的 拦截器调用的,代码如下:

 @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object arg2, ModelAndView view) throws Exception {
        Conf CONF = (Conf) request.getSession().getServletContext().getAttribute("APP_CONF");
        if (CONF == null) {
            CONF = confService.findConf();
            request.getSession().getServletContext().setAttribute("APP_CONF", CONF);
        }
    }

在 request.getSession() 需要创建 session 对象,上面的异常这么清晰,一开始是没有的,而是在项目中把Tomcat 8的源代码引入项目,然后找到抛出异常的代码。代码如下:org.apache.catalina.connector.Request.doGetSession 中部分代码:

 if (!create) {
            return (null);
        }
        if (response != null
                && context.getServletContext()
                        .getEffectiveSessionTrackingModes()
                        .contains(SessionTrackingMode.COOKIE)
                && response.getResponse().isCommitted()) {
            throw new IllegalStateException(
                    sm.getString("coyoteRequest.sessionCreateCommitted"));
        }

找到了异常,这里涉及到,Spring MVC 框架的 HandlerInterceptor 拦截器的接口处理过程,显然 preHandle()方法是在Handle之前处理的,如果要是在这里调用  request.getSession()  应该是可以的,结果的确是这样处理的,当然也可以将写在 postHandle()的移动到 preHandle()中,我不清楚原来同仁为何这么写。

所以在  preHandle()中 加如下的代码:

 public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object obj) throws Exception {
        response.addHeader("Access-Control-Allow-Origin","*");
        HttpSession httpSession = request.getSession();
        return true;
    }

这样可以避免在 postHandle()中去创建 session 。BUG到这里已经处理成功了。

3. BUG原理与总结:

       这种BUG其实不容易发生,只有在请求的过程中 HandlerInterceptor  postHandle()之前一直没有创建 session 时才发生。BUG原理其实 Spring MVC 请求做异步处理引起的

还有就是处理这种不常见的BUG主要还是需要源码 DEBUG 进去看每一变量的情况,

还有就是用比较方法去排除怀疑,比如让前端去请求一个原来可以正常使用的API接口,如果成功了,说明是现在的后端服务接口有BUG了。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think>嗯,用户遇到了net::ERR_INCOMPLETE_CHUNKED_ENCODING错误,需要解决方法。我之前根据提供的引用资料整理过解决方案,现在得再仔细看看这些引用,确保回答准确。 首先,引用[1]提到这个错误通常Nginx的proxy_temp_file_write_size配置有关。当输出文件大小超过这个值时,Nginx会写入临时目录,权限不足可能导致错误。解决方案是调整这个参数并检查目录权限。这点很重要,应该放在第一步。 然后引用[2]提到前端可能的问题,比如AJAX请求、事件处理、JSTL/EL以及后端报错。用户需要检查这些方面,特别是AJAX请求是否正确,后端是否有错误日志。这部分需要分步骤说明,帮助用户逐一排查。 引用[3]给出了具体的Nginx配置参数,比如proxy_buffer_size和proxy_buffers等。这些参数调整可以优化缓冲区,避免临时文件写入,从而解决问题。需要把这些配置示例写清楚,方便用户直接参考。 用户的问题可能涉及前后端多个方面,所以需要分点整理,结构清晰。先从服务器配置开始,再到前端检查,最后考虑其他可能性。同时要确保语言简洁,步骤明确,用户能一步步操作。 还要注意用户可能对Nginx配置不熟悉,需要说明如何修改配置文件以及重启服务。另外,检查临时目录权限的部分,可能需要具体命令,比如使用chmod或chown,但用户环境不同,所以给出通用建议更安全。 最后,总结常见原因,帮助用户快速定位。确保每个解决方案都有对应的引用标记,比如[^1]、[^2],这样用户知道来源,增加可信度。同时提醒如果问题仍未解决,需要更多具体信息,鼓励用户提供细节以便进一步帮助。</think>### 如何解决 `net::ERR_INCOMPLETE_CHUNKED_ENCODING` 错误? 此错误通常服务器代理配置或数据传输不完整相关,以下是分步解决方案: --- #### **1. 检查 Nginx 代理配置** 此错误常见于使用 Nginx 反向代理时,需调整以下参数: - **`proxy_temp_file_write_size`** 默认情况下,当响应数据超过缓冲区大小时,Nginx 会将数据写入临时文件。如果临时目录权限不足或该参数设置过小,会导致数据传输中断。 **解决方法**: 在 Nginx 配置文件中(如 `nginx.conf`)增加以下配置: ```nginx proxy_temp_file_write_size 8192k; # 临时文件写入大小上限 proxy_buffer_size 4096k; # 单个缓冲区大小 proxy_buffers 16 4096k; # 缓冲区数量大小 proxy_busy_buffers_size 8192k; # 忙碌时缓冲区大小 ``` 修改后执行 `nginx -s reload` 重启服务[^1][^3]。 - **检查临时目录权限** 确保 Nginx 工作进程对 `/var/lib/nginx/tmp`(或其他自定义临时目录)有读写权限: ```bash chmod -R 755 /var/lib/nginx/tmp chown -R nginx:nginx /var/lib/nginx/tmp ``` --- #### **2. 前端代码排查** 若错误出现在前端请求中(如 AJAX 或资源加载),需检查: - **AJAX 请求逻辑** 确保请求 URL 正确,未因路径错误返回异常响应。 - **事件处理函数** 检查 `onclick` 等事件是否因未正确处理异步操作导致请求中断。 - **JSTL/EL 表达式** 若使用 Java 模板,需确保表达式未因语法错误生成非法响应[^2]。 --- #### **3. 后端服务验证** - **查看后端日志** 检查应用服务器(如 Tomcat、Node.js)是否因代码异常中断响应。例如: - 未捕获的异常导致 HTTP 响应不完整。 - 数据库查询超时或连接中断。 - **分块传输编码(Chunked Encoding)** 确保后端正确实现分块传输逻辑,避免因数据流意外终止导致错误。 --- #### **4. 其他可能性** - **浏览器缓存干扰** 尝试清除 Chrome 缓存或使用无痕模式测试。 - **网络中间件问题** 检查防火墙或 CDN 是否拦截/修改了响应数据。 --- ### 总结表格 | 问题类型 | 检查方向 | 解决方案示例 | |----------------|---------------------------|----------------------------------| | Nginx 代理 | 缓冲区大小临时文件权限 | 调整 `proxy_*` 参数,修复目录权限[^1][^3] | | 前端代码 | AJAX 请求事件处理 | 修复请求逻辑,检查模板语法[^2] | | 后端服务 | 异常日志分块传输实现 | 捕获异常,优化响应逻辑 | 若问题仍未解决,请提供具体场景(如请求类型、服务器环境),以便进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值