Restful Api 总结

Posted liangliangzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Restful Api 总结相关的知识,希望对你有一定的参考价值。

# RESTful API开发

### 什么是REST?

- 简介

  ```
  REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。
  RESTful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
  RESTful API,就是符合REST风格开发出来的应用程序接口。
  ```

- 资源

  ```
  RESTful接口是围绕网络资源及对网络资源的动作展开的。所谓的资源就是网络上存在的实体,哪怕是一条数据。
  ```

- 动作

  ```
  所谓的动作就是对数据的CURD。在开发者设计良好的前提下,任何网络操作都可以抽象为对资源的CURD动作。RESTful对网络资源的操作抽象为HTTP的GET、POST、PUT、DELETE等请求方法,具体对照如下:
  ```

  | 方法     | 行为     | 示例                               |
  | ------ | ------ | -------------------------------- |
  | GET    | 获取资源信息 | http://127.0.0.1:5000/source     |
  | GET    | 获取指定资源 | http://127.0.0.1:5000/source/250 |
  | POST   | 创建新的资源 | http://127.0.0.1:5000/source     |
  | PUT    | 修改指定资源 | http://127.0.0.1:5000/source/250 |
  | DELETE | 删除指定资源 | http://127.0.0.1:5000/source/250 |

- 数据

  通常Restful API 风格的数据都采用JSON格式传输。

- 测试工具

  - 说明:postman是一款非常好用的测试工具,能够轻松模拟各种请求
  - 安装:下载完安装包,一路next即可。

### 原生实现

- 准备数据(放在内存)

  ```python
  posts = [
      {
          id: 1,
          title: Python基础,
          content: 人生苦短,我用python
      },
      {
          id: 2,
          title: html,
          content: 几个标签的故事
      }
  ]
  ```

- 获取资源列表

  ```python
  @app.route(/posts/)
  def get_posts_list():
      return jsonify({posts: posts})
  ```

- 获取指定资源

  ```python
  @app.route(/posts/<int:pid>)
  def get_posts(pid):
      p = list(filter(lambda p: p[id] == pid, posts))
      if len(p) == 0:
          abort(404)
      return jsonify({posts: p[0]})
  ```

- 添加新的资源

  ```python
  @app.route(/posts/, methods=[POST])
  def create_posts():
      if not request.json or title not in request.json or content not in request.json:
          abort(400)
      p = {
          id: posts[-1][id] + 1,
          title: request.json[title],
          content: request.json[content]
      }
      posts.append(p)
      return jsonify({posts: p}), 201
  ```

- 修改指定资源

  ```python
  @app.route(/posts/<int:pid>, methods=[PUT])
  def update_posts(pid):
      p = list(filter(lambda p: p[id] == pid, posts))
      if len(p) == 0:
          abort(404)
      if title in request.json:
          p[0][title] = request.json[title]
      if content in request.json:
          p[0][content] = request.json[content]
      return jsonify({posts: p[0]})
  ```

- 删除指定资源

  ```python
  @app.route(/posts/<int:pid>, methods=[DELETE])
  def delete_posts(pid):
      p = list(filter(lambda p: p[id] == pid, posts))
      if len(p) == 0:
          abort(404)
      posts.remove(p[0])
      return jsonify({result: 数据已删除})
  ```

- 错误页面定制

  ```python
  # 定制400错误显示
  @app.errorhandler(400)
  def bad_request(e):
      return jsonify({error: bad request}), 400

  # 定制404错误显示
  @app.errorhandler(404)
  def page_not_found(e):
      return jsonify({error: page not found}), 404
  ```

### flask-httpauth

- 说明:专门进行身份认证的扩展库,使用非常方便。

- 安装:`pip install flask-httpauth`

- 使用:

  ```python
  # 导入类库
  from flask_httpauth import HTTPBasicAuth

  # 创建认证对象
  auth = HTTPBasicAuth()

  # 认证的回调函数
  @auth.verify_password
  def verify_password(username, password):
      if username == Jerry and password == 123456:
          return True
      return False

  # 认证错误定制
  @auth.error_handler
  def unauthorized():
      return jsonify({error: Unauthorized Access}), 403
  ```


- 保护指定路由

  ```python
  @app.route(/posts/<int:pid>, methods=[DELETE])
  # 需要认证才能访问
  @auth.login_required
  def delete_posts(pid):
      p = list(filter(lambda p: p[id] == pid, posts))
      if len(p) == 0:
          abort(404)
      posts.remove(p[0])
      return jsonify({result: 数据已删除}) 
  ```

### flask-restful

- 说明:是一个快速实现restful api开发的扩展库,使用比较方便。

- 安装:`pip install flask-restful`

- 使用:

  ```python
  from flask_restful import Api, Resource

  # 创建资源管理对象
  api = Api()

  class UserAPI(Resource):
      # 保护类中所有的函数
      decorators = [auth.login_required]

      def get(self, uid):
          return {User: 获取}

      def put(self, uid):
          return {User: 修改}

      # 可以单独保护
      # @auth.login_required
      def delete(self, uid):
          return {User: 删除}

  class UserListAPI(Resource):
      def get(self):
          return {UserList: 获取列表}

      def post(self):
          return {UserList: 添加资源}

  # 添加资源
  api.add_resource(UserAPI, /users/<int:uid>)
  # 可以添加多个路由
  api.add_resource(UserListAPI, /users/, /u/)
  # 若创建与初始化分开, 那么一定要将初始化放在添加资源之后
  api.init_app(app)
  ```

### 基于token的身份认证

- 说明:移动APP的身份标识,使用cookie比较麻烦,使用用户名和密码有风险,使用token比较合适。

- 使用:

  ```python
  @auth.verify_password
  def verify_password(username_or_token, password):
      if username_or_token == Jerry and password == 123456:
          g.username = username_or_token
          return True
      # 再次尝试token认证
      s = Serializer(app.config[SECRET_KEY])
      try:
          data = s.loads(username_or_token.encode(utf8))
          g.username = data[username]
          return True
      except:
          return False

  # 生成token
  @app.route(/get_token/)
  @auth.login_required
  def generate_token():
      s = Serializer(app.config[SECRET_KEY], expires_in=3600)
      token = s.dumps({username: g.username})
      return jsonify({token: token.decode(utf8), expires: 3600})
  ```

  ?

 

以上是关于Restful Api 总结的主要内容,如果未能解决你的问题,请参考以下文章

Java Web学习总结(44)—— RESTful 架构和 RESTful API 设计总结

RESTful架构和RESTful API设计总结

Restful Api 总结

云原生(08):RESTful API中的HTTP方法和状态码总结

用产品思维设计API——RESTful就是个骗局

RESTful风格API个人总结