1

首先要说的是,这是来自stackoverflow的一个高票答案(提问的问题就是我这篇翻译的标题),其次就是这个回答有点偏离正题,但是不影响我们对RESTful的理解,最起码让我走出了一个误区,这里强烈推荐另外一篇文章:我是咋向我老婆解释REST滴,看的茅塞顿开有没有!!

原文链接


REST是web世界的基本架构原则,关于web最神奇的事就是:明明之前客户端对服务器以及服务器资源一无所知,客户端(浏览器)和服务器却可以使用复杂的方式来相互作用 。而关键的约束就是服务器以及浏览器客户端都在使用媒介上达成一致,而在web里我们都知道这个媒介就是HTML。

所以,坚持使用REST原则的API是不要求客户端了解该API的任何结构滴!相反,服务器会提供所有客户端与服务器交互所需要的消息,一个HTML的表单就是很好的例子:服务器指定资源的位置,以及需要的字段信息。浏览器不需要提前知道去哪里提交信息并且浏览器也不知道提交什么信息,这两种表单信息都是完全由服务器提供的(这种原则就被称为HATEOAS)(译者注:HATEOAS是Hypermedia As The Engine Of Application State的缩写)。

所以这货是怎么用在HTTP,我们又怎么在实践中使用呢?Https是面向动作(verb)和资源(resource)的,我觉得几乎所有的人都知道经常用的两个动作就是GET和POST,但是实际上HTTP标准还定义了其他的一些动作比如DELECT和PUT,这些动作根据服务器指令规定也会作用在资源上。

比如,现在我们想象有一个web服务在管理着一个数据库,我们的服务是基于自定义的JSON,因此我们定义一个application/json+userdb((这里也许还有application/xml+userdb 以及application/whatever+userdb - 许多的媒体类型都是支持的),服务器以及客户端的程序被写成了都能理解这种格式,但是相互之间没有任何联系,正如Roy Fielding指出的:

一个REST API应该把所有的精力都放在定义被用在表示资源和驱动应用状态的媒体类型(media type)上边,或者是为已经存在的标准媒体类型定义扩展的关系名以及超文本标记

一个对基本资源“/”的请求可能返回一些下边这样的:

request:

GET /
Accept: application/json+userdb

response:

200 OK
Content-Type: application/json+userdb

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

根据media的描述我们可以从部分被称为链接的部分上得到一些关于资源的信息,这被称为超媒体链接。在这种情况下,我们被告知了可以通过造另外一个链接“/user”来找寻一个user列表:
request:

GET /user
Accept: application/json+userdb

response:

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"
        }
    ]
}

我们从这个链接里又被告知了许多的东西,比如,我们知道我们可以通过POSTing这个“/user”来创建一个user:
request:

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

{
    "name": "Karl",
    "country": "Austria"
}POST /user
Accept: application/json+userdb
Content-Type: application/json+userdb

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

response:

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"
    }
}

我们同样知道了可以改变现有的数据:
request:

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

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

response:

    
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"
    }
}

注意我们使用的不同的动词(GET, PUT, POST, DELETE etc.)来操纵资源,当然我们假设客户端的部分只有我们的media定义

深入阅读:
Martin Fowler's thoughts
Paypalde API | has hypermedia controls

(这篇文章因为其主观性而备受批评,而大多数的批评都是得当的,我之前的回答似乎更偏向与Rest是如何在头几年实施的而不是现在大家看到的,我已经修改了答案使之更符合题目)
编辑于1月18号


已注销
214 声望5 粉丝

写代码不要局限某种语言,解决问题才是最重要的