zoukankan      html  css  js  c++  java
  • 8-----ret简介以及flask实现restfule api

    什么是 REST?
    
    六条设计规范定义了一个 REST 系统的特点:
    客户端-服务器: 客户端和服务器之间隔离,服务器提供服务,客户端进行消费。
    无状态: 从客户端到服务器的每个请求都必须包含理解请求所必需的信息。换句话说, 服务器不会存储客户端上一次请求的信息用来给下一次使用。
    可缓存: 服务器必须明示客户端请求能否缓存。
    分层系统: 客户端和服务器之间的通信应该以一种标准的方式,就是中间层代替服务器做出响应的时候,客户端不需要做任何变动。
    统一的接口: 服务器和客户端的通信方法必须是统一的。
    按需编码: 服务器可以提供可执行代码或脚本,为客户端在它们的环境中执行。这个约束是唯一一个是可选的。
    
    什么是一个 RESTful 的 web service?
    REST 架构的最初目的是适应万维网的 HTTP 协议。
    RESTful web services 概念的核心就是“资源”。 资源可以用 URI 来表示。客户端使用 HTTP 协议定义的方法来发送请求到这些 URIs,当然可能会导致这些被访问的”资源“状态的改变。
    
    如下示例格式:
    
    ==========  ===============================================  =============================
    HTTP 方法   URL                                              动作
    ==========  ===============================================  ==============================
    GET         http://[hostname]/devops/api/v1.0/tasks            检索任务列表
    GET         http://[hostname]/devops/api/v1.0/tasks/[task_id]  检索某个任务
    POST        http://[hostname]/devops/api/v1.0/tasks            创建新任务
    PUT         http://[hostname]/devops/api/v1.0/tasks/[task_id]  更新任务
    DELETE      http://[hostname]/devops/api/v1.0/tasks/[task_id]  删除任务
    
    ##我们定义的任务有如下一些属性:
    
    id: 任务的唯一标识符。数字类型。
    title: 简短的任务描述。字符串类型。
    description: 具体的任务描述。文本类型。
    done: 任务完成的状态。布尔值。
    目前为止关于我们的 web service 的设计基本完成。剩下的事情就是实现它!
    
    第一个示例Get请求:
    [root@localhost opt]# cat test.py 
    from flask import Flask, jsonify
    
    app = Flask(__name__)
    
    tasks = [
        {
            'id': 1,
            'title': u'Buy groceries',
            'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
            'done': False
        },
        {
            'id': 2,
            'title': u'Learn Python',
            'description': u'Need to find a good Python tutorial on the web',
            'done': False
        }
    ]
    @app.route('/todo/api/v1.0/tasks', methods=['GET'])
    def get_tasks():
        return jsonify({'tasks': tasks})
    
    if __name__ == '__main__':
        app.run(debug=True,host='0.0.0.0')
    
    ####
    [root@localhost ~]# curl -i http://localhost:5000/todo/api/v1.0/tasks
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 317
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:12:40 GMT
    
    {
      "tasks": [
        {
          "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
          "done": false, 
          "id": 1, 
          "title": "Buy groceries"
        }, 
        {
          "description": "Need to find a good Python tutorial on the web", 
          "done": false, 
          "id": 2, 
          "title": "Learn Python"
        }
      ]
    }
    ##返回json格式的结果。
    
    2、接下来函数该子,当传入id 的时候,返回对应id 的结果:
    
    [root@localhost opt]# cat test.py 
    from flask import Flask, jsonify, abort
    
    app = Flask(__name__)
    
    tasks = [
        {
            'id': 1,
            'title': u'Buy groceries',
            'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
            'done': False
        },
        {
            'id': 2,
            'title': u'Learn Python',
            'description': u'Need to find a good Python tutorial on the web',
            'done': False
        }
    ]
    
    @app.route('/todo/api/v1.0/tasks', methods=['GET'])
    @app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET'])
    def get_task(task_id=None):
        if task_id:
            task = [i for i in tasks if i['id']==task_id]
            print(task)
            if len(task) == 0:
                abort(404)
            return jsonify({'task': task})
        else:
            return jsonify({'tasks': tasks})
    
    if __name__ == '__main__':
        app.run(debug=True,host='0.0.0.0')
    
    ##测试结果:
    [root@localhost opt]# curl -i http://localhost:5000/todo/api/v1.0/tasks/3
    HTTP/1.0 404 NOT FOUND
    Content-Type: text/html
    Content-Length: 232
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:30:56 GMT
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
    <title>404 Not Found</title>
    <h1>Not Found</h1>
    <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
    [root@localhost opt]# curl -i http://localhost:5000/todo/api/v1.0/tasks/1
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 162
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:31:00 GMT
    
    {
      "task": [
        {
          "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
          "done": false, 
          "id": 1, 
          "title": "Buy groceries"
        }
      ]
    }
    [root@localhost opt]# curl -i http://localhost:5000/todo/api/v1.0/tasks
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 317
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:31:02 GMT
    
    {
      "tasks": [
        {
          "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
          "done": false, 
          "id": 1, 
          "title": "Buy groceries"
        }, 
        {
          "description": "Need to find a good Python tutorial on the web", 
          "done": false, 
          "id": 2, 
          "title": "Learn Python"
        }
      ]
    }
    
    *当资源不存在的时候,返回404,但是这种返回效果不太好,为了优雅的线上,我们添加一个装饰器:
    
    from flask import make_response
    
    @app.errorhandler(404)
    def not_found(error):
        return make_response(jsonify({'error': 'Not found'}), 404)
    
    ###测试一下结构查询结果:
    [root@localhost opt]# curl -i http://localhost:5000/todo/api/v1.0/tasks/3
    HTTP/1.0 404 NOT FOUND
    Content-Type: application/json
    Content-Length: 27
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:35:14 GMT
    
    {
      "error": "Not found"
    }
    
    4、添加post请求:
    
    from flask import request
    
    @app.route('/todo/api/v1.0/tasks', methods=['POST'])
    def create_task():
        if not request.json or not 'title' in request.json:
            abort(400)
        task = {
            'id': tasks[-1]['id'] + 1,
            'title': request.json['title'],
            'description': request.json.get('description', ""),
            'done': False
        }
        tasks.append(task)
        return jsonify({'task': task}), 201
    
    ##先做判断没有收到json数据,或者没有title就返回400,并且返回201状态码
    
    [root@localhost opt]# curl -i -H "Content-Type: application/json" -X POST -d '{"title":"Read a book"}' http://localhost:5000/todo/api/v1.0/tasks
    HTTP/1.0 201 CREATED
    Content-Type: application/json
    Content-Length: 105
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:38:52 GMT
    
    {
      "task": {
        "description": "", 
        "done": false, 
        "id": 3, 
        "title": "Read a book"
      }
    }
    
    ##添加两条数据发现数据已经添加到了内存:
    [root@localhost opt]# curl -i http://localhost:5000/todo/api/v1.0/tasks
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 531
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:41:14 GMT
    
    {
      "tasks": [
        {
          "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
          "done": false, 
          "id": 1, 
          "title": "Buy groceries"
        }, 
        {
          "description": "Need to find a good Python tutorial on the web", 
          "done": false, 
          "id": 2, 
          "title": "Learn Python"
        }, 
        {
          "description": "", 
          "done": false, 
          "id": 3, 
          "title": "Read a book"
        }, 
        {
          "description": "", 
          "done": false, 
          "id": 4, 
          "title": "Read a book"
        }
      ]
    }
    
    
    ##剩余的PUT和DELETE方法:
    
    @app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT'])
    def update_task(task_id):
        task = [i for i in tasks if i['id']==task_id]
        print(task)
        if len(task) == 0:
            abort(404)
        if not request.json:
            abort(400)
        if 'title' in request.json and type(request.json['title']) != unicode:
            abort(400)
        if 'description' in request.json and type(request.json['description']) is not unicode:
            abort(400)
        if 'done' in request.json and type(request.json['done']) is not bool:
            abort(400)
        task[0]['title'] = request.json.get('title', task[0]['title'])
        task[0]['description'] = request.json.get('description', task[0]['description'])
        task[0]['done'] = request.json.get('done', task[0]['done'])
        return jsonify({'task': task})
    
    @app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE'])
    def delete_task(task_id):
        task = [i for i in tasks if i['id']==task_id]
        if len(task) == 0:
            abort(404)
        tasks.remove(task[0])
        print(tasks)
        return jsonify({'result': True})
    
    ##测试验证,更新一下2的状态:
    
    [root@localhost opt]#  curl -i -H "Content-Type: application/json" -X PUT -d '{"done":true}' http://localhost:5000/todo/api/v1.0/tasks/2
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 171
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:54:17 GMT
    
    {
      "task": [
        {
          "description": "Need to find a good Python tutorial on the web", 
          "done": true, 
          "id": 2, 
          "title": "Learn Python"
        }
      ]
    }
    
    ##删除task_2:
    
    [root@localhost opt]# curl -i -X DELETE http://localhost:5000/todo/api/v1.0/tasks/2
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 21
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:58:31 GMT
    
    {
      "result": true
    }
    [root@localhost opt]# curl -i -X GET http://localhost:5000/todo/api/v1.0/tasks
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 163
    Server: Werkzeug/0.15.6 Python/3.6.4
    Date: Tue, 15 Oct 2019 15:58:49 GMT
    
    {
      "tasks": [
        {
          "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
          "done": false, 
          "id": 1, 
          "title": "Buy groceries"
        }
      ]
    }
  • 相关阅读:
    使用 linux kernel +busybox 定制linux系统
    记一次golang的内存泄露
    关于Queries_per_sec 性能计数器
    NUMA导致的MySQL服务器SWAP问题分析
    Drop Table对MySQL的性能影响分析
    当MySQL数据库遇到Syn Flooding
    tcp_tw_recycle参数引发的数据库连接异常
    一例数据同步异常问题分析
    MySQL大量线程处于Opening tables的问题分析
    MySQL DeadLock故障排查过程
  • 原文地址:https://www.cnblogs.com/edeny/p/12631507.html
Copyright © 2011-2022 走看看