ChatGPT解决这个技术问题 Extra ChatGPT

什么是 RESTful 编程?

RESTful programming 到底是什么?

另请参阅以下链接中的答案 stackoverflow.com/a/37683965/3762855
REST 现在可能有点过时了;)youtu.be/WQLzZf34FJ8
此外,请参阅此链接了解更多信息 news.ycombinator.com/item?id=3538585
@OLIVER.KOO 很好的观察。只是我在它是一种新事物的时候问它。它被扔了很多,但没有多少人知道它是关于什么的。至少我没有,而且我问这个似乎对他们有所帮助,因为他们也想知道。

2
22 revs, 15 users 88%

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

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

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

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

REST API 应该花费几乎所有的描述性工作来定义用于表示资源和驱动应用程序状态的媒体类型,或定义扩展关系名称和/或现有标准媒体类型的超文本启用标记。

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

要求

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。

马丁·福勒的想法

PayPal 的 API 具有超媒体控件

(这个答案因为没有抓住重点而受到相当多的批评。在大多数情况下,这是一个公平的批评。我最初描述的内容更符合几年前我通常如何实现 REST首先写这个,而不是它的真正含义。我已经修改了答案以更好地代表真正的含义。)


不,REST 不只是作为另一个流行词出现。它是作为一种描述基于 SOAP 的数据交换的替代方法而出现的。术语 REST 有助于构建关于如何传输和访问数据的讨论。
尽管如此,REST(在实际应用中)的核心是“不要使用 GET 进行更改,使用 POST/PUT/DELETE”,这是我早在 SOAP 出现之前就已经听到(并遵循)的建议。 REST 一直存在,只是直到最近它才获得了超越“实现方式”的名称。
不要忘记“超文本作为应用程序状态的引擎”。
这个答案没有抓住重点。在 Fielding 的论文中几乎没有提到 HTTP。
这个答案没有提到 REST 的目的,并且看起来就像是关于干净的 URI。虽然这可能是对 REST 的普遍看法,但 D.Shawley 和 oluies 的答案更准确 - 它是关于能够利用架构中内置的功能,如缓存,通过使用它而不是反对它。更漂亮的 URI 大多是常见的副作用。
Z
Zulkifil

一种称为 REST (Representational State Transfer)架构风格主张网络应用程序应该使用 HTTP,因为它是最初设想的。查找应使用 GET 请求。 PUT, POST, and DELETE requests 应分别用于 mutationcreationdeletion

REST 支持者倾向于使用 URL,例如

http://myserver.com/catalog/item/1729

但 REST 架构不需要这些“漂亮的 URL”。带参数的 GET 请求

http://myserver.com/catalog?item=1729

一点也不像 RESTful。

请记住,永远不应使用 GET 请求来更新信息。例如,将商品添加到购物车的 GET 请求

http://myserver.com/addToCart?cart=314159&item=1729

不合适。 GET 请求应为 idempotent。也就是说,发出两次请求应该与发出一次没有什么不同。这就是使请求可缓存的原因。 “添加到购物车”请求不是幂等的——发出两次会将商品的两个副本添加到购物车中。在这种情况下,POST 请求显然是合适的。因此,即使是 RESTful Web 应用程序 也需要它的 POST 请求份额。

这取自 David M. Geary 的优秀书籍 Core JavaServer faces book。


列出可用的幂等操作:GET(安全)、PUT 和 DELETE(此链接restapitutorial.com/lessons/idempotency.html 中提到了例外)。安全和幂等方法的附加参考 w3.org/Protocols/rfc2616/rfc2616-sec9.html
a)关于 GET 的重点是安全性,而不是幂等性,b)@Abhijeet:RFC 2616 已于 2014 年过时;见射频 7230ff。
@kushalvm REST 的学术定义并未在实践中使用。
实际上,我们可以怀疑一个概念是否可操作,因为我们无法简单地为所有人提供一个稳定且易于理解的定义
C
Community

RESTful 编程是关于:

由持久标识符标识的资源:如今,URI 是无处不在的标识符选择

使用一组通用动词操作资源:HTTP 方法是常见的情况——古老的 Create、Retrieve、Update、Delete 变成 POST、GET、PUT 和 DELETE。但 REST 不限于 HTTP,它只是目前最常用的传输方式。

为资源检索的实际表示取决于请求而不是标识符:使用 Accept 标头来控制您是否需要 XML、HTTP 甚至是表示资源的 Java 对象

维护对象中的状态并在表示中表示状态

在资源的表示中表示资源之间的关系:对象之间的链接直接嵌入在表示中

资源表示描述了如何使用表示以及在什么情况下应该以一致的方式丢弃/重新获取它: HTTP Cache-Control 标头的使用

就 REST 的后果和整体有效性而言,最后一个可能是最重要的。总体而言,大多数 RESTful 讨论似乎都集中在 HTTP 及其在浏览器中的使用以及其他方面。我知道 R. Fielding 在描述导致 HTTP 的架构和决策时创造了这个术语。他的论文更多地是关于资源的架构和缓存能力,而不是关于 HTTP。

如果您真的对什么是 RESTful 架构及其工作原理感兴趣,请阅读 his thesis 几遍并阅读全部内容,而不仅仅是第 5 章!接下来查看 why DNS works。阅读有关 DNS 的分层组织以及引荐的工作原理。然后阅读并考虑 DNS 缓存的工作原理。最后,阅读 HTTP 规范(特别是 RFC2616RFC3040)并考虑缓存如何以及为什么会以这种方式工作。最终,它只会点击。对我来说,最后的启示是当我看到 DNS 和 HTTP 之间的相似性时。在此之后,开始点击了解 SOA 和消息传递接口为何具有可扩展性。

