zoukankan      html  css  js  c++  java
  • restful

    什么是 REST

    REST 全称是 Representational State Transfer,翻译成中文是『表现层状态转移』,估计读者看到这个词也是云里雾里的,我当初也是!这里,我们先不纠结这个词到底是什么意思。事实上,REST 是一种 Web 架构风格,它有六条准则,满足下面六条准则的 Web 架构可以说是 Restuful 的。

    1. 客户端-服务器(Client-Server)服务器和客户端之间有明确的界限。一方面,服务器端不再关注用户界面和用户状态。另一方面,客户端不再关注数据的存储问题。这样,服务器端跟客户端可以独立开发,只要它们共同遵守约定。

    2. 无状态(Stateless)来自客户端的每个请求必须包含服务器所需要的所有信息,也就是说,服务器端不存储来自客户端的某个请求的信息,这些信息应由客户端负责维护。

    3. 可缓存(Cachable)服务器的返回内容可以在通信链的某处被缓存,以减少交互次数,提高网络效率。

    4. 分层系统(Layered System)允许在服务器和客户端之间通过引入中间层(比如代理,网关等)代替服务器对客户端的请求进行回应,而且这些对客户端来说不需要特别支持。

    5. 统一接口(Uniform Interface)客户端和服务器之间通过统一的接口(比如 GET, POST, PUT, DELETE 等)相互通信。

    6. 支持按需代码(Code-On-Demand,可选)服务器可以提供一些代码(比如 Javascript)并在客户端中执行,以扩展客户端的某些功能。

    使用 Flask 提供 REST Web 服务

    REST Web 服务的核心概念是资源(resources)。资源被 URI(Uniform Resource Identifier, 统一资源标识符)定位,客户端使用 HTTP 协议操作这些资源,我们用一句不是很全面的话来概括就是:URI 定位资源,用 HTTP 动词(GET, POST, PUT, DELETE 等)描述操作。下面列出了 REST 架构 API 中常用的请求方法及其含义:

    设计一个简单的 Web Service

    现在假设我们要为一个 blog 应用设计一个 Web Service。

    首先,我们先明确访问该 Service 的根地址是什么。这里,我们可以这样定义:

    http://[hostname]/blog/api/

    然后,我们明确有哪些资源是要公开的。可以知道,我们这个 blog 应用的资源就是 articles。

    下一步,我们要明确怎么去操作这些资源,如下所示:

    为了简便,我们定义一篇 article 的属性如下:

    • id:文章的 id,Numeric 类型

    • title: 文章的标题,String 类型

    • content: 文章的内容,TEXT 类型

    至此,我们基本完成了这个 Web Service 的设计,下面我们就来实现它。

    使用 Flask 提供 RESTful api

    在实现这个 Web 服务之前,我们还有一个问题没有考虑到:我们应该怎么存储我们的数据。毫无疑问,我们应该使用数据库,比如 MySql、MongoDB 等。但是,数据库的存储不是我们这里要讨论的重点,所以我们采用一种偷懒的做法:使用一个内存中的数据结构来代替数据库。

    GET 方法

    下面我们使用 GET 方法获取资源。

    # -*- coding: utf-8 -*-

    from flask import Flask, jsonify, abort, make_response

    app = Flask(__name__)

    articles = [

        {

            'id'1,

            'title''the way to python',

            'content''tuple, list, dict'

        },

        {

            'id'2,

            'title''the way to REST',

            'content''GET, POST, PUT'

        }

    ]

    @app.route('/blog/api/articles', methods=['GET'])

    def get_articles():

        """ 获取所有文章列表 """

        return jsonify({'articles'articles})

    @app.route('/blog/api/articles/<int:article_id>', methods=['GET'])

    def get_article(article_id):

        """ 获取某篇文章 """

        article = filter(lambda aa['id'] == article_id, articles)

        if len(article) == 0:

            abort(404)

        return jsonify({'article'article[0]})

    @app.errorhandler(404)

    def not_found(error):

        return make_response(jsonify({'error''Not found'}), 404)

    if __name__ == '__main__':

        app.run(host='127.0.0.1', port=5632, debug=True)

    将上面的代码保存为文件 app.py,通过 python app.py 启动这个 Web Service。

    接下来,我们进行测试。这里,我们采用命令行语句 curl 进行测试。

    开启终端,敲入如下命令进行测试:

    $ curl -i http://localhost:5632/blog/api/articles

    HTTP/1.0 200 OK

    Content-Typeapplication/json

    Content-Length224

    ServerWerkzeug/0.11.4 Python/2.7.11

    DateTue, 16 Aug 2016 15:21:45 GMT

    {

      "articles"[

        {

          "content""tuple, list, dict",

          "id"1,

          "title""the way to python"

        },

        {

          "content""GET, POST, PUT",

          "id"2,

          "title""the way to REST"

        }

      ]

    }

    $ curl -i http://localhost:5632/blog/api/articles/2

    HTTP/1.0 200 OK

    Content-Typeapplication/json

    Content-Length101

    ServerWerkzeug/0.11.4 Python/2.7.11

    DateWed, 17 Aug 2016 02:37:48 GMT

    {

      "article"{

        "content""GET, POST, PUT",

        "id"2,

        "title""the way to REST"

      }

    }

    $ curl -i http://localhost:5632/blog/api/articles/3

    HTTP/1.0 404 NOT FOUND

    Content-Typeapplication/json

    Content-Length26

    ServerWerkzeug/0.11.4 Python/2.7.11

    DateWed, 17 Aug 2016 02:32:10 GMT

    {

      "error""Not found"

    }

    上面,我们分别测试了『获取所有文章列表』、『获取某篇文章』和『获取不存在的文章』这三个功能,结果也正是我们所预料的。

    POST 方法

    下面我们使用 POST 方法创建一个新的资源。在上面的代码中添加以下代码:

    from flask import request

    @app.route('/blog/api/articles', methods=['POST'])

    def create_article():

        if not request.json or not 'title' in request.json:

            abort(400)

        article = {

            'id'articles[-1]['id'] + 1,

            'title'request.json['title'],

            'content'request.json.get('content', '')

        }

        articles.append(article)

        return jsonify({'article'article}), 201

    测试如下:

    $ curl -i -H "Content-Type: application/json" -X POST -d '{"title":"the way to java"}' http://localhost:5632/blog/api/articles

    HTTP/1.0 201 CREATED

    Content-Typeapplication/json

    Content-Length87

    ServerWerkzeug/0.11.4 Python/2.7.11

    DateWed, 17 Aug 2016 03:07:14 GMT

    {

      "article"{

        "content""",

        "id"3,

        "title""the way to java"

      }

    }

    可以看到,创建一篇新的文章也是很简单的。request.json 保存了请求中的 JSON 格式的数据。如果请求中没有数据,或者数据中没有 title 的内容,我们将会返回一个 “Bad Request” 的 400 错误。如果数据合法(必须要有 title 的字段),我们就会创建一篇新的文章。

    PUT 方法

    下面我们使用 PUT 方法更新文章,继续添加代码:

    @app.route('/blog/api/articles/<int:article_id>', methods=['PUT'])

    def update_article(article_id):

        article = filter(lambda aa['id'] == article_id, articles)

        if len(article) == 0:

            abort(404)

        if not request.json:

            abort(400)

        

        article[0]['title'] = request.json.get('title', article[0]['title'])

        article[0]['content'] = request.json.get('content', article[0]['content'])

        return jsonify({'article'article[0]})

    测试如下:

    $ curl -i -H "Content-Type: application/json" -X PUT -d '{"content": "hello, rest"}' http://localhost:5632/blog/api/articles/2

    HTTP/1.0 200 OK

    Content-Typeapplication/json

    Content-Length98

    ServerWerkzeug/0.11.4 Python/2.7.11

    DateWed, 17 Aug 2016 03:44:09 GMT

    {

      "article"{

        "content""hello, rest",

        "id"2,

        "title""the way to REST"

      }

    }

    可以看到,更新文章也是很简单的,上面我们更新了第 2 篇文章的内容。

    DELETE 方法

    下面我们使用 DELETE 方法删除文章,继续添加代码:

    @app.route('/blog/api/articles/<int:article_id>', methods=['DELETE'])

    def delete_article(article_id):

        article = filter(lambda tt['id'] == article_id, articles)

        if len(article) == 0:

            abort(404)

        articles.remove(article[0])

        return jsonify({'result'True})

    测试如下:

    $ curl -i -H "Content-Type: application/json" -X DELETE http://localhost:5632/blog/api/articles/2

    HTTP/1.0 200 OK

    Content-Typeapplication/json

    Content-Length20

    ServerWerkzeug/0.11.4 Python/2.7.11

    DateWed, 17 Aug 2016 03:46:04 GMT

    {

      "result"true

    }

    $ curl -i http://localhost:5632/blog/api/articles

    HTTP/1.0 200 OK

    Content-Typeapplication/json

    Content-Length125

    ServerWerkzeug/0.11.4 Python/2.7.11

    DateWed, 17 Aug 2016 03:46:09 GMT

    {

      "articles"[

        {

          "content""tuple, list, dict",

          "id"1,

          "title""the way to python"

        }

      ]

    }

    附录

    常见 HTTP 状态码

    HTTP 状态码主要有以下几类:

    • 1xx —— 元数据

    • 2xx —— 正确的响应

    • 3xx —— 重定向

    • 4xx —— 客户端错误

    • 5xx —— 服务端错误

    常见的 HTTP 状态码可见以下表格:

    curl 命令参考

    本文来自:

    https://mp.weixin.qq.com/s?__biz=MzA4MjEyNTA5Mw==&mid=2652564505&idx=2&sn=4391ca0d19e44d36ad35183bbc443629&chksm=8464c453b3134d45e1c87050c3676883d40324ec60eb4e8e92625709e7bb613362cc380de037&mpshare=1&scene=1&srcid=01109Mp9gHV3XWJl6Z83of7Z&key=72742a3cd154ac7cf68efd9ddab97b4c59d4aa9204c3fc739e7949108431f0a2efa3e4fc7a41588a07cfec32ec2c8f8a58fea60b391a776d3ef00f85485587e796c25092b671d5171482d099c56b33b8&ascene=0&uin=NjI3NDI1NjQw&devicetype=iMac+MacBookPro12%2C1+OSX+OSX+10.11.6+build(15G31)&version=12010210&nettype=WIFI&fontScale=100&pass_ticket=S7sSJCqbgDTJh9KfhldkumzkcifdNl0ntW923GHEnyKJYMCrijAoFvF5U7ecOzDT 

  • 相关阅读:
    配置 Ionic环境
    AngularJS 跨站请求- jsonp请求
    AngularJS过滤器filter-时间日期格式-渲染日期格式-$filter
    AngularJS过滤器filter-保留小数-渲染页面-小数点-$filter
    Linex系统 配置php服务器
    cookies,sessionStorage和localStorage的区别---web前端sessionStorage和localStorage区别
    ranch流程处理图
    iOS开发-开发总结(二)
    iOS开发-开发总结(一)
    iOS开发-开发总结
  • 原文地址:https://www.cnblogs.com/clovn/p/6271361.html
Copyright © 2011-2022 走看看