xml-rpc整理 (XML remote procedure call) – spec

這篇整理的spec是以 http://xmlrpc.com/spec.md 為參考

在一開始spec說明xml-rpc是Remote Procedure Calling protocol,可以理解成call – return的communication pattern,而HTTP本身的protocol就是request – response,可以非常直覺地直接對應到procedure call的pattern。

spec主要就是在這樣的通訊架構下,定義資料傳輸的交換格式,並且以xml為資料格式的基底。

以前一篇is_even的例子來看 client送出的xml

<?xml version="1.0"?>
<methodCall>
    <methodName>is_even</methodName>
    <params>
        <param>
            <value>
                <int>3</int>
            </value>
         </param>
    </params>
</methodCall>

在http部分 採用POST (送出xml body),spec要求User-Agent、Host  header field must be required. 值得注意的是 header Host 在HTTP/1.1是required,在HTTP/1.0則沒有要求,nodejs client送出的header sample如下,其中Content-Length是通過計算xml body size得到(在nodejs中,如果不先算好content-length,使用stream write,會導致chunked mode transfer,這部分可能會導致server不相容,因為spec中有寫到: The Content-Length must be specified and must be correct. )

POST / HTTP/1.1
User-Agent: NodeJS XML-RPC Client
Content-Type: text/xml
Accept: text/xml
Accept-Charset: UTF8
Connection: Keep-Alive
Content-Length: 137
Host: 127.0.0.1:8090

在URL的endpoint,沒有特別規定,方便整進http server,這樣一台http server就可以同時提供不同類型的服務,範例中是使用 / 來做處理

The <methodCall> must contain a <methodName> sub-item 其中的methodName有要求charset: The string may only contain identifier characters, upper and lower-case A-Z, the numeric characters, 0-9, underscore, dot, colon and slash. It’s entirely up to the server to decide how to interpret the characters in a methodName.

這邊說明,methodName的字元集限制,以及server端可以自行決定如何解釋 methodName,這邊指的自行決定是指server端背後的實作(如何進行背後的function call),從介面的角度來看,並不影響client-server的相容性,只要server提供出他有哪些methodName以及需要的parameters即可

在params的定義,包含了參數型別,scalar value type不包含參數名

<i4> <int>:	four-byte signed integer
<boolean> 0 (false) or 1 (true)	
<string>
<double> double-precision signed floating point number
<dateTime.iso8601>	date/time	19980717T14:08:55
<base64>
<params>
    <param>
        <value>
            <int>3</int>
        </value>
     </param>
</params>

可以看到上面 3本身就只有描述param, value, int

因為是remote procedure call,所以概念上基本上可以用程式語言裡的function call來理解,在function call param中,arguments是帶有型別的(即使是Javascript,雖然是dynamic typing,但argument還是有type)

在描述複雜結構,xmlrpc定義了struct / array,struct可理解為JSON的object: key value pair,array即是array of <value>, An <array> contains a single <data> element, which can contain any number of <value>s.

可以參考下面的範例

<?xml version="1.0"?>
<methodCall>
<methodName>test</methodName>
<params>
<param>
    <value>
        <struct>
        <member><name>a</name><value><int>1</int></value></member>
        <member><name>b</name><value><string>2</string></value></member>
        <member>
            <name>c</name>
            <value>
            <array>
            <data>
            <value><double>3.3</double></value>
            <value><string>hello</string></value>
            <value><boolean>1</boolean></value>
            </data>
            </array>
            </value>
        </member>
        </struct>
    </value>
</param>
</params>
</methodCall>

上面的範例用JSON表示如下

{
    "a": 1,
    "b": "2",
    "c": [3.3, "hello", true]
}

其中可以看到 a, b, c在xml的struct member中, 型態分別是int, string,c的型態則是array,array中包含了3個value,分別是double, string, boolean型態。我們也可以發現JSON表示法相較於XML簡潔許多,甚至更human readable

另外,從設計的角度dateTime.iso8601 & base64都可以視為string的一種擴展,這有點像是JSON vs BSON,BSON基於JSON之上定義了許多型態擴展,像是binary data, date, regex, undefined, objectId等。當然所有的型態,最終都可以表示成string (serialization),定義哪些基本型別是牽涉到設計的哲學和藝術

再來看xmlrpc response,以下是 is_even的response,body的內容規則和request很像,差別只是methodResponse,以及error case的判斷,正常情況回傳<params>,錯誤發生時回傳<fault>

<?xml version='1.0'?>
<methodResponse>
<params>
<param>
<value><boolean>1</boolean></value>
</param>
</params>
</methodResponse>

另外我故意傳入錯誤的參數型態,產生<fault> 和 faultString

<?xml version='1.0'?>
<methodResponse>
<fault>
<value><struct>
<member>
<name>faultString</name>
<value><string><class 'TypeError'>:unsupported operand type(s) for %: 'dict' and 'int'</string></value>
</member>
<member>
<name>faultCode</name>
<value><int>1</int></value>
</member>
</struct></value>
</fault>
</methodResponse>

上面的fault用JSON表示

{
    "faultString": "<class 'TypeError'>:unsupported operand type(s) for %: 'dict' and 'int'",
    "faultCode": 1
}

在spec中提到 Unless there’s a lower-level error, always return 200 OK. 這邊指的是 例如404, 500這種server context error response,否則一律回應200,錯誤的解析則由xml body parse處理

以上就是xmlrpc的介紹,後續有機會再整理JSON-RPC

This entry was posted in Network. Bookmark the permalink.

Leave a Reply