我认为了解 RESTful 和 Shared Nothing 架构的架构重要性和性能影响的最重要技巧是避免陷入技术和实现细节上。关注谁拥有资源,谁负责创建/维护资源等。然后考虑表示、协议和技术。


提供阅读清单的答案非常适合这个问题。
感谢更新。 PUTPOST 并没有真正一对一地映射更新和创建。 PUT 可用于创建客户端是否指定 URI。 POST 如果服务器正在分配新的 URI,则创建。
URN 是使用 urn: 方案的 URI。从概念上讲没有区别;但是,URN 确实需要您有一个单独定义的方法来“定位”由 URN 标识(命名)的资源。必须注意确保在关联命名资源及其位置时不会引入隐式耦合。
@ellisbben 同意。如果我理解正确,这就是引发 REST 的论文:ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
关于这一点的一个疑问:“为资源检索的实际表示取决于请求而不是标识符:使用 HTTP Accept 标头来控制您是否需要 XML、HTTP 甚至是表示资源的 Java 对象”——这里,它应该是“......无论你想要 XML、HTML 还是代表资源的 Java 对象......”我认为 HTTP Accept 标头告诉数据交换的格式。 HTTP 是 RESTel Web API 中使用的协议
K
Kyle Baker

这可能是它的样子。

创建具有三个属性的用户:

POST /user
fname=John&lname=Doe&age=25

服务器响应:

200 OK
Location: /user/123

将来,您可以检索用户信息:

GET /user/123

服务器响应:

200 OK
<fname>John</fname><lname>Doe</lname><age>25</age>

修改记录(lnameage 将保持不变):

PATCH /user/123
fname=Johnny

要更新记录(因此 lnameage 将为 NULL):

PUT /user/123
fname=Johnny

对我来说,这个答案抓住了所需答案的本质。简单实用。当然还有很多其他标准,但提供的示例是一个很棒的启动台。
在最后一个示例中,@pbreitenbach 使用 PUT fname=Jonny。这会将 lnameage 设置为默认值(可能是 NULL 或空字符串,以及整数 0),因为 PUT 使用提供的表示中的数据覆盖整个资源。这不是“更新”所暗示的,要进行真正的更新,请使用 PATCH 方法,因为这不会更改表示中未指定的字段。
尼古拉斯是对的。此外,创建用户的第一个 POST 的 URI 应该称为 users,因为 /user/1 没有意义,并且应该在 /users 处有一个列表。在这种情况下,响应应该是 201 Created 而不仅仅是 OK。
这只是一个 API 的示例,不一定是 RESTful api。 RESTful 具有它所遵循的约束。客户端-服务器架构,无状态,缓存能力,分层系统,统一接口。
这是一个非常紧凑的答案,涵盖了所有 http servlet 访问方法
1
14 revs, 4 users 94%

REST in Practice 是一本关于 REST 的好书。

必须阅读是 Representational State Transfer (REST)REST APIs must be hypertext-driven

有关什么是 RESTful 服务的解释,请参阅 Martin Fowlers 文章 Richardson Maturity Model (RMM)。

https://i.stack.imgur.com/FoKRB.png

要成为 RESTful 服务需要满足 Hypermedia as the Engine of Application State. (HATEOAS),即它需要达到 RMM 中的第 3 级,read the article 了解详细信息或 slides from the qcon talk

HATEOAS 约束是 Hypermedia as the Engine of Application State 的首字母缩写。此原则是 REST 与大多数其他形式的客户端服务器系统之间的关键区别。 ... RESTful 应用程序的客户端只需要知道一个固定的 URL 即可访问它。所有未来的动作都应该可以从包含在从该 URL 返回的资源表示中的超媒体链接中动态发现。任何可能使用 RESTful API 的客户端也应该能够理解标准化的媒体类型。 (维基百科,自由的百科全书)

REST Litmus Test for Web Frameworks 是针对 Web 框架的类似成熟度测试。

Approaching pure REST: Learning to love HATEOAS 是一个很好的链接集合。

REST versus SOAP for the Public Cloud 讨论了 REST 的当前使用水平。

REST and versioning 通过可修改性讨论可扩展性、版本控制、可演化性等


我认为这个答案触及了理解 REST 的关键点:representative 这个词是什么意思。级别 1 - 资源说明状态。级别 2 - HTTP 动词说关于传输(读取更改)。第 3 级 - HATEOAS 表示通过表示(返回的 JSON/XML/HTML)推动未来的传输,这意味着您已经知道如何使用返回的信息进行下一轮对话。所以 REST 读作:“(代表性(状态转移))”,而不是“((代表性状态)转移)”。
j
jball

什么是 REST? REST 代表具象状态转移。 (有时拼写为“ReST”。)它依赖于无状态、客户端-服务器、可缓存的通信协议——几乎在所有情况下都使用 HTTP 协议。 REST 是一种用于设计网络应用程序的架构风格。这个想法是,不是使用复杂的机制,如 CORBA、RPC 或 SOAP 来连接机器,而是使用简单的 HTTP 在机器之间进行调用。在许多方面,基于 HTTP 的万维网本身可以被视为基于 REST 的架构。 RESTful 应用程序使用 HTTP 请求来发布数据(创建和/或更新)、读取数据(例如,进行查询)和删除数据。因此,REST 将 HTTP 用于所有四个 CRUD(创建/读取/更新/删除)操作。 REST 是 RPC(远程过程调用)和 Web 服务(SOAP、WSDL 等)等机制的轻量级替代方案。稍后,我们将看到 REST 是多么简单。尽管很简单,但 REST 功能齐全;在 Web 服务中,基本上没有什么是 RESTful 架构无法完成的。 REST 不是“标准”。例如,永远不会有针对 REST 的 W3C 推荐。虽然有 REST 编程框架,但使用 REST 非常简单,您通常可以使用 Perl、Java 或 C# 等语言的标准库功能“自行开发”。

