RESTful 标准接口教程

如何写漂亮的 API 接口


第 1 章 了解 HTTP 协议

1.1 前言

我们现实生活中的协议是指相互遵守的规定,单方面违背,协议不成立。

而在互联网交互的过程中,也存在这许多协议,例如 FTP、HTTP、STMP、TCP/IP 等。

而 HTTP 协议则是 web 服务器 web 客户端达成的一种可靠的数据传输协议,通过 HTTP 可以从遍布全世界的 Web 服务器上将 JPEG 图片,HTML 页面,文本文件,MPEG 电影,WAV 音频文件和其他资源信息块迅速、便捷、可靠地搬移到人们桌面上的 Web 浏览器上去。它能够确保数据在传输的过程当中不会损坏或者产生混乱。这样,对用户来说是个好事,同样对 Internet 应用的开发人员来说也是一件好事。因为我们在开发过程中也不需要担心自己的页面和数据会在传输过程中发生破坏和畸变了。

1.2 WEB客户端和服务器

Web 内容都是存储在 Web 服务器上的。Web 服务器所使用的是 HTTP 协议,因此经常会被称为 HTTP 服务器。这些 HTTP 服务器存储了因特网中的数据,如果 HTTP 客户端发出请求的话,它们会提供数据。客户端向服务器发送 HTTP 请求,服务器会在 HTTP 响应中回送所请求的数据。

那么一次请求和响应的过程中发生了什么?
客户端与服务器之间的请求和响应图

HTTP 属于无状态链接协议,即是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间和服务器资源。

当然也有有状态连接,那就是我们常用的 QQ。H5 新增的特性中也包含 Websocket 帮助我们构建长链接。

1.3 资源和媒体类型

web 服务器是 web 资源的宿主,而 web 资源就是我们常见的 web 内容的源头,最简单的 web 资源就是我们服务器中的静态文件:文本文件,HTML 文档,JPEG 图片文件,AVI 文件等等。

当然 web 资源也可以是动态生成的,类似搜索引擎生成的页面,QQ 空间的动态等,总之,所有类型的内容来源都是资源。

因特网上有数千种不同类型的数据类型,HTTP 在传输的过程中为每个传输的数据都打上了名为 MIME 类型的数据类型标签,描述并标记多媒体内容。

MIME类型识别

web 浏览器请求一个网站的时候往往会发布多个 HTTP 请求,比如我们在浏览一个具有丰富图片的的 web 页面的时候,浏览器会执行一次 HTTP 请求来获取描述页面布局的 HTML,然后发布另外的请求来获取每个嵌入式的图片,这些图片甚至可能位于不同的服务器上。因此,一个 web 页面通常不是单个资源,而是一组资源的集合。

web 服务器会为所有的 HTTP 对象数据附加一个 MIME 类型,当浏览器从服务器中取回一个对象的时候,会查看相关的 MIME 类型。看看它是否知道应该如何处理这个对象。对象的类型写在响应的 content-type 头中;同样,请求的时候浏览器也会告知服务器请求数据类型。

常见的 MIME 类型:

  • HTML 格式的文本文档由 text/html 类型来标记。

  • 普通的 ASCII 文本文档由 text/plain 类型来标记。

  • JPEG 格式的图片为 image/jpeg 类型。

  • GIF 格式的图片为 image/gif 类型。

以 application 开头的媒体格式类型:

  • application/xhtml+xml :XHTML 格式
  • application/xml :XML 数据格式
  • application/atom+xml:Atom XML 聚合格式
  • application/json:JSON 数据格式
  • application/octet-stream:二进制流数据(如常见的文件下载)
  • application/x-www-form-urlencoded<form encType=''>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
  • multipart/form-data:需要在表单中进行文件上传使用的数据格式。

MIME 参考手册:W3school MINE类型

1.4 URL

统一资源定位符(Uniform Resource Locator)是资源标识符最常见的形式。URL 描述了一台特定服务器上某资源的特定位置。它们可以明确说明如何从一个精确、固定的位置获取资源。

互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

