【问题标题】:HTML interface to RESTful web service *without* javascriptRESTful Web 服务的 HTML 接口 *无 * javascript
【发布时间】:2010-11-19 04:21:09
【问题描述】:

即使我提供了 PUT 和 DELETE 的替代方法(参见“低 REST”),我如何为从浏览器访问我的 Web 服务的用户提供用户友好的表单验证,同时仍然公开 RESTful URI?表单验证问题(如下所述)是我目前的困惑,但我想问的更广泛的问题是:如果我沿着尝试提供 RESTful 公共接口 非 JavaScript HTML界面,它会让生活更轻松还是更难?他们一起玩吗?

理论上,这应该只是改变输出格式的问题。机器可以查询 URL“/people”,并以 XML 格式获取人员列表。人类用户可以将他们的浏览器指向同一个 URL,并获得漂亮的 HTML 响应。 (我用的是URL examples from the microformats wiki,看起来还算合理)。

通过对“/people”URL 的 POST 请求创建新的人员资源。为此,人类用户可以首先访问“/people/new”,它会返回一个静态 HTML 表单来创建资源。该表单具有 method=POST 和 action="/people"。如果用户的输入是有效的,这将正常工作,但是如果我们在服务器端进行验证并发现错误怎么办?友好的做法是返回表单,其中包含用户刚刚输入的数据以及错误消息,以便他们可以解决问题并重新提交。但是我们不能直接从 POST 将输出返回到“/people”,否则会破坏我们的 URL 系统,如果我们将用户重定向回“/people/new”表单,则无法报告错误并且重新填充表单(除非我们将数据存储到会话状态,否则 RESTful 会更少)。

使用 javascript,事情会容易得多。只需在后台执行 POST,如果失败,则在表单顶部显示错误。但我希望应用程序在 javascript 支持不可用时优雅地降级。目前,我得出的结论是,一个重要的 Web 应用程序无法在没有 javascript 的情况下实现 HTML 界面,并且使用传统的 RESTful URL 方案(例如微格式 wiki 上描述的方案)。如果我错了,请告诉我!

有关 Stack Overflow 的相关问题(均不涉及表单验证):

【问题讨论】:

  • @Todd 没有“低 REST”之类的东西 - 正如您所知,REST 确实允许规避协议标准,只要由于不正确的客户端实现是必要的,即仅 HTML4支持 POST/GET。

标签: html forms rest webforms


【解决方案1】:

感谢您的回复。他们让我的思想解放了一点,所以在回答我自己的问题时,我想提出一组替代的 RESTful URL 约定,实际上 embrace 这两种方法(GET和 POST) 的非 AJAX 世界,而不是试图解决它们。

编辑:正如评论者所指出的,这些“约定”不应成为 RESTful API 本身的一部分。另一方面,internal 约定很有用,因为它们使服务器端实现更加一致,因此开发人员更容易理解和维护。然而,RESTful 客户端应该将 URL 视为不透明的,并始终将它们作为超链接获取,而不是通过自己构建 URL。

获取/人
返回所有记录的列表
GET /people/new
返回用于添加新记录的表单
POST /people/new
创建新记录
(对于 HTML 客户端,如果输入无效,则再次返回表单,否则重定向到新资源)
GET /people/1
返回第一条记录
GET /people/1/edit
返回用于编辑第一条记录的表单
POST /people/1/edit
更新第一条记录
GET /people/1/delete
返回删除记录的表单
(可能只是一个确认 - 您确定要删除吗?)
POST /people/1/delete
删除记录

这里有一个模式:获取资源,例如“/people/1”,返回记录本身。 GET on resource+operation 返回一个 HTML 表单,例如“/人/1/编辑”。 POST on resource+operation 实际执行的是操作。

也许这不如使用额外的 HTTP 动词(PUT 和 DELETE)那么优雅,但这些 URL 应该可以很好地与普通 HTML 表单一起使用。对于人类用户来说,它们也应该是不言自明的……我相信“URL 是 UI 的一部分”,用户可以通过浏览器访问 Web 服务器。

附:让我解释一下我将如何进行删除。 “/people/1”视图将有一个指向“/people/1/delete”的链接,带有一个 onclick javascript 处理程序。启用 javascript 后,点击会被拦截,并会向用户显示一个确认框。如果他们确认删除,则会发送 POST,立即删除记录。但是如果 javascript 被禁用,单击链接将改为发送一个 GET 请求,该请求从服务器返回一个删除确认表单,那个 表单发送 POST 以执行删除。因此,javascript 改善了用户体验(更快的响应),但没有它,网站会优雅地降级。

【讨论】:

  • 您真的要创建一个 RESTful 接口吗?如果是这样,请停止尝试创建 URL 约定。除此之外,我在这里没有看到任何你不能用 AtomPub 做的事情。为什么要重新发明轮子?
  • 将 URI 约定定义为 API 的一部分意味着您的 API 是 RPC。 URI 必须可通过超文本发现,从单个入口点 URI 开始。见:roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
  • 谢谢,我会记住的。在这种情况下,我列出的 URL 不是 API 的一部分,而只是一个实现决策…… RESTful 客户端不应该注意这一点。它们恰好实现起来相当方便(至少在 Struts 2 中,这是我正在使用的框架),并且还与普通 HTML 表单兼容。 [已编辑答案以澄清这一点。]
  • @Todd 这很合理,漂亮的 URI 没有任何错误。只要确保它们可以通过超文本被发现。
