帶附件的 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 消息互換產生巨大的促進做用。

參考文獻

相關文章
相關標籤/搜索