大部分 URL 都遵循一种标准格式, 这种格式包含三个部分。

  • URL 的第一部分被称为方案(scheme), 说明了访问资源所使用的协议类型。 这部
    分通常就是 HTTP 协议(http://)。

  • 第二部分给出了服务器的因特网地址(比如,http://www.itheima.com)。

  • 其余部分指定了 Web 服务器上的某个资源(比如, /static/image/common/zixuelogo.png)。

URL 可以更为细致的进行划分。

扩展:URI、URL、URN 的区别

URI = Uniform Resource Identifier 统一资源标志符
URL = Uniform Resource Locator 统一资源定位符
URN = Uniform Resource Name 统一资源名称

翻译成人话: URI 是抽象的定义,不管用什么方法表示,只要能定位一个资源,就叫 URI,本来设想的的使用两种方法定位。
1)URL 用地址定位
2)URN 用名称定位

举个例子:去村子找个具体的人(URI)。如果用地址:某村多少号房子第几间房的主人就是 URL, 如果用身份证号 + 名字,去找就是 URN 了。

目前 WEB 上就 URL 流行开了,平常见得 URI 基本都是 URL。
URI、URL、URN 的区别

扩展:HTTP 和 HTTPS 协议的区别

1)HTTP 和 HTTPS 的相同点

大多数情况下,HTTP 和 HTTPS 是相同的,因为都是采用同一个基础的协议,作为 HTTP 或 HTTPS 客户端——浏览器,设立一个连接到 Web 服务器指定的端口。当服务器接收到请求,它会返回一个状态码以及消息,这个回应可能是请求信息、或者指示某个错误发送的错误信息。系统使用统一资源定位器 URI 模式,因此资源可以被唯一指定。而 HTTPS 和 HTTP 唯一不同的只是一个协议头(https)的说明,其他都是一样的。

2)HTTP 和 HTTPS 的不同之处

  • HTTP 的 URL 以 http:// 开头,而 HTTPS 的 URL 以 https:// 开头
  • HTTP 是不安全的,而 HTTPS 是安全的
  • HTTP 标准端口是 80 ,而 HTTPS 的标准端口是 443
  • 在 OSI 网络模型中,HTTP 工作于应用层,而 HTTPS 工作在传输层
  • HTTP 无需加密,而 HTTPS 对传输的数据进行加密
  • HTTP 无需证书,而 HTTPS 需要认证证书

3)如何选择 HTTP 和 HTTPS 协议

假如为了安全保密,将一个网站所有的 Web 应用都启用 SSL 技术来加密,并使用 HTTPS 协议进行传输,那么该网站的性能和效率将会大大降低,而且没有这个必要,因为一般来说并不是所有数据都要求那么高的安全保密级别,所以,我们只需对那些涉及机密数据的交互处理使用 HTTPS 协议,这样就做到鱼与熊掌兼得。总之不需要用 HTTPS 的地方,就尽量不要用。

1.5 方法

HTTP 支持几种不同请求和命令,这些命令被称为 HTTP 方法,每条 HTTP 请求报文都包含一个方法。 这个方法会告诉服务器要执行什么动作(获取一个 Web 页面、发送一段信息、删除一个文件等)。

我们在学习 form 表单的时候也知道 method 可以写作 post 和 get。这就是 HTTP 请求的方法。

请求方法如下:

请求方法描述
GET获取一个URL指定的资源,即资源实体
POST向服务器提交数据
PUT向服务器提交数据,多次请求会覆盖原来的操作
DELETE请求源服务器删除Request-URI标志的资源
HEAD获取一个指定资源的头信息
OPTIONS获取服务器支持的方法

1.6 状态码

每条 HTTP 响应报文返回时都会携带一个状态码。状态码是一个三位数字的代码,告知客户端请求是否成功, 或者是否需要采取其他动作。

状态码分成如下几个系列:

状态码定义说明
1XX请求被接受一般只在实验环境下使用
2XX成功操作成功的收到,理解和接收
3XX重定向为了完成请求,进行进一步措施
4XX客户端错误请求的语法有错误或者不能完全被满足
5XX服务器错误服务器无法完成明显有效的请求

常见的 HTTP 状态码:

HTTP状态码描述
200OK。文档正确返回
301/2永久/临时重定向
304not modified 未修改(原有的缓存可以继续使用)
404请求的网页不存在
503服务器暂时不可用
500服务器内部错误

1.7 报文

HTTP 报文是由一行一行的简单字符串组成的。HTTP 报文都是纯文本,不是二进制代码,所以人们可以很方便地对其进行读写。

请求和响应报文

