帶附件的 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 中定義)媒體類型來構造的,構造規則如下:

  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)。

強烈建議在根部分包含一個 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="<[email protected]>"
 Content-Description: This is the optional message description. 
 --MIME_boundary 
 Content-Type: text/xml; charset=UTF-8 
 Content-Transfer-Encoding: 8bit 
 Content-ID: <[email protected]> 
 <?xml version='1.0' ?> 
 <SOAP-ENV:Envelope 
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
 <SOAP-ENV:Body> 
 .. 
 <theSignedForm href="cid:[email protected]"/> 
 .. 
 </SOAP-ENV:Body> 
 </SOAP-ENV:Envelope> 
 --MIME_boundary 
 Content-Type: image/tiff 
 Content-Transfer-Encoding: binary 
 Content-ID: <[email protected]> 
 ...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 的過程框架,基於下列次序,按優先級排列。

  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: 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="<[email protected]/s445>"
 Content-Description: This is the optional message description. 
 --MIME_boundary 
 Content-Type: text/xml; charset=UTF-8 
 Content-Transfer-Encoding: 8bit 
 Content-ID: <[email protected]/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: <[email protected]/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 消息包的規則如下:

  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="<[email protected]>"
 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: <[email protected]> 
 <?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:[email protected]"/> 
 <theCrashPhoto href="cid:[email protected]"/> 
 <!-- ... 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: <[email protected]> 
 ...Base64 encoded TIFF image... 
 --MIME_boundary 
 Content-Type: image/jpeg 
 Content-Transfer-Encoding: binary 
 Content-ID: <[email protected]> 
 ...Raw JPEG image.. 
 --MIME_boundary--

結束語

通過利用 SOAP 和 MIME 自身的功能,就能實現 SOAP 消息與相關實體的綁定,達到一同傳輸的目的。本文詳細介紹了消息格式、對附件的引用方法以及相應 SOAP 處理器的處理規則,最後給出了 SOAP 消息包通過 HTTP 協議傳時的具體消息格式。本文所介紹的 SOAP 消息與附件的綁定方法,適用於各種格式的附件,必將對 B2B 消息互換產生巨大的促進作用。

參考文獻

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章