HTTP Methods 和 RESTful Service API 设计

转载 2016年08月29日 10:10:12

API 可以说是软件开发者的用户界面,API 设计也是系统架构的重要环节。尤其对复杂和分布式系统而言,其设计的好坏,直接影响着整个系统的设计,实现和演进。一套糟糕的 API 设计也会严重影响使用者(开发人员)的心情和工作效率。如果你对此表示怀疑并且打算进一步了解,可以先阅来自 Goolge 的一位大牛的分享: How to Design a Good API and Why it Matters[1]

本系列的前一篇文章详细介绍了 REST 架构的理论和基础,而我们的最终目标是付诸实践和解决实际工程问题。本文将探讨 RESTful Service API 的一些基本设计方法和套路,包括常见的数据 CRUD API 设计,以及这些 API 应该如何返回信息等等。

文章目录 [显示]

约定和定义

在详细讨论 RESTful Service API 设计之前,我们先来解释和约定几个概念,以方便下文描述。在了解这些概念之前,假设你已经熟悉 HTTP 协议和 REST 架构

  • HTTP Methods
    也叫 HTTP Verbs,HTTP Methods 可以翻译成 HTTP 方法。它们是 HTTP 协议的一部分,主要规定了 HTTP 如何请求和操作服务器上的资源,常见的有GET,POST等。

  • API
    Application Programming Interface 应用程序接口。如果没有特别的说明,本文中提到的 API 均指 RESTful Web Service API 简称 RESTful API。这类API是通过 HTTP 协议 URL 形式暴露给其它系统或者模块调用,比如,一个获得用户所有评论的 API 可能像这样:
    https://api.server-name.com/user-id/comments

使用 HTTP Methods 构建 RESTful API

HTTP Methods 一共有九个,分别是 GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATCH。在RESTful API 设计中,常用的有POST,GET,PUT,PATCH 和 DELETE。分别对应对资源的创建,获取,修改,部分修改和删除操作。下表简单列出了这些Methods的用途和返回值约定。

HTTP Methods 用途一览

这是一个推荐的 Best Practise 和大多数现有 API 所遵守的约定。它本身并不是一个规范和强制标准。遵守约定和套路的好处是可以避免产生方向性问题,也可以让使用的人感觉熟悉而容易上手,否则你可能需要额外的文来解释你的特殊设计。

HTTP Methods 操作方式(CRUD) 获取多个资源(/books)返回结果 获取单个资源(/books/id) 返回结果
POST 创建数据Create 201 (Created) 
HTTP Header 'Location' 值设置为/books/id,其中id为新创建的book id
404 (Not Found), 
如果资源已经存在,返回409 (Conflict)
GET 读取数据Read 200 (OK) 
在Body中返回所有的books,可以使用参数来获取部分books数据如/books?page=3
200 (OK)
在Body中返回对应id的book

404 (Not Found)
如果没有对应数据,或者id格式不对

PUT 修改数据Update

整条修改
修改除ID外的所有属性

404 (Not Found) 
除非该API要实现批量或者全部更新可返回200,否则一般直接返回404即可
200 (OK) 
204 (No Content)
404 (Not Found), 如果id格式不正确或者没有找到
PATCH 修改数据Update

部分修改 
修改一条记录的部分属性

404 (Not Found) 
除非该API要实现批量或者全部更新可返回200,否则一般直接返回404即可
200 (OK) 
204 (No Content)
404 (Not Found), 如果id格式不正确或者没有找到
DELETE 删除数据Delete 404 (Not Found)
一般直接返回404 除非你真的想删除全部集合可返回200
200 (OK)
404 (Not Found) 如果id格式不正确或者没有找到

其中 HEAD,TRACE,OPTIONS,CONNECT 在 RESTful API 设计中不常用,这些 Methods 具体定义可以在这里找到。如果需要,可以根据相关语意来实现具有对应功能的API。

HTTP Methods 使用详细说明