从 Web 客户端发往 Web 服务器的 HTTP 报文称为请求报文(request message)。从服务器发往客户端的报文称为响应报文(response message)。

HTTP 报文包括以下三个部分:

  • 起始行
    报文的第一行就是起始行, 在请求报文中用来说明要做些什么, 在响应报文中说明
    出现了什么情况。

    • 请求行部分由 请求方法(GET,POST等),请求路径,协议版本组成。

    • 响应行部分由 协议版本,状态码,状态文字组成。

  • 首部字段
    起始行后面有零个或多个首部字段。 每个首部字段都包含一个名字和一个值, 为了
    便于解析, 两者之间用冒号来分隔。 首部以一个空行结束。

  • 主体
    空行之后就是可选的报文主体了, 其中包含了所有类型的数据。 请求主体中包括了
    要发送给 Web 服务器的数据; 响应主体中装载了要返回给客户端的数据。 起始行
    和首部都是文本形式且都是结构化的, 而主体则不同, 主体中可以包含任意的二进
    制数据(比如图片、视频、音轨、软件程序)。 当然, 主体中也可以包含文本。

1.7.1 请求头(Requests)部分

Header解释示例
Accept指定客户端能够接收的内容类型Accept: text/plain, text/html
Accept-Charset浏览器可以接受的字符编码集。Accept-Charset: iso-8859-5
Accept-Encoding指定浏览器可以支持的web服务器返回内容压缩编码类型。Accept-Encoding: compress, gzip
Accept-Language浏览器可接受的语言Accept-Language: en,zh
Accept-Ranges可以请求网页实体的一个或者多个子范围字段Accept-Ranges: bytes
AuthorizationHTTP授权的授权证书Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control指定请求和响应遵循的缓存机制Cache-Control: no-cache
Connection表示是否需要持久连接。(HTTP 1.1默认进行持久连接)Connection: close
CookieHTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。Cookie: $Version=1; Skin=new;
Content-Length请求的内容长度Content-Length: 348
Content-Type请求的与实体对应的MIME信息Content-Type: application/x-www-form-urlencoded
Date请求发送的日期和时间Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect请求的特定的服务器行为Expect: 100-continue
From发出请求的用户的EmailFrom: user@email.com
Host指定请求的服务器的域名和端口号Host: www.zcmhi.com
If-Match只有请求内容与实体相匹配才有效If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为EtagIf-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since只在实体在指定时间之后未被修改才请求成功If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards限制信息通过代理和网关传送的时间Max-Forwards: 10
Pragma用来包含实现特定的指令Pragma: no-cache
Proxy-Authorization连接到代理的授权证书Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range只请求实体的一部分,指定范围Range: bytes=500-999
Referer先前网页的地址,当前请求网页紧随其后,即来路Referer: http://www.zcmhi.com/archives/71.html
TE客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息TE: trailers,deflate;q=0.5
Upgrade向服务器指定某种传输协议以便服务器进行转换(如果支持)Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-AgentUser-Agent的内容包含发出请求的用户信息User-Agent: Mozilla/5.0 (Linux; X11)
Via通知中间网关或代理服务器地址,通信协议Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning关于消息实体的警告信息Warn: 199 Miscellaneous warning

1.7.2 响应头(Responses)部分

