SOAP 消息有時須要與不一樣類型的附件一同傳輸,從法定文書的影印圖像到工程圖形,這些數據常常是二進制格式。例如,在因特網上傳輸的圖像絕大部分都是 GIF 或 JPEG 格式。本文描述一種標準的方法,將 SOAP 消息與一個或多個附件聯繫起來,並保留附件的原始格式,做爲一個多組分 MIME 結構來傳輸。這種方法結合了 Multipart/Related MIME 媒體類型的特殊用法和在 RFC21十一、RFC2557 中所述的用 URI 引用 MIME 組分的方案,以次來實現 SOAP 消息與相關附件的共同傳輸。html
這裏所描述的方法是將多組分 MIME 結構做爲傳輸協議綁定的一個基本組成部分,也就是說,對於 SOAP 消息而言,它等同於傳輸協議報頭。多組分結構,儘管這裏給出一個肯定的名字―― SOAP 消息包,並非一個能夠明確標識的實體,由於並無標記來明確地標識它是一個實體。在此有意避免增長新的、基於可辨識標記的實體類型。本文的目的在於表述怎樣利用現有的 SOAP 工具和標準 MIME 機制來承載和引用附件。換句話來說,咱們用最簡單的方法證實了利用現有的技術已經可能實現什麼,而不用發明新的東西。對於消息包,更嚴格的語義須要新的實體類型。這種類型可經過擴展本文所述方法――建立一個新的 SOAP 頭條目來實現,好比能夠爲消息包中的全部內容創建一個清單。框架
回頁首異步
一個 SOAP 消息包包含一個主體 SOAP1.1 消息,還可包含附加實體――詞法上不在 SOAP 消息內,卻與之相關。這些實體能夠包含非 XML 格式的數據,消息包中的 SOAP1.1 消息能夠引用這些附加的實體,這些附加的實體常常被非正式的稱爲附件。本部分描述怎樣構造 SOAP 消息包,及 SOAP 處理器該如何處理他們。ide
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)。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 消息中的 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: 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 消息所引用。
帶附件的 SOAP 消息包是對 SOAP1.1 所定義的傳輸綁定機制的一個擴展。將 SOAP1.1 消息做爲 Multipart/Related MIME 結構的根組分,與其餘內容一同打包,能夠看做是經過任何可以傳輸 MIME 內容的通訊協議,承載 SOAP1.1 消息的一種特殊方法。SOAP 處理器要同時支持 MIME 編碼格式和底層通訊協議,而且在處理 SOAP1.1 消息時,必須遵循 SOAP1.1 中全部關於消息及底層傳輸綁定的規定。
由於是基於 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: 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 消息互換產生巨大的促進做用。
參考文獻
[SOAPATTACH] SOAP Messages with Attachments( http://www.w3.org/TR/2000/NOTE-SOAP-p_w_uploads-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)
[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)
[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)