上表列出了 HTTP Methods 和相应 API 的设计概述,下面我们我们分别来看这些方法所对应的 API 设计,具体探讨客户端该如何调用,服务端实现注意事项,以及数据安全和数据幂等性等注意事项。

  1. POST
    使用 POST 的 API 一般用来表示创建一条数据。举例来说,如果要设计一个向后端数据库添加一条关于图书信息等 API,可以设计成:
    https://api.server.com/books

    客户端调用
    客户端把要创建的数据放在HTTP请求的Body中,比如Body数据是

    之后发送 HTTP POST 请求到https://api.server.com/books

    服务端实现
    a) 服务端在收到客户端 POST 来的数据时,根据POST URL,发现应该创建books数据。
    b) 之后获取 body 里面的内容来创建一条新 book 记录并保存,如果一切正常,返回201表示创建成功。
    c) 返回时将 HTTP Header 'Location' 值设置为
    https://api.server.com/books/new-created-book-id
    之后客户端可以获得该条刚创建数据的 Unique ID,方便在需要进一步操作时使用(为什么需要返回这个 Unique ID 可以参见RESTful Web Service 架构剖析 约定6.2 Resource Identifiers)

    值得注意的是 POST API 不是一个数据安全和幂等性[2]操作,如果客户端多次调用同样的 API 会导致多条数据被创建,这些数据除了 ID 不同其他属性都相同。

    API举例
    POST https://api.server.com/books
    POST https://api.server.com/books/123456/comments

  2. GET
    GET 操作一般用于读取数据,即获取资源。成功调用 GET API 会返回相应的数据。如果请求的数据不存在可返回404(Not Found)或者由于参数不正确的原因可以返回400(Bad Request)

    客户端调用
    客户端只要简单发送一个 HTTP GET 请求到相应的 URL 即可,请求URL 中可以带上有关参数用来对数据进行条件过滤,如:
    GET https://api.server.com/books?author=gause

    服务端实现
    服务端在收到相应的请求之后根据 URL 判断应该返回什么类型的数据,并且根据 URL 参数对数据进行过滤后在放在 Body 中返回给客户端。GET 可以返回一个集合,类似数组的形式。比如返回的数据可能是这样的:

    如果客户端只请求一条数据 GET https://api.server.com/books/000
    应该返回对应ID的数据即可:

    注意,这里返回的数据格式仅用于举例,实际格式可以根据不同的需求可能差别很大。

    GET操作是数据安全和具有幂等性的操作,也就是多次调用GET应该返回相同的数据(期间没有修改操作的前提下),并且不会导致任何数据的破坏性修改。

    API举例
    GET https://api.server.com/books/123456
    GET https://api.server.com/books/123456/comments
    GET https://api.server.com/books/123456/comments/id001
    GET https://api.server.com/books?author=gause

  3. PUT
    PUT 一般用来更新记录,和 PATCH 不同的是,PUT 一般用于替换该记录的所有属性。PATCH 只是部分更新。和 POST 不同的是,PUT 不会生成新的资源 ID,而 POST 会生成并且返回新创建的数据 ID

    客户端调用
    和 POST 调用方式几乎相同,比如要修改的数据是

    客户端发送 HTTP PUT 请求到https://api.server.com/books。和POST不同的是,该操作会带上数据的 UID,这样我们才能知道具体修改的是哪一条数据。
    也有的设计会把ID放在URL中https://api.server.com/books/book-id-000,这样要修改的Body中的数据可以不用包含ID

    服务端实现
    如果更新成功 PUT API 应该返回200。如果 PUT 请求的 body 中没有任何信息则返回204, 如果id没有找到或id格式不正确,返回404。和POST不同的是该 API 没有必要在Header中更新刚创建数据ID URL,因为我们是在修改该条数据,其 ID 之前已经被客户的获取。

    PUT 操作不是数据安全的,因为这个操作改变了数据,但是PUT操作是幂等性的,对于相同的PUT请求,无论调用多少次,造成的数据修改的结果永远和调第一次时相同。

    API举例
    PUT https://api.server.com/books/123456
    PUT https://api.server.com/books/123456/comments/id001

  4. PATCH
    PATCH 操作只更新部分数据,比如有这么一条数据
    {id:000, title: "Are your lights on", author: "Donald C. Gause", pub:"xyz"}
    PATCH 操作可能只是修改 title,或者修改 pub,具体修改的内容由body 里面的数据格式规定。而 PUT API 中 body 数据一般是要替换所有数据的属性(除了ID以外)。

    客户端调用
    和 PUT 不同的只是 Body 的数据格式,PUT 请求的 Body 一般是这样的
    {title: "Are your lights on"} 只包含部分要修改的数据。

    服务端实现
    服务端根据 Body 的内容对该条数据进行部分更新。成功更新数据应该返回200,当数据 ID 没有找到返回404。

    注意 PATCH 操作其实不是幂等性操作,也不是数据安全的,来自不同的客户端的 PATCH 请求可能让数据部分属性相互覆盖和冲突。PATCH的幂等性可能不是很好理解,举例来说明:
    假设第一个PATCH 请求A 操作导致 book 数据修改成
    {id:000, title: "AAA", author: "AAA", pub:"xyz"}
    这时候如果其他客户端一个发出一个 PATCH 请求B 将数据改成
    {id:000, title: "AAA", author: "AAA", pub:"BBB"}
    如果此时重复调用 请求A,虽然要修改的数据部分属性是相同的,但对于整条数据本身而言,已经和第一次调用结束时不完全相同了。不像PUT操作,整个修改之后不会造成数据有部分不相同的情况,PUT请求即使在多次相同的调用期间,其他客户端修改了数据,最后一次调用之后和第一次调用之后数据依然相同。

    API举例
    PATCH https://api.server.com/books/123456
    PATCH https://api.server.com/books/123456/comments/id001
    注意这些 API URL 形式和 PUT API 没有区别,不同的只是 BODY 部分数据不同。

  5. DELETE
    DELETE 应该很好理解,和其字面意义一样,用来删除一条数据。

    正确删除后应该返回200,如果要删除的资源ID不存在则返回404
    DELETE 在HTTP 协议语义中是幂等性的,无论调用多少次之后,该数据都是同样的被删除状态。
    虽然第一次调用的结果(200)和之后的调用的结果(数据已经不存在会返回404)有所不同,但数据本身没有变化,对数据而言,它依然具有幂等性。
    不过,如果服务端维护了一些统计数据,就会破坏幂等性,因为DELETE导致了统计数据的减少。

    API 举例
    DELETE https://api.server.com/books/123456
    DELETE https://api.server.com/books/123456/comments/id001