当我试图找到休息的简单真正含义时,我找到了最好的参考资料之一。

http://rest.elkstein.org/


这是一个非常简洁的答案。你能否描述一下为什么 REST 被称为无状态?
d
dbr

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

与其使用特定 URL 来删除方法(例如 /user/123/delete),不如向 /user/[id] URL 发送 DELETE 请求,以编辑用户,检索您向 {2 }

例如,取而代之的是一组可能类似于以下内容的 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

那就是“正确使用HTTP”,和“restful”不一样(虽然和它有关)
您也可以使用 /user/del/2 和 /user/remove/2 或... GET/DELETE/PUT/POST 只是标准化的“正确”方式来做这些事情(正如朱利安所说,这还不是全部有休息)
当然,但这不是避免它们的理由。REST 只是让您每次都重新发明轮子。对于 API,REST 很棒(一致性!),但对于构建一个随机网站,我想说这并不重要(它可能比它的价值更麻烦)
Vadim,那就是简单的 RPC。使用 GET 修改数据也很危险,因为(除其他原因外)搜索引擎可能会抓取您的删除链接并访问它们。
@aehlke - 我认为真正的问题是“为什么匿名用户能够从您的系统中删除记录?”
H
Hank Gay

它是您的系统架构符合 Roy Fielding 在 his thesis 中提出的 REST style 的编程。由于这是描述网络的架构风格(或多或少),所以很多人都对它感兴趣。

奖励答案:不。除非您正在研究软件架构作为学术或设计 Web 服务,否则真的没有理由听说过这个术语。


但不是直截了当..使它变得更加复杂。
此外,尽管 REST 和 RESTful 这两个术语现在几乎专门用于 Web 应用程序领域,但从技术上讲,没有任何东西将 REST 与 HTTP 联系起来。
Fielding 的博客有一些关于 REST 和常见误解的好文章,更易于理解:roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
@HankGay 我认为它不是更深奥的原因是大多数 Web 服务开发人员将 REST 视为对 SOAP 等替代方案的极好的简化。他们不一定坚持让所有 REST 技术正确——这可能会让 REST 狂热者发疯——但在大多数情况下,他们可能不需要担心诸如确保他们的结果是“支持超媒体的”之类的事情。
n
nsandersen

我会说 RESTful 编程是关于创建遵循 REST 架构风格的系统 (API)。

我发现 M. Elkstein 博士撰写的关于 REST 的精彩、简短且易于理解的教程,并引用了大部分可以回答您的问题的基本部分:

Learn REST: A Tutorial

REST 是一种用于设计网络应用程序的架构风格。这个想法是,不是使用复杂的机制,如 CORBA、RPC 或 SOAP 来连接机器,而是使用简单的 HTTP 在机器之间进行调用。在许多方面,基于 HTTP 的万维网本身可以被视为基于 REST 的架构。 RESTful 应用程序使用 HTTP 请求来发布数据(创建和/或更新)、读取数据(例如,进行查询)和删除数据。因此,REST 将 HTTP 用于所有四个 CRUD(创建/读取/更新/删除)操作。

我认为你不应该因为没有听到 Stack Overflow 之外的 REST 而感到愚蠢......,我也会遇到同样的情况!回答 Why is REST getting big now 上的其他 SO 问题可以缓解一些情绪。


本文解释了 HTTP 和 REST freecodecamp.org/news/… 之间的关系
w
womp

如果我没有直接回答问题,我深表歉意,但是通过更详细的示例更容易理解所有这些。由于所有的抽象和术语,Fielding 并不容易理解。

这里有一个相当好的例子:

Explaining REST and Hypertext: Spam-E the Spam Cleaning Robot

更好的是,这里有一个简单的例子的清晰解释(powerpoint 更全面,但你可以在 html 版本中获得大部分内容):

http://www.xfront.com/REST.ppthttp://www.xfront.com/REST.html

阅读示例后,我可以理解为什么 Ken 说 REST 是超文本驱动的。不过,我实际上不确定他是否正确,因为 /user/123 是一个指向资源的 URI,而且我不清楚它是否是非 RESTful 只是因为客户端“带外”知道它。

该 xfront 文档解释了 REST 和 SOAP 之间的区别,这也很有帮助。当 Fielding 说“That is RPC. It screams RPC.”时,很明显 RPC 不是 RESTful,因此了解其确切原因很有用。 (SOAP 是一种 RPC。)


很酷的链接,谢谢。我厌倦了这些 REST 家伙说某些示例不是“REST-ful”,然后拒绝说如何将示例更改为 REST-ful。
A
Aliaksandr Belik

什么是 REST?

REST 用官方的话说,REST 是一种架构风格,建立在某些原则之上,使用当前的“Web”基础。有 5 个 Web 基本原理可用于创建 REST 服务。

原则 1:一切都是资源 在 REST 架构风格中,数据和功能被视为资源,并使用统一资源标识符 (URI) 访问,通常是 Web 上的链接。

原则 2:每个资源都由唯一标识符 (URI) 标识

原则 3:使用简单统一的接口

原则 4:沟通由代表完成

原则 5:无国籍


Communication is Done by Representation 是什么意思?
K
Ken

我看到一堆答案说将有关用户 123 的所有内容放在资源“/user/123”中是 RESTful。

创造该术语的 Roy Fielding 说 REST APIs must be hypertext-driven。特别是,“REST API 不得定义固定的资源名称或层次结构”。

