[From HTTP to AWS][3] Web Services: XMLRPC/SOAP/RESTful

· Types

XMLRPC – SOAP RPC – RESTful RPC

本文将以代码、Request和Response三个不同的视角来分析三种不同的RPC方式。

· XMLRPC/JSONRPC(宝莱坞)

这是Leonard Richardson之《Restful Web Services》一书中的例子。

An example in Ruby:

#!/usr/bin/ruby -w

# xmlrpc-upc.rb

require 'xmlrpc/client'

def find_product(upc)

server = XMLRPC::Client.new2('http://www.upcdatabase.com/rpc')

begin

response = server.call('lookupUPC', upc)

rescue XMLRPC::FaultException => e

puts "Error: "

puts e.faultCode

puts e.faultString

end

end

puts find_product("001441000055")['description']

# "Trader Joe's Thai Rice Noodles"

Rewrite in Python:

#!/usr/bin/python

import xmlrpclib

def find_product(upc):

server = xmlrpclib.ServerProxy('http://www.upcdatabase.com/rpc')

result = server.lookupUPC(upc)

if type(result) == dict:

if result['found']:

return result['description']

else:

return result['message']

return ""

print find_product("001441000055")

# Trader Joe's Thai Rice Noodles

Request:

<?xml version="1.0" ?>

<methodCall>

<methodName>lookupUPC</methodName>

<params>

<param><value><string>001441000055</string></value></param>

</params>

</methodCall>

Response:

HTTP/1.1 200 OK

Date: Mon, 16 Aug 2010 13:49:58 GMT

Server: Apache

Vary: Accept-Encoding

Connection: close

Content-Type: text/xml

<?xml version="1.0"?>

<methodResponse>

<params>

<param><value><struct>

<member><name>upc</name><value><string>001441000055</string></value>

</member>

<member><name>pendingUpdates</name><value><int>0</int></value>

</member>

<member><name>isCoupon</name><value><boolean>0</boolean></value>

</member>

<member><name>ean</name><value><string>0001441000055</string></value>

</member>

<member><name>issuerCountryCode</name><value><string>us</string></value>

</member>

<member><name>found</name><value><boolean>1</boolean></value>

</member>

<member><name>description</name><value><string>Trader Joe's Thai Rice Noodles</string></value>

</member>

<member><name>size</name><value><string>12 oz.</string></value>

</member>

<member><name>message</name><value><string>Database entry found</string></value>

</member>

<member><name>issuerCountry</name><value><string>United States</string></value>

</member>

<member><name>lastModified</name><value><string>2006-10-01 18:11:27</string></value>

</member>

<member><name>upce</name><value><string>00144155</string></value>

</member>

</struct></value>

</param>

</params>

</methodResponse>

· SOAP RPC(好莱坞)

In actual, SOAP is not just about HTTP. It’s also about SMTP and some other protocols.

The reason why it’s based on HTTP is just for pass through firewall.

下面这个例子调用ChinaStock的SOAP API,获得沪深股市某只股票的行情。其实好多基金网站和股票行情网站都是这样干的。

// 61.147.124.120

//

class SoapQuery

{

public static string GetSource()

{

return "http://www.webxml.com.cn/WebServices/ChinaStockWebService.asmx";

}

// getStockInfo

//

public static string GetStockInfo(string code)

{

ChinaStockWebService.cn.com.webxml.www.ChinaStockWebService oService = new ChinaStockWebService.cn.com.webxml.www.ChinaStockWebService();

string[] info_byte = oService.getStockInfoByCode(code);

string strInfo = "";

foreach (string strLine in info_byte)

{

strInfo = strInfo + "\n" + strLine;

}

return strInfo;

}

// Save Stock Image to local file

//

public static void GetStockImage(string code, string filename)

{

ChinaStockWebService.cn.com.webxml.www.ChinaStockWebService oService =

new ChinaStockWebService.cn.com.webxml.www.ChinaStockWebService();

byte[] image_bytes = oService.getStockImageByteByCode(code);

Image image = CovertUtil.byteArrayToImage(image_bytes);

image.Save(filename);

}

};

运行结果

image

Request

// Request from CommView HTTP Analyzer