【解决方案2】:

为什么要使用 XML 创建第二个“API”?

您的 HTML 包含您的用户需要查看的数据。 HTML 相对容易解析。类属性可用于像微格式一样添加语义。您的 HTML 包含能够访问应用程序所有功能的表单和链接。

您为什么要创建另一个界面来提供完全无语义的应用程序/xml,而该应用程序/xml 可能不包含超媒体链接,因此您现在必须将 url 硬编码到您的客户端中,从而产生令人讨厌的耦合?

如果您可以在 Web 浏览器中使用 HTML 来让您的应用程序运行而无需存储会话状态,那么您已经拥有了一个 RESTful API。不要试图设计一堆与某人的标准想法相对应的 URL。

这是来自 Roy Fielding 的 quote

REST API 不得定义固定的 资源名称或层次结构

我知道这与您见过的几乎所有 REST 示例背道而驰,但那是因为它们都是错误的。我知道我开始听起来像一个宗教狂热者,但是看到人们在完全错误的基础上努力设计 RESTful API 时,我感到很沮丧。

听听 Breton 说“REST 不在乎 [url] 长什么样”,@Wahnfrieden 很快就会告诉你同样的事情。对于尝试做 REST 的人来说,那个微格式页面是可怕的建议。我并不是说对于创建某种其他类型的 HTTP API(而不是 RESTful API)的人来说这是一个糟糕的建议。

【讨论】:

  • 感谢您提供的信息链接。实际上,我并不立即需要 XML 接口,但我认为它是对干净的应用程序架构(特别是表示与业务逻辑的分离)的一个很好的测试。如果应用程序可以发出除了 HTML 之外的 XML,而开发人员只需付出最小的努力,那么发出将来可能需要的 any 输出格式应该很容易。
  • HTML 很容易变成 XML 的子集。
  • @Todd,这又回到了我的观点,即 RESTful 接口用于将内容暴露给“用户代理”而不是商业数据给消费者应用程序。这就是 Web 服务的用途。我认为 RESTful 接口和 Web 服务可以解决两个不同的问题。
【解决方案3】:

您可以将 html 表单直接发布到 /people/new。如果验证失败,请使用适当的信息重新呈现编辑表单。如果成功,则将用户转发到新 URL。据我了解,这与 REST 架构是一致的。

我看到你对 Monis Iqbal 发表评论,我不得不承认我不知道你所说的“非 RESTful URL”是什么意思。 REST 体系结构对 URL 的唯一要求是它是不透明的,并且它必须唯一地与资源配对。 REST 不关心它的外观、其中的内容、斜线或使用的方式、使用的数量或类似的东西。 URL 的可视化设计取决于您,而 REST 没有任何影响。

【讨论】:

  • “非 RESTful”我的意思是它不符合 http//microformats.org/wiki/rest/urls 上概述的建议,它建议通过 POST 创建新资源对人民来说”。不过我明白你的意思——我的界面可以很容易地变成:GET "/people/new" = 空白表单,POST "/people/new" = 创建资源。
  • 哦,是的,这些建议。我记得他们是什么时候发明的。请注意顶部的 ruby​​ on rails 曾经使用 ;edit 和 ;new ?那是我愚蠢的想法,因为在我看来,edit 和 new 并不像 /people 中的 seperate 资源,只是呈现相同资源的不同方式。所以我发现分号可以用来表示,而不是子关系/暗示。 ;虽然破坏了野生动物园,所以flltt。
  • 在任何情况下,您也可以对其建模,以便 POST /people 呈现您的“新”表单,但会发出有关问题所在的警报。
  • 这样你就可以遵循建议,并且你的 api 可以被它所说的与该表单兼容的那些东西使用。
  • 回想起来我希望我建议。反而。那么你仍然有区别,但你最终不会破坏野生动物园。
【解决方案4】:

为什么不在客户端使用 AJAX 来完成工作,如果禁用了 javascript,那么设计 html 以便传统的 POST 可以工作。

【讨论】:

  • 嗯,我可以让它工作,可能是通过将 HTML 表单发布到“/people/new”。但这意味着使用非 RESTful URL,再次让我得出结论,即普通 HTML 表单根本不符合 REST 哲学。
  • @Todd “RESTful URLs”是一个不存在的概念。 REST 对 URI 没有任何规定,只是它们必须是不透明的。
  • 我发布了一个关于 HTML 表单如何适应 REST 的类似问题。看看吧
  • IMO 实际的 HTML 表单界面与 REST 是分开的。表单应该能够根据 REST API 的知识构建,而不是通过与 API 交互来构建。
猜你喜欢
  • 1970-01-01
  • 2014-09-01
  • 1970-01-01
  • 2011-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多