因此,如果您的“/user/123”路径在客户端上是硬编码的,那么它并不是真正的 RESTful。很好地使用 HTTP,也许,也许不是。但不是 RESTful。它必须来自超文本。


所以....那个例子怎么会让人放松?您将如何更改网址以使其安静?
hasen:对于 RESTful 而言,可能需要为所有操作使用一种资源,但这还不够。
好吧好吧..你能进一步解释一下吗?说“不,这些人是错的……我知道什么是对的”而不说你知道(或认为)是对的有什么意义?
我给了菲尔丁描述的链接。我以为我准确地说了与其他响应的相关差异:需要由超文本驱动。如果“/user/123”来自一些带外 API 文档,那么它不是 RESTful。如果它来自超文本中的资源标识符,那么它就是。
@Andy:当您将硬编码的 URL 放入其中时,client 将不再是 RESTful。特别是,RESTful 服务可能会一时兴起决定对用户重新编号,这会破坏该非 RESTful 客户端。当无法从记录的入口点发现 /user/123/ 时,该服务将停止 RESTful,这实际上意味着所有客户端都必须对该 URL 进行硬编码。
i
inf3rno

答案很简单,有一个由 Roy Fielding 撰写的dissertation。]1在那篇论文中,他定义了 REST 原则。如果一个应用程序满足所有这些原则,那么这就是一个 REST 应用程序。

The term RESTful was created because ppl exhausted the word REST by calling their non-REST application as REST. 此后,RESTful 一词也用尽了。 Nowadays we are talking about Web APIs and Hypermedia APIs,因为大多数所谓的 REST 应用程序没有满足统一接口约束的 HATEOAS 部分。

REST 约束如下:

客户端-服务器架构因此它不适用于例如 PUB/SUB 套接字,它基于 REQ/REP。无状态通信因此服务器不维护客户端的状态。这意味着您不能使用服务器端会话存储,并且您必须对每个请求进行身份验证。您的客户端可能通过加密连接发送基本身份验证标头。 (对于大型应用程序,很难维护许多会话。)如果可以的话,使用缓存因此您不必一次又一次地处理相同的请求。统一接口作为客户端和服务器之间的通用合约客户端和服务器之间的合约不由服务器维护。换句话说,客户端必须与服务的实现分离。您可以通过使用标准解决方案达到此状态,例如识别资源的 IRI (URI) 标准、交换消息的 HTTP 标准、描述正文序列化格式的标准 MIME 类型、元数据(可能是 RDF 词汇、微格式等)描述消息体不同部分的语义。要将 IRI 结构与客户端分离,您必须以超媒体格式(如 HTML、JSON-LD、HAL 等)向客户端发送超链接。因此,客户端可以使用分配给超链接的元数据(可能是链接关系,RDF 词汇)通过适当的状态转换来导航应用程序的状态机,以实现其当前目标。例如,当客户想要向网上商店发送订单时,它必须检查网上商店发送的响应中的超链接。通过检查链接,它找到了 http://schema.org/OrderAction 描述的链接。客户端知道 schema.org 词汇,因此它知道通过激活此超链接将发送订单。因此它会激活超链接并发送带有正确正文的 POST https://example.com/api/v1/order 消息。之后,服务处理消息并以具有正确 HTTP 状态标头的结果进行响应,例如 201 - 由成功创建。要使用详细元数据注释消息,使用 RDF 格式的标准解决方案,例如带有 REST 词汇的 JSON-LD,例如 Hydra 和特定于域的词汇,如 schema.org 或任何其他链接数据词汇,并且可能是自定义应用程序特定词汇,如果需要。现在这并不容易,这就是为什么大多数人使用 HAL 和其他简单格式,这些格式通常只提供 REST 词汇,但不支持链接数据。构建分层系统以增加可扩展性 REST 系统由分层组成。每一层都包含使用下一层组件服务的组件。因此,您可以毫不费力地添加新层和组件。例如,有一个包含客户端的客户端层,下面是一个包含单个服务的服务层。现在您可以在它们之间添加客户端缓存。之后,您可以添加另一个服务实例和负载均衡器,等等......客户端代码和服务代码不会改变。按需代码以扩展客户端功能 此约束是可选的。例如,您可以将特定媒体类型的解析器发送到客户端,等等...为了做到这一点,您可能需要客户端中的标准插件加载器系统,或者您的客户端将耦合到插件加载器解决方案.

REST 约束导致了一个高度可扩展的系统,其中客户端与服务的实现分离。所以客户端可以重复使用,就像网络上的浏览器一样。客户端和服务共享相同的标准和词汇,因此尽管客户端不知道服务的实现细节,但它们可以相互理解。这使得创建可以找到并利用 REST 服务来实现其目标的自动化客户端成为可能。从长远来看,这些客户端可以相互交流并在任务中相互信任,就像人类一样。如果我们向此类客户端添加学习模式,那么结果将是一个或多个 AI 使用机器网络而不是单个服务器园区。所以最终伯纳斯·李的梦想:语义网和人工智能将成为现实。所以在 2030 年,我们最终会被天网终结。直到那时 ... ;-)


k
kenorb

RESTful(具象状态转移)API 编程是按照以下 5 条基本软件architectural style原则以任何编程语言编写 Web 应用程序:

资源(数据、信息)。唯一的全局标识符(所有资源都由 URI 唯一标识)。统一接口 - 使用简单和标准的接口 (HTTP)。表示 - 所有通信都通过表示完成(例如 XML/JSON) 无状态(每个请求都完全隔离发生,更容易缓存和负载平衡),

