带附件的 SOAP 消息
简介:?
本文介绍了一种在 MIME Multipart/Related 消息中绑定 SOAP1.1 消息的方法,同时使得对 SOAP1.1 消息的处理规则保持不变。MIME 封装复合文档的多组分机制,能够用来绑定与 SOAP1.1 消息相关的实体,如附件。这里详细说明了使用 URI 来引用 MIME 包中实体的规则。
?
引言
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 中定义)媒体类型来构造的,构造规则如下:
强烈建议在根部分包含一个 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 的过程框架,基于下列次序,按优先级排列。
构成 SOAP 消息包的 Multipart/Related 结构中,每个 MIME 组分至少有一个绝对 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 消息包的规则如下:
下面的例子是一则 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 消息互换产生巨大的促进作用。
参考文献
[SOAPATTACH] SOAP Messages with Attachments( http://www.w3.org/TR/2000/NOTE-SOAP-attachments-20001211) [SOAP] Simple Object Access Protocol (SOAP) Version 1.1 (http://www.w3.org/TR/SOAP/)[XML] Extensible Markup Language (XML) 1.0 (http://www.w3.org/TR/1998/REC-xml-19980210)[MultipartRelated] The MIME Multipart/Related Content-type (http://www.ietf.org/rfc/rfc2387.txt)[MIME1] Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies (http://www.ietf.org/rfc/rfc2045.txt)[CID] Content-ID and Message-ID Uniform Resource Locators http://www.ietf.org/rfc/rfc2111.txt[URI] Uniform Resource Identifiers (URI): Generic Syntax (http://www.ietf.org/rfc/rfc2396.txt)[RFC2557] MIME Encapsulation of Aggregate Documents, such as HTML (MHTML) (http://www.ietf.org/rfc/rfc2557.txt)[XMLBASE] XML Base http://www.w3.org/TR/xmlbase[HTTP] Hypertext Transfer Protocol -- HTTP/1.1 (http://www.ietf.org/rfc/rfc2616.txt)[SMTP] Simple Mail Transfer Protocol (http://www.ietf.org/rfc/rfc0821.txt)?
参考资料
学习
developerWorks 中国网站 XML 专区:在 developerWorks XML 专区可以得到更多技术文章、技巧、教程、标准以及 IBM 红皮书。原文:http://www.ibm.com/developerworks/cn/xml/x-soapa/index.html?ca=drs-