1 前言
RPC:面向过程,也就是要做一件什么事情,只发送 GET 和 POST 请求;
GET 用来查询信息,其他情况下一律用 POST;请求参数是动词。
RESTful:面向资源,这里的资源可以是一段文字、一个文件、一张图片,总之是一个具体的存在,可以使用 GET、POST、DELETE、PUT 请求,对应了增删查改的操作;请求参数是名词。
比如按照 id 查找用户:
Copy RPC 风格:GET /queryUser?userid=xxx;
RESTful 风格:GET /user/{userid}
2 RPC 风格
RPC 通常包含传输协议和序列化协议,单说传输协议,RPC 可以建立在 TCP 协议之上(比如 Dubbo),也可以建立在 HTTP 协议之上(比如 gRPC);如果是基于数据形式分类,RPC 又可以分成基于二进制、XML 和 JSON 三种;
对于 RPC 来讲,它通常代表 remote procedure call
, 这里我们把它理解成为 WYGOPIAO, 也就是 what you get or post is an operation. 通过这个 RPC 类型,你通过 http 协议暴露出自己的动作以及数据封装。据我所知,通常也没有什么规则可循,但是大致是这样的:
Copy GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata":"another value"
}
3 REST 风格
Copy GET /someresources/anId
PUT /someresources/anId
{"anotherdata":"another value"}
动词 + 宾语
Copy 客户端发出的数据操作指令都是"动词 + 宾语"的结构。
比如,GET /articles 这个命令,GET 是动词,/articles 是宾语。
宾语必须是名词
Copy /getAllCars # 错误
/createNewCar # 错误
/deleteAllRedCars # 错误
/articles # 正确
复数 URL
Copy /articles/2 # 推荐
/article/2 # 不推荐
避免多级 URL, 除了第一级,其他级别都用查询字符串表达。
Copy # 比如获取某个作者的某一类文章
GET /authors/12/categories/2 # 不推荐,不利于扩展,语义也不明确
GET /authors/12?categories=2 # 推荐
# 查询已发布的文章
GET /articles/published # 不推荐
GET /articles?published=true # 推荐
3.1 如何设计为 REST 风格
需要支持 RESTful 规范,则需要支持动态路由
,即 /articles/2
形式,后面的 2 是个动态值
则可以通过如下方式实现
3.1.1 约束
请求路径只有 1 级的 resource,且 URL 结尾不包含斜杠“/”
Copy path="/resources/object/" # 错误
path="/resources/object" # 正确
path="/resources/" # 错误
path="/resources" # 正确
访问 Butterfly 时进行自动去掉末尾的 “/”
3.1.2 分析
获取 resources 和 object
Copy # 去掉 PATH 结尾的斜杠
path = wsgienv.get("PATH_INFO", "/")
if path.endswith("/") and path != "/":
func_name = path[:-1].encode("ascii")
else:
func_name = path.encode("ascii")
resource_name = ''
object_key = ''
# 当 PATH_INFO 为 "/" 时,则 index_slash 为 -1
index_slash = path.find('/', 1)
if index_slash < 0 and len(path) > 1:
resource_name = path[1:]
elif index_slash > 1:
resource_name = path[1:index_slash]
object_key = path[index_slash + 1:]
self.resource_name = resource_name
self.object_key = object_key
实现 api map
Copy 根据 resources+mathod 自动 map 到特定的 package/func_name
3.1.3 抛砖引玉
handler 例子
Copy class Resources(object):
def __init__(self, req, object_key=None)
...
def list(self, arg1=xx):
...
def get(self, arg1=xx):
...
def create(self):
...
def update(self):
...
def delete(self):
...
---------------------------------------------------------------------------
get /app/resources/object ===> 将 object_key 进行初始化,并调用 get 方法
get /app/resources ===> object_key 传 None, 调用 list 方法
post /app/resources/object ===> 将 object_key 进行初始化,并调用 create 方法
等等
4 传送门
Last updated 7 months ago