级别: 初级 刘海龙, 通信与信息系统专业博士研究生, 北航电子工程系
2001 年 9 月 01 日
本文介绍了一种在 MIME Multipart/Related 消息中绑定 SOAP1.1 消息的方法,同时使得对 SOAP1.1 消息的处理规则保持不变。MIME 封装复合文档的多组分机制,能够用来绑定与 SOAP1.1 消息相关的实体,如附件。这里详细说明了使用 URI 来引用 MIME 包中实体的规则。
注:这篇文章是我们热心的读者刘海龙翻译的 W3C 站点上发布的 “SOAP Message with Attachments ” 一文,奉献给大家旨在让更多的读者来了解 SOAP,了解 SOAP 消息如何带附件的原理。
引言
SOAP消息有时需要与不同类型的附件一同传输,从法定文书的影印图像到工程图形,这些数据经常是二进制格式。例如,在因特网上传输的图像绝大部分都是GIF或JPEG格式。本文描述一种标准的方法,将SOAP消息与一个或多个附件联系起来,并保留附件的原始格式,作为一个多组分MIME结构来传输。这种方法结合了Multipart/Related MIME媒体类型的特殊用法和在RFC2111、RFC2557中所述的用URI引用MIME组分的方案,以次来实现SOAP消息与相关附件的共同传输。
这里所描述的方法是将多组分MIME结构作为传输协议绑定的一个基本组成部分,也就是说,对于SOAP消息而言,它等同于传输协议报头。多组分结构,尽管这里给出一个确定的名字――SOAP消息包,并不是一个可以明确标识的实体,因为并没有标记来明确地标识它是一个实体。在此有意避免增加新的、基于可辨识标记的实体类型。本文的目的在于表述怎样利用现有的SOAP工具和标准MIME机制来承载和引用附件。换句话来讲,我们用最简单的方法证明了利用现有的技术已经可能实现什么,而不用发明新的东西。对于消息包,更严格的语义需要新的实体类型。这种类型可通过扩展本文所述方法――创建一个新的SOAP头条目来实现,比如可以为消息包中的所有内容建立一个清单。
SOAP消息包
一个SOAP消息包包含一个主体SOAP1.1消息,还可包含附加实体――词法上不在SOAP消息内,却与之相关。这些实体可以包含非XML格式的数据,消息包中的SOAP1.1消息可以引用这些附加的实体,这些附加的实体经常被非正式的称为附件。本部分描述怎样构造SOAP消息包,及SOAP处理器该如何处理他们。
SOAP消息包是通过Multipart/Related(在RFC 2387中定义)媒体类型来构造的,构造规则如下:
- 主体SOAP1.1消息必需处于Multipart/Related结构的根部,因此,Multipart/Related媒体报头的type参数,将总是等于主体SOAP1.1消息的Content-Type头的值,也就是text/xml。
- 被引用的MIME组分,必须包含或者是一个MIME报头Content-ID(遵从RFC 2045),或者是一个MIME报头Content-Location(遵从RFC 2557)。
强烈建议在根部分包含一个MIME头Content-ID(遵从RFC 2045),这样就另需要在Multipart/Related媒体类型的参数中包含start参数。这样能够允许更健壮的错误检测。
符合本规范的SOAP处理器,当接收到SOAP1.1消息(处于Multipart/Related MIME消息的根部)时,必须按照SOAP1.1规范中所定义的规定来处理SOAP消息。特别地,当SOAP处理器接到一条无效的消息时,必须产生如SOAP1.1中4.4.1节所述的客户错误代码。
使用MIME Multipart/Related对SOAP消息进行封装,在语义上等同于一个SOAP协议绑定,SOAP消息本身并不知道它是被封装的。也就是说,在主体SOAP消息的内部没有任何部分指出该SOAP消息是被封装的。
下面的例子是带一个附件的SOAP1.1消息,其中附件的内容是一幅关于已签名索赔单的影印图像(claim061400a.tiff)。
MIME-Version: 1.0
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml; start="<claim061400a.xml@claiming-it.com>"
Content-Description: This is the optional message description.
--MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <claim061400a.xml@claiming-it.com>
<?xml version='1.0' ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
..
<theSignedForm href="cid:claim061400a.tiff@claiming-it.com"/>
..
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
--MIME_boundary
Content-Type: image/tiff
Content-Transfer-Encoding: binary
Content-ID: <claim061400a.tiff@claiming-it.com>
...binary TIFF image...
--MIME_boundary--
|
SOAP对附件的引用
主体SOAP消息中的Header条目和Body元素及其任一级子元素都可引用消息包中的其他实体。本节阐明一种方法,通过使用SOAP和MIME中现有的机制就可实现此功能。
根据SOAP1.1的数据编码规则,一个accessor的值可以通过引用一个href属性的值给出,就像一个资源可以通过URI来引用一样。我们注意到SOAP编码模式允许href属性的值可以是任何的URI,所以该属性不仅可以用来引用SOAP1.1消息中的XML段,还可以引用其他任何资源。
这里给出SOAP1.1中href属性的一种使用方式,使属性值是SOAP消息包中附件(作为MIME的组分)的引用。主体SOAP1.1消息中URI引用的解析过程,基于RFC2557中的部分规定(关于具有text/html根文档的多组分MIME消息)。我们采用这些关于HTML和描述上下文的规则,并将其应用于SOAP1.1消息上下文。另外,我们采用RFC2396中关于相对URI句法及其绝对化规则,而不是已经过时的、RFC2557中使用的RFC1808。
解析的过程分两步进行:先将所有的URI转化为绝对URI,然后解析绝对URI。我们对这两步进行规定。注意,这个处理过程不能应用于RFC2396中4.2节所定义的同文档引用。SOAP1.1的语义特征包括通过使用一个带段标识符的href属性,来引用同一个SOAP1.1消息中的XML元素(基于一个保持不变的标签,由ID属性定义)。
在RFC2396中定义了将相对URI引用转化为绝对引用的过程,很具权威性。关于这个过程,我们需要详细说明的是基础URI的建立。RFC2396中规定了建立基础URI的过程框架,基于下列次序,按优先级排列。
- 基础URI在文档内:一种机制,明确规定在SOAP1.1消息内的基础URI将是XML基础的机制。
- 基础URI来自封装实体:在封装了主体SOAP1.1消息的任何MIME实体中,有包含一个绝对URI的Content-Location报头,那么,最近的Content-Location报头中的URI就是此实体的基础URI。
- 基础URI来自回调URI:为SOAP消息包而回调的URI,不允许被用作基础URI。
- 缺省基础URI:根据RFC2557,如果不能从上面的方法中得到基础URI,本消息的基础URL将是缺省基础URI。
构成SOAP消息包的Multipart/Related结构中,每个MIME组分至少有一个绝对URI标记,由三种情形:
- 如果给出的是一个Content-Location报头并被赋予一个绝对URI,那么这个URI就是此组分的标记。
- 如果给出的是一个Content-Location报头被赋予一个相对URI,那么就用上述规则的2和4来创建基础URI,并据此将相对URI转化为绝对URI。所得的绝对URI便是此组分的标记。
- 如果给出的是一个Content-ID报头,那么此组分的绝对URI标记,将按照RFC2111中所规定的CID URI方案生成。
按如下方式对绝对URI进行解析。对于主体SOAP1.1消息中的每个URI,将其按照上述方式转化为绝对URI后,与Multipart/Related结构中其他组分的绝对URI标记(由Content-ID和Content-Location报头得出)进行比较,比较规则由RFC2396给出。如果发现一个匹配,相应MIME组分中所包含的实体就是被引用的资源。如果没有匹配,就使用正常的、基于URI方案的解析规则。当Content-ID和Content-Location报头的标记发生冲突时,用RFC2557中8.3节的规定加以解决,即使用Content-ID报头值。
第2节的例子说明了在SOAP消息的body元素中使用CID的方法。显然,该例中能够使用远程资源的引用。下面仍是这个例子,但使用了Content-Location报头来标识实体,并用绝对URI来引用实体:
MIME-Version: 1.0
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml;
start="<http://claiming-it.com/claim061400a.xml>"
Content-Description: This is the optional message description.
--MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <http://claiming-it.com/claim061400a.xml>
Content-Location: http://claiming-it.com/claim061400a.xml
<?xml version='1.0' ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
..
<theSignedForm href="http://claiming-it.com/claim061400a.tiff"/>
..
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
--MIME_boundary
Content-Type: image/tiff
Content-Transfer-Encoding: binary
Content-ID: <http://claiming-it.com/claim061400a.tiff>
Content-Location: http://claiming-it.com/claim061400a.tiff
...binary TIFF image...
--MIME_boundary―
|
下面是同一个例子,这次使用了相对URI,并使用MIME Multipart/Related结构基础部分的Content-Location报头的值最为它们的基础URI:
MIME-Version: 1.0
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml;
start="<http://claiming-it.com/claim061400a.xml>"
Content-Description: This is the optional message description.
Content-Location: http://claiming-it.com/
--MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <http://claiming-it.com/claim061400a.xml>
Content-Location: claim061400a.xml
<?xml version='1.0' ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
..
<theSignedForm href="claim061400a.tiff"/>
..
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
--MIME_boundary
Content-Type: image/tiff
Content-Transfer-Encoding: binary
Content-Location: claim061400a.tiff
...binary TIFF image...
--MIME_boundary-- |
最后这个例子使用了相对URI,但并没有明确声明基础URI,这样就会用到规则4来建立一个基础URI。此时,SOAP消息中的相对URI和Content-Location标记都要用到此基础URI:
MIME-Version: 1.0
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml;
start="<b6f4ccrt@15.4.9.92/s445>"
Content-Description: This is the optional message description.
--MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <b6f4ccrt@15.4.9.92/s445>
Content-Location: claim061400a.xml
<?xml version='1.0' ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
..
<theSignedForm href="the_signed_form.tiff"/>
..
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
--MIME_boundary
Content-Type: image/tiff
Content-Transfer-Encoding: binary
Content-ID: <a34ccrt@15.4.9.92/s445>
Content-Location: the_signed_form.tiff
...binary TIFF image...
--MIME_boundary-
|
值得注意的是,在SOAP消息中,作为href属性的值而出现的URI引用,并未暗示接收SOAP处理器必需解析该URI。SOAP处理器可以根据消息的处理语义来决定是否需要解析URI。接收SOAP处理器可以选择忽略该URI,尽管它是用来引用一个MIME附件。相反地,消息包所有的附件也可能均不被SOAP消息所引用。
与SOAP1.1的关系
带附件的SOAP消息包是对SOAP1.1所定义的传输绑定机制的一个扩展。将SOAP1.1消息作为Multipart/Related MIME结构的根组分,与其他内容一同打包,可以看作是通过任何能够传输MIME内容的通信协议,承载SOAP1.1消息的一种特殊方法。SOAP处理器要同时支持MIME编码格式和底层通信协议,并且在处理SOAP1.1消息时,必须遵循SOAP1.1中所有关于消息及底层传输绑定的规定。
HTTP绑定
因为是基于SOAP1.1的,所以这里并不描述异步消息、或同步请求/响应交互模式。这里所讲的HTTP绑定只涉及到在构建SOAP消息包时,HTTP报头与MIME报头之间的关系,而对于交互模式丝毫没有涉及。
在HTTP消息中承载多组分MIME结构的基本方法是:限定用MIME编码的内容于MIME组分内,并在HTTP本身报头中使用Multipart/Related媒体类型。在HTTP消息中包含SOAP消息包的规则如下:
- MIME报头Content-Type:Multipart/Related必须作为一个HTTP报头出现,在第2节中所规定的关于此报头中参数的规定在这里也适用。
- 在MIME规范中定义的其他含义报头(如Content-Transfer-Encoding)不能作为HTTP报头出现。特别是“MIME-Version: 1.0”报头,绝对不能作为HTTP报头出现。注意,在HTTP1.1中定义了许多与MIME类似的报头,有具体的含义。这些报头当然可以自由出现。
- 包含了SOAP消息和附件的各MIME组分,构成了HTTP消息体,并且按第2节中所述的方式表示,包括恰当的MIME报头。
下面的例子是一则HTTP消息,包含一个SOAP消息包,包内含有两个附件构成一则汽车保险索赔。SOAP1.1消息内包含索赔数据,与一个已签署索赔单的影印图像(claim.tiff)和一幅被毁坏汽车的数字照片(car.jpeg)一同发送。
POST /insuranceClaims HTTP/1.1
Host: www.risky-stuff.com
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml;
start="<claim061400a.xml@claiming-it.com>"
Content-Length: XXXX
SOAPAction: http://schemas.risky-stuff.com/Auto-Claim
Content-Description: This is the optional message description.
--MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <claim061400a.xml@claiming-it.com>
<?xml version='1.0' ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<claim:insurance_claim_auto id="insurance_claim_document_id"
xmlns:claim="http://schemas.risky-stuff.com/Auto-Claim">
<theSignedForm href="cid:claim061400a.tiff@claiming-it.com"/>
<theCrashPhoto href="cid:claim061400a.jpeg@claiming-it.com"/>
<!-- ... more claim details go here... -->
</claim:insurance_claim_auto>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
--MIME_boundary
Content-Type: image/tiff
Content-Transfer-Encoding: base64
Content-ID: <claim061400a.tiff@claiming-it.com>
...Base64 encoded TIFF image...
--MIME_boundary
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
Content-ID: <claim061400a.jpeg@claiming-it.com>
...Raw JPEG image..
--MIME_boundary--
|

 |

|
结束语
通过利用SOAP和MIME自身的功能,就能实现SOAP消息与相关实体的绑定,达到一同传输的目的。本文详细介绍了消息格式、对附件的引用方法以及相应SOAP处理器的处理规则,最后给出了SOAP消息包通过HTTP协议传时的具体消息格式。本文所介绍的SOAP消息与附件的绑定方法,适用于各种格式的附件,必将对B2B消息互换产生巨大的促进作用。
参考文献
参考资料 学习
获得产品和技术
-
IBM 试用版软件:使用 IBM 试用版软件构建您的下一个开发项目,这些试用版软件可直接从 developerWorks 下载获得。
讨论
关于作者  | |  | 刘海龙,北航电子工程系通信与信息系统专业博士研究生。主要研究方向:B2B电子商务技术。 |
对本文的评价
|