Header解释示例
Accept-Ranges表明服务器是否支持指定范围请求及哪种类型的分段请求Accept-Ranges: bytes
Age从原始服务器到代理缓存形成的估算时间(以秒计,非负)Age: 12
Allow对某网络资源的有效的请求行为,不允许则返回405Allow: GET, HEAD
Cache-Control告诉所有的缓存机制是否可以缓存及哪种类型Cache-Control: no-cache
Content-Encodingweb服务器支持的返回内容压缩编码类型。Content-Encoding: gzip
Content-Language响应体的语言Content-Language: en,zh
Content-Length响应体的长度Content-Length: 348
Content-Location请求资源可替代的备用的另一地址Content-Location: /index.htm
Content-MD5返回资源的MD5校验值Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range在整个返回体中本部分的字节位置Content-Range: bytes 21010-47021/47022
Content-Type返回内容的MIME类型Content-Type: text/html; charset=utf-8
Date原始服务器消息发出的时间Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag请求变量的实体标签的当前值ETag: “737060cd8c284d8af7ad3082f209582d”
Expires响应过期的日期和时间Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified请求资源的最后修改时间Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location用来重定向接收方到非请求URL的位置来完成请求或标识新的资源Location: http://www.zcmhi.com/archives/94.html
Pragma包括实现特定的指令,它可应用到响应链上的任何接收方Pragma: no-cache
Proxy-Authenticate它指出认证方案和可应用到代理的该URL上的参数Proxy-Authenticate: Basic
refresh应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)Refresh: 5; url=http://www.zcmhi.com/archives/94.html
Retry-After如果实体暂时不可取,通知客户端在指定时间之后再次尝试Retry-After: 120
Serverweb服务器软件名称Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie设置Http CookieSet-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer指出头域在分块传输编码的尾部存在Trailer: Max-Forwards
Transfer-Encoding文件传输编码Transfer-Encoding:chunked
Vary告诉下游代理是使用缓存响应还是从原始服务器请求Vary: *
Via告知代理客户端响应是通过哪里发送的Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning警告实体可能存在的问题Warning: 199 Miscellaneous warning
WWW-Authenticate表明客户端请求实体应该使用的授权方案WWW-Authenticate: Basic

以上内容复制自:http://www.cnblogs.com/Joans/p/3956490.html

使用火狐和 chrome 浏览器打开一个网页,找到其中一个网络请求查看报文。

1.8 推荐书籍

图解HTTP协议,入门经典图书

第 2 章 了解 API 接口

俗话说,无规矩不成方圆,为了让前后端更好的分离,写好每一个 API 接口是开发必备的技能,开发刚开始兴起的那些年,接口并未固定的规范,随着开发人数的不断扩大,配合问题成为大问题,接口的规范也就变得特别紧迫。
不管是什么开发,只要是基于互联网的,就必须考虑多人合作,共同开发的效率的问题。举个例子:我们有个 Python 库,可以处理图片的识别,你在代码中可以把图片路径直接写死,但我的图片是从摄像头过来的,是视频,你告诉人家,你必须给我图片,而且还得放在我自己的电脑上的固定文件夹里?

image-20210821111944596.png

第 3 章 RESTful 风格

Roy Thomas Fielding 演讲

Roy Thomas Fielding 博士是一个非常重要的人,他是 HTTP 协议(1.0版和1.1版)的主要设计者、Apache 服务器软件的作者之一、Apache 基金会的第一任主席。

早期有复杂的 SOAP 和 XML-PRC 规范, 2000 年 Fielding 发布论文Architectural Styles and the Design of Network-based Software Architectures 中重新对网络中数据传输进行重新定义,即表现层状态转换,俗称 RESTREST 是设计风格而不是标准。

API 云端一体
目前几乎都在使用 RESTful 作为接口标准

REST 通常基于HTTPURIXML以及HTML这些现有的广泛流行的协议和标准。下面是截取维基百科关于 REST 的要点以及标准,更多说明参考:表现层状态转换 REST(需要 VPN)。

  • 资源是由 URI 来指定。
  • 对资源的操作包括获取、创建、修改和删除,这些操作正好对应 HTTP 协议提供的 GET、POST、PUT 和 DELETE 方法。
  • 通过操作资源的表现形式来操作资源。
  • 资源的表现形式则是 XML 或者 HTML,取决于读者是机器还是人、是消费 Web 服务的客户软件还是 Web 浏览器。当然也可以是任何其他的格式,例如 JSON。只是我们见多了,觉得 JSON 好像是规定一样,其实不然,返回可以是多样的。

对于 Web 服务应用领域,符合 REST 设计风格的 Web API 称为RESTful API。它从以下三个方面资源进行定义。

  • 直观简短的资源地址:URI,比如:http://example.com/resources
  • 传输的资源:Web服务接受与返回的互联网媒体类型,比如:JSONXMLHTML等。
  • 对资源的操作:Web服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE)。

第 4 章 实战编写 API 接口

接口规范说起来大,其实也就那么几个部分,接口规范(RESTful)接口管理工具(阿里 RAP)接口文档编写(demo 示例),下面就根据以上这几个部分分别进行实战。

4.1 接口规范

1)协议

为了确保不同系统/模块间的数据交互,需要事先约定好通讯协议,如:TCP、HTTP、HTTPS 协议。为了确保数据交互安全,建议使用 HTTPS 协议。刚开始练习写接口的时候可忽略这一条。

