• 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})
      ```
    
      ​
  • 相关阅读:
    高危!Fastjson反序列化远程代码执行漏洞风险通告,请尽快升级
    主管发话:一周搞不定用友U8 ERP跨业务数据分析,明天就可以“毕业”了
    解决Visual Studio Code无法响应的问题
    【摸鱼神器】一次搞定 vue3的 路由 + 菜单 + tabs
    【java】BigDecimal大于等于/小于等于/小于/大于/等于 比较器工具方法
    【mysql】 mysql having count 的使用
    linux中在进程之间传递文件描述符的实现方式
    top使用
    JavaScript 学习27.查找HTML DOM节点(元素) 上海
    JavaScript 学习29.HTML DOM 事件 上海
  • 原文地址:https://www.cnblogs.com/liangliangzz/p/10221968.html
Copyright © 2020-2023  润新知