换句话说,您正在通过 HTTP 编写简单的点对点网络应用程序,该应用程序通过实现 RESTful 架构来使用诸如 GET、POST、PUT 或 DELETE 之类的动词,该架构建议对每个“资源”公开的接口进行标准化。以简单有效的方式使用 Web 的当前功能(非常成功、经过验证的分布式架构),这不算什么。它是 SOAPCORBARPC 等更复杂机制的替代方案。

RESTful 编程符合 Web 架构设计,如果实施得当,它可以让您充分利用可扩展的 Web 基础架构。


K
Kal

这是我对 REST 的基本概述。我试图展示 RESTful 架构中每个组件背后的思想,以便更直观地理解这个概念。希望这有助于为某些人揭开 REST 的神秘面纱!

REST (Representational State Transfer) 是一种设计架构,它概述了如何设计和处理网络资源(即共享信息的节点)。一般来说,RESTful 架构使得客户端(请求机器)和服务器(响应机器)可以请求读取、写入和更新数据,而客户端不必知道服务器如何操作,服务器可以通过它返回而无需了解有关客户端的任何信息。好的,很酷......但是我们如何在实践中做到这一点?

最明显的要求是需要某种通用语言,以便服务器可以告诉客户端它试图对请求做什么并让服务器响应。

但是要找到任何给定的资源,然后告诉客户端该资源所在的位置,就需要有一种通用的方式来指向资源。这就是通用资源标识符 (URI) 的用武之地;它们基本上是查找资源的唯一地址。

但是 REST 架构并没有就此结束!虽然上面满足了我们想要的基本需求,但我们还希望有一个支持大流量的架构,因为任何给定的服务器通常处理来自多个客户端的响应。因此,我们不想让服务器记住有关先前请求的信息,从而使服务器不堪重负。

因此,我们强加了客户端和服务器之间的每个请求-响应对是独立的限制,这意味着服务器不必记住有关先前请求(客户端-服务器交互的先前状态)的任何信息来响应新的请求。要求。这意味着我们希望我们的交互是无状态的。

为了进一步减轻我们的服务器因重做最近已经为给定客户端完成的计算而造成的压力,REST 还允许缓存。基本上,缓存意味着对提供给客户端的初始响应进行快照。如果客户端再次发出相同的请求,服务器可以为客户端提供快照,而不是重做创建初始响应所需的所有计算。然而,由于它是一个快照,如果快照没有过期——服务器提前设置了一个过期时间——并且响应自初始缓存以来已经更新(即请求将给出与缓存响应不同的答案) ,客户端将不会看到更新,直到缓存过期(或缓存被清除)并且再次从头开始呈现响应。

关于 RESTful 架构,您在这里经常会遇到的最后一件事是它们是分层的。实际上,我们在讨论客户端和服务器之间的交互时已经隐含地讨论了这个要求。基本上,这意味着我们系统中的每一层仅与相邻层交互。所以在我们的讨论中,客户端层与我们的服务器层交互(反之亦然),但可能还有其他服务器层帮助主服务器处理客户端不直接与之通信的请求。相反,服务器会根据需要传递请求。

现在,如果这一切听起来很熟悉,那就太好了。通过万维网定义通信协议的超文本传输协议 (HTTP) 是 RESTful 架构的抽象概念的实现(或者,如果您像我一样是 OOP 狂热者,则可以实现抽象 REST 类)。在这种 REST 实现中,客户端和服务器通过 GET、POST、PUT、DELETE 等进行交互,这些都是通用语言的一部分,并且可以使用 URL 来指向资源。


很好的解释。
N
Nathan Andelin

如果我不得不将关于 REST 的原始论文缩减为 3 个简短的句子,我认为以下内容抓住了它的精髓:

通过 URL 请求资源。协议仅限于您可以使用 URL 进行通信的内容。元数据作为名称-值对(发布数据和查询字符串参数)传递。

在那之后,很容易陷入关于改编、编码约定和最佳实践的争论。

有趣的是,论文中没有提到 HTTP POST、GET、DELETE 或 PUT 操作。那一定是某人后来对“统一界面”的“最佳实践”的解释。

当谈到 Web 服务时,我们似乎需要某种方法来区分基于 WSDL 和 SOAP 的架构,这会增加相当大的开销,并且可能会给接口带来很多不必要的复杂性。它们还需要额外的框架和开发工具才能实现。我不确定 REST 是否是区分常识接口和过度设计的接口(如 WSDL 和 SOAP)的最佳术语。但我们需要一些东西。


s
suing

REST 是一种架构模式和编写分布式应用程序的风格。它不是狭义的编程风格。

说您使用 REST 风格类似于说您以特定风格建造房屋:例如 Tudor 或 Victorian。作为软件风格的 REST 和作为家庭风格的 Tudor 或 Victorian 都可以通过构成它们的质量和约束来定义。例如,REST 必须具有客户端服务器分离,其中消息是自描述的。都铎式风格的房屋有重叠的山墙和屋顶,这些屋顶陡峭地倾斜着面向前的山墙。您可以阅读 Roy 的论文,以了解有关构成 REST 的约束和质量的更多信息。

与家庭风格不同,REST 一直很难得到一致和实际应用。这可能是故意的。将其实际实现留给设计者。因此,只要您满足您正在创建 REST 系统的论文中规定的约束,您就可以自由地做您想做的事情。

奖金:

整个 Web 都是基于 REST(或者 REST 是基于 Web)。因此,作为一名 Web 开发人员,您可能希望了解这一点,尽管没有必要编写好的 Web 应用程序。


m
minghua

我认为 restful 的重点是将有状态分离到更高层,同时利用互联网(协议)作为无状态传输层。大多数其他方法都混淆了。

