带附件的 SOAP 消息

引言

SOAP 消息有时须要与不一样类型的附件一同传输,从法定文书的影印图像到工程图形,这些数据常常是二进制格式。例如,在因特网上传输的图像绝大部分都是 GIF 或 JPEG 格式。本文描述一种标准的方法,将 SOAP 消息与一个或多个附件联系起来,并保留附件的原始格式,做为一个多组分 MIME 结构来传输。这种方法结合了 Multipart/Related MIME 媒体类型的特殊用法和在 RFC21十一、RFC2557 中所述的用 URI 引用 MIME 组分的方案,以次来实现 SOAP 消息与相关附件的共同传输。html

这里所描述的方法是将多组分 MIME 结构做为传输协议绑定的一个基本组成部分,也就是说,对于 SOAP 消息而言,它等同于传输协议报头。多组分结构,尽管这里给出一个肯定的名字―― SOAP 消息包,并非一个能够明确标识的实体,由于并无标记来明确地标识它是一个实体。在此有意避免增长新的、基于可辨识标记的实体类型。本文的目的在于表述怎样利用现有的 SOAP 工具和标准 MIME 机制来承载和引用附件。换句话来说,咱们用最简单的方法证实了利用现有的技术已经可能实现什么,而不用发明新的东西。对于消息包,更严格的语义须要新的实体类型。这种类型可经过扩展本文所述方法――建立一个新的 SOAP 头条目来实现,好比能够为消息包中的全部内容创建一个清单。框架


SOAP 消息包

一个 SOAP 消息包包含一个主体 SOAP1.1 消息,还可包含附加实体――词法上不在 SOAP 消息内,却与之相关。这些实体能够包含非 XML 格式的数据,消息包中的 SOAP1.1 消息能够引用这些附加的实体,这些附加的实体常常被非正式的称为附件。本部分描述怎样构造 SOAP 消息包,及 SOAP 处理器该如何处理他们。ide

SOAP 消息包是经过 Multipart/Related(在 RFC 2387 中定义)媒体类型来构造的,构造规则以下:工具

  1. 主体 SOAP1.1 消息必需处于 Multipart/Related 结构的根部,所以,Multipart/Related 媒体报头的 type 参数,将老是等于主体 SOAP1.1 消息的 Content-Type 头的值,也就是 text/xml。编码

  2. 被引用的 MIME 组分,必须包含或者是一个 MIME 报头 Content-ID(听从 RFC 2045),或者是一个 MIME 报头 Content-Location(听从 RFC 2557)。code

强烈建议在根部分包含一个 MIME 头 Content-ID(听从 RFC 2045),这样就另须要在 Multipart/Related 媒体类型的参数中包含 start 参数。这样可以容许更健壮的错误检测。orm

符合本规范的 SOAP 处理器,当接收到 SOAP1.1 消息(处于 Multipart/Related MIME 消息的根部)时,必须按照 SOAP1.1 规范中所定义的规定来处理 SOAP 消息。特别地,当 SOAP 处理器接到一条无效的消息时,必须产生如 SOAP1.1 中 4.4.1 节所述的客户错误代码。xml

使用 MIME Multipart/Related 对 SOAP 消息进行封装,在语义上等同于一个 SOAP 协议绑定,SOAP 消息自己并不知道它是被封装的。也就是说,在主体 SOAP 消息的内部没有任何部分指出该 SOAP 消息是被封装的。htm

下面的例子是带一个附件的 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: p_w_picpath/tiff 
 Content-Transfer-Encoding: binary 
 Content-ID: <claim061400a.tiff@claiming-it.com> 
 ...binary TIFF p_w_picpath... 
 --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 的过程框架,基于下列次序,按优先级排列。

  1. 基础 URI 在文档内:一种机制,明确规定在 SOAP1.1 消息内的基础 URI 将是 XML 基础的机制。

  2. 基础 URI 来自封装实体:在封装了主体 SOAP1.1 消息的任何 MIME 实体中,有包含一个绝对 URI 的 Content-Location 报头,那么,最近的 Content-Location 报头中的 URI 就是此实体的基础 URI。

  3. 基础 URI 来自回调 URI:为 SOAP 消息包而回调的 URI,不容许被用做基础 URI。

  4. 缺省基础 URI:根据 RFC2557,若是不能从上面的方法中获得基础 URI,本消息的基础 URL 将是缺省基础 URI。

构成 SOAP 消息包的 Multipart/Related 结构中,每一个 MIME 组分至少有一个绝对 URI 标记,由三种情形:

  1. 若是给出的是一个 Content-Location 报头并被赋予一个绝对 URI,那么这个 URI 就是此组分的标记。

  2. 若是给出的是一个 Content-Location 报头被赋予一个相对 URI,那么就用上述规则的 2 和 4 来建立基础 URI,并据此将相对 URI 转化为绝对 URI。所得的绝对 URI 即是此组分的标记。

  3. 若是给出的是一个 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: p_w_picpath/tiff 
 Content-Transfer-Encoding: binary 
 Content-ID: <http://claiming-it.com/claim061400a.tiff> 
 Content-Location: http://claiming-it.com/claim061400a.tiff 
 ...binary TIFF p_w_picpath... 
 --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: p_w_picpath/tiff 
 Content-Transfer-Encoding: binary 
 Content-Location: claim061400a.tiff 
 ...binary TIFF p_w_picpath... 
 --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: p_w_picpath/tiff 
 Content-Transfer-Encoding: binary 
 Content-ID: <a34ccrt@15.4.9.92/s445> 
 Content-Location: the_signed_form.tiff 
 ...binary TIFF p_w_picpath... 
 --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 消息包的规则以下:

  1. MIME 报头 Content-Type:Multipart/Related 必须做为一个 HTTP 报头出现,在第 2 节中所规定的关于此报头中参数的规定在这里也适用。

  2. 在 MIME 规范中定义的其余含义报头(如 Content-Transfer-Encoding)不能做为 HTTP 报头出现。特别是“MIME-Version: 1.0”报头,绝对不能做为 HTTP 报头出现。注意,在 HTTP1.1 中定义了许多与 MIME 相似的报头,有具体的含义。这些报头固然能够自由出现。

  3. 包含了 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: p_w_picpath/tiff 
 Content-Transfer-Encoding: base64 
 Content-ID: <claim061400a.tiff@claiming-it.com> 
 ...Base64 encoded TIFF p_w_picpath... 
 --MIME_boundary 
 Content-Type: p_w_picpath/jpeg 
 Content-Transfer-Encoding: binary 
 Content-ID: <claim061400a.jpeg@claiming-it.com> 
 ...Raw JPEG p_w_picpath.. 
 --MIME_boundary--

结束语

经过利用 SOAP 和 MIME 自身的功能,就能实现 SOAP 消息与相关实体的绑定,达到一同传输的目的。本文详细介绍了消息格式、对附件的引用方法以及相应 SOAP 处理器的处理规则,最后给出了 SOAP 消息包经过 HTTP 协议传时的具体消息格式。本文所介绍的 SOAP 消息与附件的绑定方法,适用于各类格式的附件,必将对 B2B 消息互换产生巨大的促进做用。

参考文献

相关文章
相关标签/搜索