2)域名

应该尽量将 API 部署在专用域名之下。

例如:`https://api.xxxxx.com`

如果确定 API 很简单,不会有进一步扩展,可以考虑放在主域名下。

例如:`https://xxxxx.org/api/`

3)接口版本控制规范

为了便于后期接口的升级和维护,建议在接口路径中加入版本号,便于管理,实现接口多版本的可维护性。如果你细心留意过的话,你会发现好多框架对外提供的 API 接口中,都带有版本号的。如:接口路径中添加类似v1v2等版本号。Github 采用这种做法。

格式规范如下:

`https://api.xxxxx.com/v1/xx`

更新版本后可以使用 v2、v3 等依次递加。

4)接口路径规范

路径又称终点(endpoint),表示 API 的具体网址。
在 RESTful 架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以 API 中的名词也应该使用复数。举例来说,有一个 API 提供动物园(zoo)的信息,还包括各种动物种类和雇员的信息,则它的路径应该设计成下面这样。

格式规范如下:

动物种类信息   `https://api.xxxxx.com/v1/species`

雇员信息   `https://api.xxxxx.com/v1/users`

5)接口命名规范

具体接口命名也要规范些,可使用驼峰命名法按照实现接口的业务类型、业务场景等命名,有必要时可采取多级目录命名,但目录不宜过长,两级目录较为适宜。

格式规范如下:

用户模块的登录接口 `https://api.xxxxx.com/v1/user/login`

动物园模块,获取 ID 为 9 的动物  `https://api.xxxxx.com/v1/zoo/zoos/9`

6) HTTP 请求方法

接口路径中包含具体接口名称的名词,接口数据操作动作以HTTP请求方式来区分。常用的HTTP请求方式有如下。

  	GET:从服务器取出资源(一项或多项)。

  	POST:在服务器新建一个资源。

  	PUT:在服务器更新资源(更新全部资源)。

  	PATCH:在服务器更新资源(更新局部资源)。

  	DELETE:从服务器删除资源。

格式规范如下:

GET https://api.xxxxx.com/v1/zoos:列出所有动物园`		

POST https://api.xxxxx.com/v1/zoos:新建一个动物园`

GET https://api.xxxxx.com/v1/zoos/ID:获取某个指定动物园的信息`

PUT https://api.xxxxx.com/v1/zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)

PATCH https://api.xxxxx.com/v1/zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)

DELETE https://api.xxxxx.com/v1/zoos/ID:删除某个动物园

GET https://api.xxxxx.com/v1/zoos/ID/animals:列出某个指定动物园的所有动物

DELETE https://api.xxxxx.com/v1/zoos/ID/animals/ID:删除某个指定动物园的指定动物

注意:修改有两个方法 PUT 和 PATCH。

假设 URL 位置有一组数据 UserInfo,包括 UserID、UserName 等 20 个字段
需求:用户修改了 UserName,其他不变
• 采用 PATCH,仅向 URL 提交 UserName 的局部更新请求
• 采用 PUT,必须将所有 20 个字段一并提交到 URL,未提交字段被删除
PATCH 的最主要好处:节省网络带宽

7)接口信息过滤

如果记录数量很多,服务器不可能都将它们返回给用户。API 应该提供参数,过滤返回结果。

格式规范如下:

?limit=10:指定返回记录的数量

?offset=10:指定返回记录的开始位置

?page=2&per_page=100:指定第几页,以及每页的记录数

?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序

?animal_type_id=1:指定筛选条件

参数的设计允许存在冗余,即允许 API 路径和 URL 参数偶尔有重复。比如,GET /zoo/ID/animalsGET /animals?zoo_id=ID 的含义是相同的。

8)请求参数规范

  • 请求方式: 按照 GET、POST、PUT 等含义定义,避免出现不一致现象,对人造成误解、歧义。

  • 请求头: 请求头根据项目需求添加配置参数。如:请求数据格式,accept=‘application/json’等。如有需要,API 的身份验证应该使用OAuth 2.0 框架 ,也可以参考:一张图搞定 OAuth 2.0。前期可不设置,随着 API 的开放程度,再决定是否要带 token、唯一验证码等。

  • 请求参数/请求体:

    请求参数字段,尽可能与数据库表字段、对象属性名等保持一致,因为保持一致最省事,最舒服的一件事。
    