它是应对互联网时代编程根本变化的最佳实用方法。关于根本性的变化,Erik Meijer 在此处进行了讨论:http://www.infoq.com/interviews/erik-meijer-programming-language-design-effects-purity#view_93197。他将其概括为五种效果,并通过将解决方案设计成编程语言来提出解决方案。该解决方案也可以在平台或系统级别实现,而与语言无关。 restful 可以看作是目前实践中非常成功的解决方案之一。

使用 restful 风格,您可以在不可靠的互联网上获取和操作应用程序的状态。如果当前操作未能获得正确的当前状态,则需要零验证主体来帮助应用程序继续。如果它无法操纵状态,它通常会使用多个确认阶段来保持正确。从这个意义上说,rest 本身并不是一个完整的解决方案,它需要 web 应用程序堆栈的其他部分的功能来支持它的工作。

鉴于这种观点,其余风格并不真正与互联网或 Web 应用程序相关联。它是许多编程情况的基本解决方案。它也不简单,它只是让界面变得非常简单,并且可以很好地应对其他技术。

只是我的2c。

编辑:两个更重要的方面:

无国籍具有误导性。它是关于 RESTful API,而不是应用程序或系统。系统需要有状态。 Restful 设计是关于基于无状态 API 设计有状态系统。来自另一个 QA 的一些引用:REST,对资源表示进行操作,每个都由一个 URL 标识。这些通常不是数据对象,而是复杂的对象抽象。 REST 代表“代表性状态转移”,这意味着它完全是关于通信和修改系统中某些资源的状态。

REST 对资源表示进行操作,每个表示由 URL 标识。这些通常不是数据对象,而是复杂的对象抽象。

REST 代表“代表性状态转移”,这意味着它完全是关于通信和修改系统中某些资源的状态。

幂等性:REST 中一个经常被忽视的部分是大多数动词的幂等性。这导致了健壮的系统和更少的语义精确解释的相互依赖性。


MVC 观点:博客 Rest Worst Practices 建议不要混合模型和资源。书Two Scoops of django建议Rest API 是视图,而不是将业务逻辑混合到视图中。应用程序的代码应保留在应用程序中。
J
Jaider

REST 定义了 6 个架构约束,这些约束使任何 Web 服务成为真正的 RESTful API。

统一接口 客户端-服务器 无状态 可缓存 分层系统 按需代码(可选)

https://restfulapi.net/rest-architectural-constraints/


Fielding 添加了 some further rules RESTful API/客户端必须遵守
C
Chris DaMour

老问题,新的回答方式。关于这个概念有很多误解。我总是试图记住:

结构化 URL 和 Http 方法/动词不是 restful 编程的定义。 JSON 不是 RESTful 编程 RESTful 编程不适用于 API

我将宁静的编程定义为

如果应用程序以客户端理解的媒体类型提供资源(数据+状态转换控件的组合),则应用程序是宁静的

要成为一个安静的程序员,您必须尝试构建允许参与者做事的应用程序。不仅仅是暴露数据库。

只有当客户端和服务器就资源的媒体类型表示达成一致时,状态转换控制才有意义。否则就无法知道什么是控件,什么不是以及如何执行控件。 IE 如果浏览器不知道 html 中的 <form> 标签,那么您将没有任何东西可以提交到浏览器中的转换状态。

我不打算自我推销,但我会在我的演讲 http://techblog.bodybuilding.com/2016/01/video-what-is-restful-200.html 中深入探讨这些想法。

我演讲的摘录是关于经常提到的 Richardson 成熟度模型,我不相信这些级别,你要么是 RESTful(3 级),要么不是,但我想强调的是每个级别在通往 RESTful 的道路上为您服务

https://i.stack.imgur.com/YYS7O.png


我正在研究有关 API 的内容,特别是 REST 或 RESTful API。而且,尽管上面有很多赞成的答案,但我发现您的答案特别有趣,不是因为这个 SO 答案中的直接内容(尽管它也很有趣),而是因为您共享博客文章中的视频。它非常出色。您在实际实施后对 3 级/超媒体 API 的见解非常宝贵。它当然提供了编写 API 时的注意事项。
@MuhammadTalhaAkbar thx,感谢您的支持
k
kalin

这是非常长的“讨论”,但至少可以说相当混乱。

海事组织:

1) 没有安静的编程,没有大联合和大量啤酒 :)

2) 具象状态转移 (REST) 是 the dissertation of Roy Fielding 中指定的一种架构风格。它有许多限制条件。如果您的服务/客户尊重这些,那么它就是 RESTful。 就是这样。

您可以将约束(显着)总结为:

无状态通信

尊重 HTTP 规范(如果使用 HTTP)

清楚地传达传输的内容格式

使用超媒体作为应用程序状态的引擎

还有一个very good post很好地解释了事情。

很多答案复制/粘贴了有效信息,混合了它并增加了一些混乱。人们在这里谈论级别,关于 RESTFul URI(没有这样的东西!),应用 HTTP 方法 GET、POST、PUT ...... REST 不是关于那个或不仅仅是那个。

例如链接 - 拥有漂亮的 API 很好,但最终客户端/服务器并不真正关心您获取/发送的链接,重要的是内容。

最后,只要内容格式已知,任何 RESTful 客户端都应该能够使用任何 RESTful 服务。


P
Priyantha

REST === HTTP 类比是不正确的,除非您不强调它“必须”由 HATEOAS 驱动。

罗伊本人清除它here

除了初始 URI(书签)和适合目标受众(即,任何可能使用 API 的客户端都可以理解)的标准化媒体类型集之外,应该在没有任何先验知识的情况下输入 REST API。从那时起,所有应用程序状态转换必须由客户端选择服务器提供的选项驱动,这些选项出现在接收到的表示中或用户对这些表示的操作暗示。转换可以由客户端对媒体类型和资源通信机制的了解来确定(或限制),这两者都可以在运行中(例如,按需编码)得到改进。

