rest - 什么是 RESTful 编程?

标签 rest http architecture definition

到底是什么 RESTful programming

最佳答案

REST 是网络的基础架构原则。 Web 的神奇之处在于客户端(浏览器)和服务器可以以复杂的方式进行交互,而客户端无需事先了解服务器及其托管的资源。关键约束是服务器和客户端必须就使用的媒体达成一致,在网络的情况下是HTML

遵循 REST 原则的 API 不需要客户端了解 API 的结构。相反,服务器需要提供客户端与服务交互所需的任何信息。 HTML 表单 就是这样的一个例子:服务器指定资源的位置和必填字段。 浏览器事先并不知道向哪里提交信息,也不知道要提交什么信息。这两种形式的信息完全由服务器提供。(这个原则称为 HATEOAS: Hypermedia As The Engine Of Application State 。)

那么,这如何应用于 HTTP,如何在实践中实现?HTTP 以动词和资源为导向。主流用法中的两个动词是GETPOST,我想大家都会认识。然而,HTTP 标准定义了其他几个,例如 PUTDELETE。然后根据服务器提供的指令将这些动词应用于资源。

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

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types.

对基础资源 / 的请求可能会返回如下内容:

请求

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 发出另一个请求来找到用户列表:

请求

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 来创建一个新用户:

请求

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 动词(GETPUTPOSTDELETE 等)操纵这些资源,我们假定客户唯一知道的就是我们的媒体定义。

进一步阅读:

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

关于rest - 什么是 RESTful 编程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/671118/

相关文章:

javascript - Mixer Client 接口(interface) Beam 对象不是构造函数

node.js - Neo4j 将数据序列化为 JSON

c# - DAL 类(class)应该公开吗?

iOS 是否有更好的替代基于通知的代码?

java - 如何在 Jersey RESTful web 服务中放置 cookie?

rest - Jmeter : How to check for empty text response

http - Solidity 有 HTTP 请求功能吗?

http - 使用 "+="缓慢构建长字符串

java - 使用 VpnService 的 Android http 隧道

python - Python 脚本中的架构最佳实践 - 一个函数调用所有其他函数,或者 "tree"其中一个函数调用调用其他函数的函数?