9)接口返回数据

统一规范返回数据的格式,对己对彼都有好处,此处以 JSON 格式为例,XML 等格式已经过时。

返回数据应包含:返回状态码、返回状态信息、具体数据。

格式规范如下:

{
    "status":"0",
    "data": {
        //json 格式的具体数据
    },
    "msg":"success"
}

status::接口的执行状态

=0 表示成功,无错误

<0 表示有异常`

data:接口的主数据

可以根据实际返回 JSON 对象

msg:返回成功或者失败的错误信息

"msg":"success"

"msg":"error"

返回数据中的状态码、状态信息,常指具体的业务状态,不建议和 HTTP 状态码混在一起。HTTP 状态,是用来体现 HTTP链路状态情况,如:404-Not Found。HTTP 状态码和 JSON 结果中的状态码,并存尚可,用于体现不同维度的状态。

4.2 实战编写 API 接口

从接口的地址能看出来,有的是用框架做的,有的是单纯放在服务上的某个文件。哪种方式,都不重要,适合当前的业务需求,才是重点。使用框架,能系统性的组织接口目录,甚至轻松设置各种权限,且分离逻辑层和数据层。

这里我们使用 Python 的 Flask 框架,遵守上面的所有的要求,编写一组有关图书的 API。

简单的功能如下:

  • 图书列表返回
  • 返回指定图书的信息(书名,价格,作者)
  • 新增一本书
  • 删除一本书
  • 更新书本的信息(涨价了)

这里不牵扯到任何 Python 和 Pycharm 的教学,不会的童鞋挪步 Python 开发教程。

from flask import Flask, jsonify, abort, request

app = Flask(__name__)

# 正常 books 的数据应该是数据库查询出来的,方法有很多。
# 1、每次请求,都去请求数据库拿数据库,缺点是服务器压力大,如果数据量大,返回结果慢,针对实时变化的数据
# 2、把数据写到一个 JSON 文件中,每次都读这个文件数据,甚至可以直接返回该文件的内容,准对不变化的数据。
books = [
    {
        'id': 1,
        'title': u'论语',
        'auther': u'孔子',
        'price': 18
    },
    {
        'id': 2,
        'title': u'道德经',
        'auther': u'老子',
        'price': 15
    }
]

# 返回所有图书
@app.route('/bookstore/api/v1/books', methods=['GET'])
def get_tasks():
    return jsonify({'books': books})


# 返回指定 ID 的图书
@app.route('/bookstore/api/v1/books/<int:id>', methods=['GET'])
def get_task(id):
    for book in books:
        if book['id'] == id:
            return jsonify({'book': book})
    abort(404)


# 新增一本书
@app.route('/bookstore/api/v1/books/', methods=['POST'])
def create_task():
    if not request.form or not 'title' in request.form: # request.form 获取表单数据并做判断
        abort(400)
    book = {
        'id': books[-1]['id'] + 1,
        'title': request.form['title'],
        'auther': request.form['auther'],
        'price': request.form['price'],
    }
    books.append(book)
    return jsonify({'book': book}), 201 # 状态码 201 创建成功


# 修改某个 id 图书下的信息
@app.route('/bookstore/api/v1/books/<int:id>', methods=['PUT'])
def update_book(id):
    for book in books:
        if book['id'] == id:
           book["title"] = request.form['title']
           book["auther"] = request.form['auther']
           book["price"] = request.form['price']
        return jsonify({'books': books})
    abort(400)

 

# 删除某个 ID 图书下的信息
@app.route('/bookstore/api/v1/books/<int:id>', methods=['DELETE'])
def delete_task(id):
    for book in books:
        if book['id'] == id:
            books.remove(book)
            return jsonify({'result': True})
    abort(404)

    return jsonify({'result': True})


if __name__ == '__main__':
    app.run()

4.3 编写 API 文档

合格的 API 文档,不光是自己看着舒服,用着舒服,对接到其他团队,也是非常愉快的事情。当然,有很多接口工具,我们还没到那个阶段,工具是团队人数达到一定规模,API 经常维护,找个平台统一更新接口说明,现阶段,从基本的手写练习。

参考新浪开放平台 https://open.weibo.com,基本是国内最为标准的 API 文档之一。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT老鸟-王猛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值