[这里的失败意味着带外信息正在推动交互而不是超文本。]


没有像其他人一样回答这个问题,但为相关信息+1!
我认为这也回答了这个问题,但例如它缺少无国籍。每个约束都很重要……标准媒体类型部分并不总是正确的。我的意思是有层次的理解。例如,如果使用 RDF,则可以理解媒体类型,但不能理解内容的含义。所以客户也需要知道词汇。有些人正在尝试使用这种 REST API 和通用 REST 词汇来描述超链接等。hydra-cg.com
R
Rafiq

这个答案是为绝对初学者准备的,让我们了解一下当今最常用的 API 架构。

了解 Restful 编程或 Restful API。首先,您必须了解 API 是什么,在非常高级的 API 上代表应用程序编程接口,它基本上是一个软件,可以被另一个软件使用,以允许应用程序相互通信。

全球使用最广泛的 API 类型是 Web API,而应用程序在收到请求时向客户端发送数据。

https://i.stack.imgur.com/w9Dz3.png

事实上,API 不仅用于发送数据,而且并不总是与 Web 开发或 javascript 或 python 或任何编程语言或框架相关。

只要软件相对独立,API 中的应用程序实际上可以有很多不同的含义。以文件系统或 HTTP 模块为例,我们可以说它们是小软件,我们可以使用它们,我们可以使用它们的 API 与它们进行交互。例如,当我们对任何编程语言的文件系统模块使用读取文件功能时,我们实际上是在使用 file_system_reading API。或者当我们在浏览器中进行 DOM 操作时,我们并没有真正使用 JavaScript 语言本身,而是浏览器向我们公开的 DOM API,因此我们可以访问它。甚至另一个例子,假设我们用任何编程语言(如 Java)创建一个类,然后向它添加一些公共方法或属性,这些方法将成为从该类创建的每个对象的 API,因为我们正在为其他软件提供与我们最初的软件交互的可能性,在这种情况下是对象。 S0,API 实际上比仅仅构建 Web API 具有更广泛的含义。

现在让我们看一下构建 API 的 REST 架构。

代表 Representational State Transfer 的 REST 基本上是一种以逻辑方式构建 Web API 的方式,使它们易于为我们自己或他人使用。

要按照 REST 架构构建 Restful API,我们只需要遵循几个原则。 1.我们需要将我们的API分离成逻辑资源。 2. 然后应该使用基于资源的 URL 公开这些资源。 3. 要对数据执行不同的操作,例如读取、创建或删除数据,API 应该使用正确的 HTTP 方法而不是 URL。 4. 现在我们实际发送回客户端或从客户端接收到的数据通常应该使用 JSON 数据格式,是一些适用于它的格式标准。 5. 最后,EST API 的另一个重要原则是它们必须是无状态的。

https://i.stack.imgur.com/vZGhB.png

https://i.stack.imgur.com/yuEng.png

https://i.stack.imgur.com/6pt7j.png

我们的 API 将有许多不同的端点,如下所示

https://www.tourguide.com/addNewTour
https://www.tourguide.com/getTour
https://www.tourguide.com/updateTour
https://www.tourguide.com/deleteTour
https://www.tourguide.com/getRoursByUser
https://www.tourguide.com/deleteToursByUser

这些 API 中的每一个都会将不同的数据发送回客户端,同时执行不同的操作。现在这些端点有一些非常错误的地方,因为它们确实不遵循第三条规则,即我们应该只使用 HTTP 方法来对数据执行操作。所以端点应该只包含我们的资源,而不是我们对它们执行的操作,因为它们很快就会成为维护的噩梦。

https://i.stack.imgur.com/sLq20.png

(我们在端点或 URL 中只有资源,没有动词,因为动词现在在 HTTP 方法中,对吗?通常的做法是始终使用复数形式的资源名称,这就是我写 /tours 或 /tour 的原因。 ) 约定是,当调用端点 /tours 时将返回数据库中的所有旅游,但如果我们只想要一个 ID 的旅游,比如说七个,我们在另一个斜杠之后添加七个 (/tours/7)或在搜索查询 (/tours?id=7) 中,当然,它也可以是旅游的名称而不是 ID。

HTTP 方法:这里真正重要的是端点名称如何与所有人的名称完全相同。

GET: (for requesting data from the server.)

https://www.tourguide.com/tours/7
POST: (for sending data to the server.)
https://www.tourguide.com/tours
PUT/PATCH: (for updating requests for data to the server.) https://www.tourguide.com/tours/7
DELETE: (for deleting request for data to the server.)
https://www.tourguide.com/tours/7

PUT 和 PATCH 之间的区别-> 通过使用 PUT,客户端应该发送整个更新的对象,而使用 PATCH,它应该只发送已更改的对象部分。

通过使用 HTTP 方法,用户可以执行四种基本的 CRUD 操作,CRUD 代表 Create、Read、Update 和 Delete。

现在可能会出现如下情况:

https://i.stack.imgur.com/uNw9P.png

因此,/getToursByUser 可以简单地转换为 /users/tours,因为用户号 3 的端点将类似于 /users/3/tours。

如果我们要删除特定用户的特定游览,则 URL 应类似于 /users/3/tours/7,此处用户 ID:3 和游览 ID:7。

所以真的有很多这样的组合资源的可能性。

https://i.stack.imgur.com/XOzTh.png

https://i.stack.imgur.com/FeuPv.png

像我们在这里所做的那样将数据包装到一个额外的对象中称为 Enveloping,这是一种减轻一些安全问题和其他问题的常见做法。