POST /WebServices/ChinaStockWebService.asmx HTTP/1.1

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.3603)

VsDebuggerCausalityData: uIDPowOEuUJZbqRJtxAFcA/WSHkAAAAA1gzbkv7ONEGsZ5se4/oaBJ00bq++H01LmgVGJKWdaA4ACQAA

Content-Type: text/xml; charset=utf-8

SOAPAction: "http://WebXml.com.cn/getStockInfoByCode"

Host: www.webxml.com.cn

Content-Length: 354

Expect: 100-continue

Connection: Keep-Alive

HTTP/1.1 100 Continue

xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><getStockInfoByCode xmlns="http://WebXml.com.cn/"><theStockCode>sh000001</theStockCode></getStockInfoByCode></soap:Body></soap:Envelope>

Response

// Response from CommView HTTP Analyzer

HTTP/1.1 200 OK

Date: Mon, 16 Aug 2010 07:44:34 GMT

Server: Microsoft-IIS/6.0

X-Powered-By: ASP.NET

X-AspNet-Version: 2.0.50727

Cache-Control: private, max-age=0

Content-Type: text/xml; charset=utf-8

Content-Length: 832

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><getStockInfoByCodeResponse xmlns="http://WebXml.com.cn/"><getStockInfoByCodeResult><string>sh000001</string><string>上证指数</string><string>2010-08-16 15:03:09</string><string>2661.708</string><string>2606.700</string><string>2603.792</string><string>55.01</string><string>2596.771</string><string>2665.314</string><string>2.11%</string><string>1258628.23</string><string>13073685.1353</string><string /><string /><string /><string /><string /><string /><string /><string /><string /><string /><string /><string /><string /></getStockInfoByCodeResult></getStockInfoByCodeResponse></soap:Body></soap:Envelope>

· RESTful RPC(原生态)

{code}

// 60.28.0.266

//

class RESTfulQuery

{

public static string GetSource()

{

       return "http://hq.sinajs.cn";

}

public static string GetStockInfo(string code)

{

       string uri = "http://hq.sinajs.cn/list=" + code;

       HttpWebRequest request = CreateWebRequest(uri);

       //request.TransferEncoding = "GBK";

       HttpWebResponse response = (HttpWebResponse)request.GetResponse();

       StreamReader responsestream = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("GBK"));

       return responsestream.ReadToEnd();

}

// Save Stock Image to local file

public static void GetStockImage(string code, string filename)

{

    string uri = "http://image.sinajs.cn/newchart/daily/n/" + code + ".gif";

    try

    {

        HttpWebRequest request = CreateWebRequest(uri);

       HttpWebResponse response = (HttpWebResponse)request.GetResponse();

       Image image = Image.FromStream(response.GetResponseStream());

       image.Save(filename);

}

catch (Exception e)

{

       MessageBox.Show("Failed to query Stock infromation");

       filename = "";

}

}

public static HttpWebRequest CreateWebRequest(string uri)

{

       return (HttpWebRequest)WebRequest.Create(uri);

}

};

运行结果

image

Request

// Request from Commview HTTP Analyzer

GET /list=sh000001 HTTP/1.1

Host: hq.sinajs.cn

Response

//Response from CommView HTTP Analyzer

HTTP/1.1 200 OK

Cache-Control: no-cache

Content-Length: 164

Connection: Keep-Alive

Content-Type: application/x-javascript; charset=GBK

var hq_str_sh000001="ÉÏÖ¤Ö¸Êý,2603.792,2606.700,2661.708,2665.314,2596.771,0,0,125862823,130736851353,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2010-08-16,15:03:09";

RESTful方式的架构意味着方法信息体现在HTTP方法里;

XMLRPC and SOAP, all requests are based on POST method.

An interesting example of AWS is that Amazon called non-SOAP API as Query API, not RESTful API.

在Leonard的书中提到了ROA;它则表明作用域信息存在于URI内;

对于一个基于ROA的RESTful Web Service,我们应该从URI就能基本了解客户端的请求,而HTTP Request部分,则定义了方法的具体信息。

可能的Representation Format: XML, JSON, ATOM Publish, XHTML..

posted on 2011-04-10 00:30  飘行天下  阅读(674)  评论(0编辑  收藏  举报

导航