“未修改”标头后跟带有 sitemesh3 和 mod-jk 的意外内容正文

Posted

技术标签:

【中文标题】“未修改”标头后跟带有 sitemesh3 和 mod-jk 的意外内容正文【英文标题】:"Not Modified" header followed by unexpected content body with sitemesh3 and mod-jk 【发布时间】:2014-08-17 06:48:16 【问题描述】:

在我的 Java / Struts2 / Tomcat 应用程序中,当请求一些生成“304 Not Modified”响应的资源时,响应中仍在发送文件。

这是使用 Fiddler 捕获的响应示例:

HTTP/1.1 304 Not Modified
Date: Thu, 26 Jun 2014 11:27:27 GMT
Server: Apache/2.2.16 (Ubuntu)
Connection: Keep-Alive
Keep-Alive: timeout=15, max=100
Vary: Accept-Encoding

/*! jQuery v1.7.2 jquery.com | jquery.org/license */
(function(a,b)function cy(a)return f.isWindow(a)?a:a.nodeType===9? 
a.defaultView||a.parentWindow:!1function cu(a)if(!cj[a])var b=c.body,d=f("
<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e==="")ck||
[...]

这是一个问题,因为返回文件的内容被插入到下一个请求的文件中,最终导致损坏和奇怪的行为。

这只发生在从“/struts”路径加载的资源上,例如:

/struts/utils.js
/struts/js/base/jquery-1.10.2.min.js
/struts/js/base/jquery.ui.core.min.js?s2j=3.7.0

“/struts”路径由struts2类处理

org.apache.struts2.dispatcher.DefaultStaticContentLoader

这些是系统的相关元素:

Ubuntu 12.04.4 LTS(GNU/Linux 3.5.0-27-generic x86_64) JVM 1.6.0_31-b31 Sun Microsystems Inc.(也尝试使用 ibm-java-x86_64-71) Apache2 2.2.22-1ubuntu1.6 和 modjk Apache Tomcat/6.0.35 Struts 2.3.16 Sitemesh 3.0.0

直接连接到 tomcat 时,在 Not Modified 标头之后我没有收到任何意外数据。

Apache Server 配置没有做太多修改,只是 /contents 的别名和两个 modjk 指令:

JkMount /* ajp13_worker
JkUnMount /contents/* ajp13_worker

与 /struts 或缓存或任何异国情调无关。 ModJK 配置是默认设置。

有什么建议吗?

【问题讨论】:

你在tomcat前面使用apache服务器吗?如果在本地机器应用程序工作,那么它可能是服务器配置问题。 是的,我确实在远程安装中使用了 apache。谢谢你指出这一点。我会更新问题。 还要更换你的JVM实例,你使用的版本有很多bug,强烈建议在你的盒子上运行自动更新服务。 java版本没有任何区别。我用 IBM java7 "ibm-java-x86_64-71"(Tomcat Manager 报告的 pxa6470_27-20131115_04)启动了 tomcat,问题仍然存在。 【参考方案1】:

这是一个不能解决问题的答案,但会引发新的问题。

在 apache 服务器后面使用 sitemesh3 时发生响应损坏。 如果我直接访问 tomcat 服务器,响应是干净的 304。 如果我通过 modjk/apache 访问,响应包含意外数据。

意外数据的原因是由于 sitemesh 的工作方式:发送响应时,在某些时候它会强制 struts 忽略任何“If-Modified-Since”标头,将请求的内容写入响应缓冲区。然后通过在缓冲区的开头添加 304 标头来继续。

先看看

org.sitemesh.webapp.contentfilter.HttpServletRequestFilterable
org.apache.struts2.dispatcher.DefaultStaticContentLoader.process()

我不知道从这里去哪里。它是一个错误吗?是 Apache Server 的错误还是 Tomcat 的错误、Struts 的错误或 Sitemesh 的错误?!

要复制该问题,您需要在 apache 后面运行一个带有 sitemesh 的 struts webapp 的 tomcat,并在 fiddler2 处于活动状态时获取此 url 两次:

http://[test.server.address]/struts/utils.js

小菜一碟o_O'

编辑:

如果我查看 modjk 日志,我可以清楚地看到传输回 Apache 服务器的文件:

: trying to connect socket 29 to 127.0.0.1:9009                                                     
: socket 29 [127.0.0.1:57195 -> 127.0.0.1:9009] connected                                           
: sending to ajp13 pos=4 len=581 max=8192                                      
.4.A....HTTP/1.1  
.../struts/utils  
.js...2.235.97.2  
[...]
...Accept-Langua  
ge..#en,en-US;q=  
0.8,it-IT;q=0.6,  
it;q=0.4....+JSE  
SSIONID=B77369AB  
D8239724A27A5CC5  
6E06DED8...If-Mo  
dified-Since...F  
ri,.27.Jun.2014.  
08:37:46.GMT....  
.0....AJP_REMOTE  
_PORT...19143...  
.JK_LB_ACTIVATIO  
N...............  
: (rdp_worker) request body to send 0 - request body to resend 0                              
: received from ajp13 pos=0 len=20 max=8192                                     
..0..Not.Modifie   
d...............   
: status = 304                                                                           
: Number of headers is = 0                                                               
: received from ajp13 pos=0 len=4767 max=8192                                   
.../*..*.$Id:.ut   
ils.js.1240312.2   
012-02-03.19:44:   
51Z.jogep.$..*..   
*.Licensed.to.th   
e.Apache.Softwar   
e.Foundation.(AS   
F).under.one..*.   
or.more.contribu   
tor.license.agre   
ements...See.the   
[...]   
the.ajaxValidati   
on.interceptor.S   
trutsUtils.getVa   
lidationErrors.=   
: ws_write::mod_jk.c (537): written 4763 out of 4763                                                                                    
: received from ajp13 pos=0 len=4 max=8192                                      
................   
: received from ajp13 pos=0 len=2 max=8192                                      
................   
: AJP13 protocol: Reuse is OK 

当我直接访问 tomcat 并使用 tcpflow 转储 TCP 流量时,我没有看到任何虚假数据:

# tcpflow -p -s -c host xxx.xxx.xxx.xxx and port 8080

xxx.xxx.xxx.xxx.19292-yyy.yyy.yyy.yyy.08080: GET /rdp/struts/utils.js HTTP/1.1
Host: xxx.net:8080
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en,en-US;q=0.8,it-IT;q=0.6,it;q=0.4
Cookie: JSESSIONID=B0F02CXXXEC3448F1B927C0E8C579A9B
If-Modified-Since: Fri, 27 Jun 2014 08:49:23 GMT


yyy.yyy.yyy.yyy.08080-xxx.xxx.xxx.xxx.19292: HTTP/1.1 304 Not Modified
Server: Apache-Coyote/1.1
Date: Fri, 27 Jun 2014 08:52:43 GMT

因此,将缓冲区返回到 ajp 端口并将其返回到网络套接字似乎有不同的行为。这对我来说太低了。

编辑:

解决方法

我实施的解决方法是让 Apache 服务器处理 /struts 上下文:

从 struts 和 struts-jquery-plugin jar 中提取所有受影响的文件(分别为 org\apache\struts2\static 的内容和模板的内容) 将这些文件复制到服务器上的目录中 在 apache 中创建一个别名,以便在遇到 /struts 路径时为该目录提供服务 从 modJK 中取消映射 /struts 路径

【讨论】:

我在 Sitemesh3 网站上打开了一个问题,以便我们可以联合起来:github.com/sitemesh/sitemesh3/issues/62

以上是关于“未修改”标头后跟带有 sitemesh3 和 mod-jk 的意外内容正文的主要内容,如果未能解决你的问题,请参考以下文章

CORS 尝试,php 未修改响应标头

SiteMesh3整合SpringMVC+FreeMarker

Angular 6获取带有httpclient问题的响应标头

带有参数列表的Fortran类型定义

带有 0 或 1 的正则表达式数字 - 后跟数字

php ACF代码显示带有嵌入链接的图像,后跟文本字段