浙江移动新推出了中兴的彩信加速器(MMSA),用来专门接入SP。以前浙江的彩信中心所采用的厂家虽然也有不规范的地方(主要在于编码,在HTTP协议上约定书写为US-ASCII,但实际用GB2312编码),但都没有这次这么离谱。为了能够在AXIS这种标准平台上实现这些“非标准”的webservice,写了几段代码用来修补这种错误。
错误及解决方法
- 错误一
错误报文
Content-Type:text/xml;charset=US-ASCII; name=1.xml
Content-Transfer-Encoding:8bit
Content-Location:1.xml
Content-ID:<1.xml>
<?xml version="1.0" encoding="GB2312"?>
在HTTP头中申明字符编码为US-ASCII,但是在随后的XML中又申明XML编码为GB2312并且实际也是用GB2312来编码,AXIS 1.X的代码会自动判断HTTP的字符编码来决定XML的编码,并且HTTP头的优先级比XML的申明要高。AXIS中这样的构架其实没错,因为内容是要服从载体的。但AXIS中没知道可以调整的选项,于是修改了一下org.apache.axis.Message类,并打入工程包,重载axis中的原有包,为的就是处理这种非标做法。
org.apache.axis.Message
private void setup(Object initialContents, boolean bodyInStream,
String contentType, String contentLocation,
javax.xml.soap.MimeHeaders mimeHeaders) {
//省略原有部分
if (contentType != null) {
//省略原有部分
/////////添加部分/////////////////////////////////
try {
if (charset.endsWith("US-ASCII")) {
charset = "GB2312";
}
setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset);
} catch (SOAPException e) {
}
/////////添加部分/////////////////////////////////
}//if (contentType != null)
}
- 错误二
作为一个SOAP的WS,彩信上行(DeliverReq)的包,竟然没有SoapAction的HTTP Header,厂家的人还以协议没有强制规定作为理由,但是他们其他的包又是有的...
- 错误三
更离谱,彩信上行作为一个multipart的HTTP请求,是应该符合multipart的相关规定。这在之前的彩信中心是没有出问题的。但是新的MMSA,显然开发人员没有什么理论功底,至少也是没有做好功课。把multipart/related和multipart/mixed混为一谈,这到了严格编码的axis这边,当然有问题。
错误报文
Content-Type:multipart/mixed;type="text/xml";start="<1.xml>";boundary="----=_NextPart_0_2817_24856"
this is a multi-part message in MIME format.
------=_NextPart_0_2817_24856
Content-Type:text/xml;charset=US-ASCII; name=1.xml
Content-Transfer-Encoding:8bit
Content-Location:1.xml
Content-ID:<1.xml>
<?xml version="1.0" encoding="GB2312"?>
问题就出在this is...这句话里,按照协议multipart/mixed,在start和包头之间是不存在其他内容的,而上面的写法,应该是multipart/related的规格,按照错误的报文,axis会把this is...连同下面的xml正文一起送给xml解析器解析,这个不伦不类的xml报文,自然就出错了,AXIS也就停止了下面的工作,认为客户端送来了一个无效的WS请求。
我把发现的问题反馈给中兴的人,但是这样的大厂,工作效率和认错态度真是...无语。为了修正错误二和错误三,部署了一个filter,用来修改来源请求,使之符合协议。主要是新写一个HttpServletRequestWrapper,然后编写一个filter用新的HttpServletRequestWrapper来包装旧的错误请求,使得AXIS请求相关数据时能够进行纠正,主要重载getHeader方法。
HttpServletRequestWrapper的修复部分
public String getHeader(String name) {
if ("SOAPAction".equalsIgnoreCase(name)) {
if (null == super.getHeader(name)) {
return "";
}
}
if ("Content-Type".equalsIgnoreCase(name)) {
if (super.getHeader(name).startsWith("multipart/mixed")) {
return super.getHeader(name).replace("multipart/mixed",
"multipart/related");
}
}
return super.getHeader(name);
}
中兴的解释是,部分SP使用他们的厂家API,自然是不会出问题的...对这样的说法,我真的是很无奈。如果一个交换机,还要非标插头插头,那还有什么人会用,套用我们老总爱说的一句话,那就叫做自慰...
最新评论
4 周 3 天之前
4 周 3 天之前
24 周 2 天之前
36 周 16 小时之前
37 周 1 天之前
1 年 13 周之前
1 年 16 周之前
1 年 33 周之前
1 年 33 周之前
1 年 37 周之前