结束语

本来打算在本篇文章中讨论一些关于“常用问题解决方案和最佳工程实践(Best Practices)”这类更加贴近实际操作层面的内容,不过写着写着发现本篇内容已经足够多了。为了降低读者理解负担和限于篇幅,打算另写一篇文章。下一篇主要是对这篇文章 Best Practices for Designing a Pragmatic RESTful API 进行翻译和总结,敬请期待。

参考文档


[1]:原始链接在这里: http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/32713.pdf,须自备梯子 ↩︎

[2]:幂等性是指一次和多次请求某一个资源应该具有同样的副作用, 具体可参见https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html 或者http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html ↩︎

 本文转自《http://www.macode.net/http-methods-and-restful-service-api-design/》,感谢作者分享!

版权声明
本博客所有文章皆为原创,作者保留所有版权。转载必须保证全文完整和包含本声明,并以超链接形式注明出处 http://www.macode.net/http-methods-and…rvice-api-design/

举报

相关文章推荐

跟着 Github 学习 Restful HTTP API 设计

近几年提供 HTTP API 服务的公司越来越多,许多公司都把 API 作为产品重要的一部分,作为服务提供出去。而微服务的兴起,也让企业内部开始重视和频繁使用 HTTP API 。好的 HTTP AP...

BE - 唠叨下 Restful 与 RPC-JSON 基于HTTP的API接口设计

本篇文章不涉及 XML 接口数据内容 : rpc-xml 啰嗦最近在写关于restful相关接口,学习之后,发现与之前所了解到的接口不大一样。从接触移动开发以来均是rpc-json方式进行开发,比如...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

通过HTTP RESTful API 操作elasticsearch搜索数据

样例数据集这是编造的JSON格式银行客户账号信息文档,文档schema如下: { “account_number”: 0, “balance”: 16623, “fir...

基于 springMVC 的 RESTful HTTP API 实践(服务端)

理解 RESTREST(Representational State Transfer),中文翻译叫“表述性状态转移”。是 Roy Thomas Fielding 在他2000年的博士论文中提出的。...
  • bhuds
  • bhuds
  • 2017-06-29 01:28
  • 176

http协议、Web架构, RESTFUL API及互联网应用的工作原理

http协议 该Restful API的设计特点, 主要由以下几方面来描述.   1). URL的设计 1 http[s]://{server}/rest/2.0/{pro...

使用C#开发HTTP服务器系列之构建RESTful API

各位朋友大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是http://qinyuanpei.com。到目前为止,“使用C#开发HTTP服务器”这个系列系列文章目前已经接近尾声了,虽然我们在服务...

http接口、api接口、RPC接口、RMI、webservice、Restful等概念

http接口:基于HTTP协议的开发接口.这个并不能排除没有使用其他的协议。         api接口:API(Application Programming Interface)应用程序编程接口...

通过HTTP RESTful API 操作elasticsearch文档

Elasticsearch提供近乎实时的数据操作和搜索能力。 当创建、修改、删除索引中数据后,检索数据后能有一秒左右的延迟。索引elasticsearch 是不同于像其他平台的SQL,一个事务操作结...

通用查询引擎Restful service设计(目前支持hive,shark)

最近在设计开发一个通用查询Restful Service (https://github.com/lalaguozhe/polestar-1) ,名字叫polestar (中文名叫北极星,野营灯,指导...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)