Restful API 应该始终是无状态的:最后,RESTful API 应该始终是无状态的,这意味着在无状态的 RESTful API 中,所有状态都在客户端而不是服务器上处理。状态只是指应用程序中可能随时间变化的一段数据。例如,某个用户是否登录或在具有多个页面的列表的页面上当前页面是什么?现在,应该在客户端处理状态这一事实意味着每个请求都必须包含在服务器上处理某个请求所需的所有信息。因此,服务器永远不必为了处理当前请求而记住先前的请求。

https://i.stack.imgur.com/n4SJJ.png

假设目前我们在第五页,我们想前进到第六页。因此,我们可以有一个名为 /tours/nextPage 的简单端点并向服务器提交请求,但是服务器必须确定当前页面是什么,并基于该服务器将下一页发送到客户端。换句话说,服务器必须记住之前的请求。这正是我们希望在 RESTful API 中避免的。

而不是这种情况,我们应该创建一个 /tours/page 端点并将数字 6 粘贴到它以请求第 6 页 /tours/page/6 。所以服务器不需要记住任何内容,它所要做的就是按照我们的要求发回第 6 页的数据。

无状态和相反的状态是计算机科学和一般应用中非常重要的概念


G
GowriShankar

REST 代表 Representational state transfer。

它依赖于无状态、客户端-服务器、可缓存的通信协议——几乎在所有情况下都使用 HTTP 协议。

REST 通常用于移动应用程序、社交网络网站、混搭工具和自动化业务流程。 REST 风格强调通过有限数量的操作(动词)来增强客户端和服务之间的交互。通过为资源(名词)分配它们自己独特的通用资源指示符(URI)来提供灵活性。

Introduction about Rest


q
qmckinsey

谈话不仅仅是简单地交换信息。协议实际上被设计为不必发生对话。每一方都知道他们的特定工作是什么,因为它在协议中有所规定。协议允许纯粹的信息交换,代价是对可能的操作进行任何更改。另一方面,谈话允许一方询问另一方可以采取哪些进一步的行动。他们甚至可以两次问同一个问题并得到两个不同的答案,因为对方的状态可能在此期间发生了变化。 Talking 是 RESTful 架构。菲尔丁的论文详细说明了如果一个人想要让机器相互交谈而不是简单地通信,就必须遵循的架构。


A
ACV

本身不存在“RESTful 编程”这样的概念。最好称为 RESTful 范式,甚至更好的 RESTful 架构。它不是一种编程语言。这是一个范式。

From Wikipedia

在计算中,代表性状态转移 (REST) 是一种用于 Web 开发的架构风格。


B
Benoit Essiambre

剩下的一点是,如果我们同意对基本操作(http 动词)使用通用语言,则可以配置基础设施以理解它们并适当优化它们,例如,通过使用缓存标头来实现缓存水平。

通过正确实施的 RESTful GET 操作,信息来自服务器的数据库、服务器的内存缓存、CDN、代理的缓存、浏览器的缓存还是浏览器的本地存储都无关紧要。可以使用禁食的、最容易获得的最新源。

说 Rest 只是从使用带有操作参数的 GET 请求到使用可用的 http 动词的句法变化,这使它看起来没有任何好处,而且纯粹是装饰性的。关键是使用一种可以被链的每个部分理解和优化的语言。如果你的 GET 操作有副作用,你必须跳过所有的 HTTP 缓存,否则你会得到不一致的结果。


“说 Rest 只是一种句法变化……让它看起来没有任何好处,纯粹是装饰性的”——这正是我在 SO 上阅读答案的原因。请注意,您没有解释为什么 REST 不是纯粹的装饰。
K
Krishna Ganeriwal

这一点在所有地方都很少提及,但 Richardson 的成熟度模型是实际判断 Restful 是一个 API 的最佳方法之一。更多关于它的信息:

Richardson's Maturity Model


如果您查看 Fielding 对 REST 的约束,您会清楚地看到 API 需要达到 RMM 的第 3 层才能被视为 RESTful,尽管这实际上还不够,因为仍有足够的可能性失败REST 理念——客户端与服务器 API 的分离。当然,第 3 层满足 HATEOAS 约束,但仍然很容易打破要求并将客户端紧密耦合到服务器(即通过使用类型化资源)
K
Krrishnaaaa

什么是 API Testing

API 测试利用编程向 API 发送调用并获得收益。它测试将被测段视为黑匣子。 API 测试的目的是确认在将其协调到应用程序之前的部分的正确执行和错误处理。

REST API

REST:具象状态转移。

这是测试人员执行请求和接收响应的功能安排。在 REST API 中,交互是通过 HTTP 协议进行的。

REST 还允许计算机之间通过网络进行通信。

对于发送和接收消息,它涉及使用 HTTP 方法,并且不像 Web 服务那样需要严格的消息定义。

REST 消息通常接受 XML 或 JavaScript Object Notation (JSON) 形式的形式。

4 种常用 API 方法:-

GET: – 它提供对资源的只读访问。 POST:——用于创建或更新新资源。 PUT: – 用于更新或替换现有资源或创建新资源。 DELETE: – 用于删除资源。

手动测试 API 的步骤:-

要手动使用 API,我们可以使用基于浏览器的 REST API 插件。

安装 POSTMAN(Chrome) / REST(Firefox) 插件 输入 API URL 选择 REST 方法 选择 content-Header 输入请求 JSON (POST) 点击发送 会返回输出响应

Steps to Automate REST API


这甚至不是一个正确的答案
K
Kürsat Aydinli

我想说理解 REST 的一个重要组成部分在于端点或映射,例如 /customers/{id}/balance

您可以将这样的端点想象为从网站(前端)到数据库/服务器(后端)的连接管道。使用它们,前端可以执行在应用程序中任何 REST 映射的相应方法中定义的后端操作。