究竟什么是RESTful编程?

究竟什么是RESTful编程?

REST是网络的基本架构原则。网络的神奇之处在于,客户(浏览器)和服务器可以以复杂的方式进行互动,而客户事先对服务器和它所承载的资源一无所知。关键的制约因素是,服务器和客户端必须就使用的媒体达成一致,在网络的情况下就是HTML*。

遵循REST原则的API不要求客户知道任何关于API结构的信息。相反,服务器需要提供客户需要的任何信息来与服务进行交互。一个HTML表格就是这样的例子。服务器指定资源的位置和所需的字段。浏览器不会事先知道在哪里提交信息,也不会事先知道要提交什么信息。这两种形式的信息完全由服务器提供。(这一原则被称为[HATEOAS:超媒体作为应用状态的引擎](https://en.wikipedia.org/wiki/HATEOAS)。

那么,这如何适用于HTTP,以及如何在实践中实现? HTTP是围绕动词和资源展开的。主流使用的两个动词是 "GET "和 "POST",我想每个人都会认识它们。然而,HTTP标准还定义了其他几个动词,如PUTDELETE。然后,根据服务器提供的指示,这些动词被应用于资源。

例如,让我们想象一下,我们有一个用户数据库,由一个网络服务管理。我们的服务使用基于JSON的自定义超媒体,我们为其分配了mimetype application/json+userdb(也可能有application/xml+userdbapplication/whatever+userdb--许多媒体类型可能被支持)。客户端和服务器都被编程为理解这种格式,但它们对彼此并不了解。正如Roy Fielding所指出的。

一个REST API应该把几乎所有的描述工作都花在 定义用于表示资源和驱动的媒体类型。

应用状态,或定义扩展关系名称和/或 为现有的标准媒体类型提供超文本标记。

对基本资源/的请求可能会返回这样的结果。

Request

GET /
Accept: application/json+userdb

响应

200 OK
Content-Type: application/json+userdb

{
    "version": "1.0",
    "links": [
        {
            "href": "/user",
            "rel": "list",
            "method": "GET"
        },
        {
            "href": "/user",
            "rel": "create",
            "method": "POST"
        }
    ]
}

我们从媒体的描述中得知,我们可以从名为"链接"的部分找到相关资源的信息。这被称为超媒体控制。在这种情况下,我们可以从这样的部分得知,我们可以通过对/user的另一个请求来找到一个用户列表。

Request

GET /user
Accept: application/json+userdb

响应

200 OK
Content-Type: application/json+userdb

{
    "users": [
        {
            "id": 1,
            "name": "Emil",
            "country: "Sweden",
            "links": [
                {
                    "href": "/user/1",
                    "rel": "self",
                    "method": "GET"
                },
                {
                    "href": "/user/1",
                    "rel": "edit",
                    "method": "PUT"
                },
                {
                    "href": "/user/1",
                    "rel": "delete",
                    "method": "DELETE"
                }
            ]
        },
        {
            "id": 2,
            "name": "Adam",
            "country: "Scotland",
            "links": [
                {
                    "href": "/user/2",
                    "rel": "self",
                    "method": "GET"
                },
                {
                    "href": "/user/2",
                    "rel": "edit",
                    "method": "PUT"
                },
                {
                    "href": "/user/2",
                    "rel": "delete",
                    "method": "DELETE"
                }
            ]
        }
    ],
    "links": [
        {
            "href": "/user",
            "rel": "create",
            "method": "POST"
        }
    ]
}

我们可以从这个响应中看出很多东西。例如,我们现在知道我们可以通过POST/user来创建一个新的用户。

Request

POST /user
Accept: application/json+userdb
Content-Type: application/json+userdb

{
    "name": "Karl",
    "country": "Austria"
}

响应

201 Created
Content-Type: application/json+userdb

{
    "user": {
        "id": 3,
        "name": "Karl",
        "country": "Austria",
        "links": [
            {
                "href": "/user/3",
                "rel": "self",
                "method": "GET"
            },
            {
                "href": "/user/3",
                "rel": "edit",
                "method": "PUT"
            },
            {
                "href": "/user/3",
                "rel": "delete",
                "method": "DELETE"
            }
        ]
    },
    "links": {
       "href": "/user",
       "rel": "list",
       "method": "GET"
    }
}

我们还知道,我们可以改变现有的数据。

请求

PUT /user/1
Accept: application/json+userdb
Content-Type: application/json+userdb

{
    "name": "Emil",
    "country": "Bhutan"
}

响应

200 OK
Content-Type: application/json+userdb

{
    "user": {
        "id": 1,
        "name": "Emil",
        "country": "Bhutan",
        "links": [
            {
                "href": "/user/1",
                "rel": "self",
                "method": "GET"
            },
            {
                "href": "/user/1",
                "rel": "edit",
                "method": "PUT"
            },
            {
                "href": "/user/1",
                "rel": "delete",
                "method": "DELETE"
            }
        ]
    },
    "links": {
       "href": "/user",
       "rel": "list",
       "method": "GET"
    }
}

请注意,我们使用不同的HTTP动词(GET',PUT', POST',DELETE'等)来操作这些资源,而且我们在客户端假定的唯一知识是我们的媒体定义。

进一步阅读。

(这个答案已经受到了相当多的批评,因为它错过了重点。在大多数情况下,这是个公平的批评。我最初描述的内容更符合几年前我第一次写这篇文章时REST的通常实现方式,而不是它的真正含义。我已经修改了答案,以更好地代表真正的含义)。

评论(39)

REST是使用各种HTTP方法(主要是GET/PUT/DELETE)来操作数据。

而不是使用一个特定的URL来删除一个方法(比如说,/user/123/delete),你会向/user/[id] URL发送一个DELETE请求,要编辑一个用户,要检索一个用户的信息,你会向/user/[id]发送一个GET请求

例如,一组URL可能看起来像以下一些。

GET /delete_user.x?id=123
GET /user/delete
GET /new_user.x
GET /user/new
GET /user?id=1
GET /user/id/1

你使用HTTP的"动词",并有。

GET /user/2
DELETE /user/2
PUT /user
评论(5)

这是一种编程,你的系统架构符合Roy Fielding在他的论文中所阐述的REST风格。由于这是描述网络的架构风格(或多或少),很多人都对它感兴趣。

奖励答案。除非你作为一个学者研究软件架构或设计网络服务,否则真的没有理由听到这个词。

评论(4)