我有一个服务,它接受一个.odt模板文件和一些文本值,并产生一个.odt作为它的输出.我需要通过HTTP提供此服务,我不太清楚什么是使REST接口工作的最RESTful方式.
我需要能够将模板文件和输入值提供给服务器 - 并将生成的.odt文件发送给我.我看到的关于它如何工作的选项是:
(1)的问题是我不想将模板文件存储在服务器上.这增加了复杂性并且存储文件对我来说没有用,除了它是一个非常RESTful的方法.此外,单个请求优于2,所有其他条件相同.
(2)的问题是将一个正文放在一个GET请求中接近滥用HTTP - 我现在使用的软件支持它,但可能并不总是如此.
数字(3)似乎具有误导性,因为这更像是"阅读"或"获取"操作而不是"帖子".
我在做什么本质上是一样的函数调用-我需要传递数据的显著量中,和我真的只是使用HTTP作为整个网络暴露我的代码的一种便捷方式.也许我正在尝试做的本质上是非RESTful,并且没有REST友好的解决方案?任何人都可以建议吗?谢谢!
哇,所以这个答案迅速升级......
在过去一年左右的时间里,我试图通过书籍,邮件列表等方式更好地理解REST.出于某种原因,我决定选择你的问题来测试我学到的东西.
对不起:P
让我们让整个例子更简单一步.我们不会担心用户上传文件,而是假设用户只是传递一个字符串.所以,实际上,除了要替换的字符的参数(键/值列表)之外,它们还将传递一个字符串.我们稍后将处理文件上传部分.
这是一种RESTful方式,它不需要存储在服务器上的任何东西.我将使用一些HTML(虽然已经破坏,我会省略像HEAD这样的东西)作为我的媒体类型,只是因为它是众所周知的.
首先,用户需要访问我们的REST服务.
GET /
<body>
<a rel="http://example.com/rels/arguments" href="/arguments">
Start Building Arguments
</a>
</body>
Run Code Online (Sandbox Code Playgroud)
这基本上为用户提供了一种开始实际与我们的服务交互的方法.现在他们只有一个选项:使用链接构建一组新的参数(最终将在字符串替换方案中使用的名称/值对).所以用户转到该链接.
GET /参数
<body>
<a rel="self" href="/arguments"/>
<form rel="http://example.com/rels/arguments" method="get" action="/arguments?{key}={value}">
<input id="key" name="key" type="text"/>
<input id="value" name="value" type="text"/>
</form>
<form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}">
<input id="input_string" name="input_string" />
</form>
</body>
Run Code Online (Sandbox Code Playgroud)
这将我们带到一个"参数"资源的实例.请注意,这不是一个JSON或XML文档,只返回键/值对的明确数据; 它是超媒体.它包含控件,指导用户下一步做什么(有时称为允许用户"跟随他们的鼻子").此特定URL("/ arguments")表示键/值对的空列表.如果我愿意的话,我很可能已将url命名为"/ empty_arguments":这是一个例子,为什么在URL方面考虑REST是愚蠢的:它实际上应该与URL无关.
在这个新的HTML中,用户可以获得三种不同的资源,可以导航到:
注意:你可能注意到第二个表单有一个奇怪的"动作"url:
/arguments?{key}={value}
在这里,我作弊:我正在使用URI模板.这允许我指定如何将参数放置到URL上,而不是使用仅使用的默认HTML方案<input-name>=<input-value>
.显然,为了使其工作,用户不能使用浏览器(因为浏览器不实现这一点):他们需要使用理解HTML 和 URI模板的软件.当然,我使用HTML作为示例,您的REST服务可以使用某种支持URI模板规范的URI模板的XML.
无论如何,假设用户想要添加他们的参数.用户使用第一种形式(例如,用"作者"填写"键"输入,用"John Doe"填写"值"输入).这导致......
GET/arguments?作者= John%20Doe
<body>
<a rel="self" href="/arguments?Author=John%20Doe"/>
<form rel="http://example.com/rels/arguments" method="get" action="/arguments?Author=John%20Doe&{key}={value}">
<input id="key" name="key" type="text"/>
<input id="value" name="value" type="text"/>
</form>
<form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}?Author=John%20Doe">
<input id="input_string" name="input_string" />
</form>
</body>
Run Code Online (Sandbox Code Playgroud)
这是一个全新的资源.您可以将其描述为具有单个键/值对的参数列表(键/值对):"作者"/"John Doe".HTML与以前几乎完全相同,只有一些变化:
用户现在想要添加"Date"参数,因此他们再次提交第一个表单,这次使用"Date"键和值"2003-01-02".
GET/arguments?作者= John%20Doe&Date = 2003-01-02
<body>
<a rel="self" href="/arguments?Author=John%20Doe&Date=2003-01-02"/>
<form rel="http://example.com/rels/arguments" method="get" action="/arguments?Author=John%20Doe&Date=2003-01-02&{key}={value}">
<input id="key" name="key" type="text"/>
<input id="value" name="value" type="text"/>
</form>
<form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}?Author=John%20Doe">
<input id="input_string" name="input_string" />
</form>
</body>
Run Code Online (Sandbox Code Playgroud)
最后,用户已准备好处理其字符串,因此他们使用第二种形式并填写"input_string"变量.这再次使用URI模板,从而将用户带到下一个资源.假设该字符串如下:
{Author} wrote some books in {Date}
结果将是:
GET/processed_string /%7BAuthor%7D +写了+一些+书+ +%7BDate%7D?作者= John%20Doe&Date = 2003-01-02
<body>
<a rel="self" href="/processed_string/%7BAuthor%7D+wrote+some+books+in+%7BDate%7D?Author=John%20Doe&Date=2003-01-02">
<span class="results">John Doe wrote some books in 2003-01-02</span>
</body>
Run Code Online (Sandbox Code Playgroud)
唷!这是很多工作!但它是(AFAIC)RESTful,它满足了不需要在服务器端实际存储ANYTHING的要求(包括参数列表或您最终想要处理的字符串).
这里重要的一件事是我不只是在谈论URL.事实上,大多数时候,我在谈论HTML.HTML是超媒体,它是REST中如此巨大的一部分,被遗忘了.所有那些说他们"安静"的API,他们说"使用这些参数在这个URL上进行GET,并使用看起来像这样的文档在这个URL上进行POST"并不是在练习REST.Roy Fielding(他真的写了关于REST的书)自己做了这个观察.
另一件需要注意的事情是,设置参数是非常痛苦的.在初始GET /到达服务的根目录(您可以将其视为"菜单")之后,您需要再进行五次GET调用以构建您的参数资源以使参数资源为四个密钥/值配对.这可以通过不使用HTML来缓解.例如,我在我的示例中已经使用了URI模板,没有理由说HTML对于REST来说不够好.使用支持类似于表单的超媒体格式(如某些XML派生),但能够指定值的"映射",您可以一次性完成.例如,我们可以扩展HTML媒体类型以允许另一种称为"映射"的输入类型......
只要使用我们的API的客户端理解"映射"输入类型是什么,他们就能够使用单个GET构建其参数资源.
那时,您甚至可能不需要"参数"资源.您可以直接跳到包含映射和实际字符串的"processed_string"资源...
好的,所以最初你提到了文件上传,以及如何在不需要存储文件的情况下获取文件.好吧,基本上,我们可以使用现有的示例,但用文件替换最后一步.
在这里,除了我们上传文件外,我们基本上都在做同样的事情.需要注意的是,现在我们向用户暗示(通过表单上的"方法"属性)他们应该进行POST而不是GET.请注意,即使在任何地方您都听到POST是不安全的(它可能导致服务器上的更改),非幂等操作,但没有任何迹象表明它必须是服务器上的更改状态.
最后,服务器可以返回新文件(更好的方法是返回一些带有新文件链接的超媒体或LOCATION标题,但这需要存储).
这只是这个具体例子的一个例子.虽然我希望你获得某种洞察力,但我要提醒你接受这个作为福音.我确信有些事情我说的并不是真正的"REST".我打算发布这个问题并回答REST-Discuss邮件列表,看看其他人对此有什么看法.
我希望通过这一点表达的一个主要问题是,最简单的解决方案可能只是使用RPC.毕竟,你最初尝试使RESTful试图完成的是什么?如果你试图告诉别人你完成了"REST",请记住,有很多API声称自己"RESTful",它们实际上只是被带有名词而不是动词的URL伪装成RPC.
如果是因为您已经听说过REST的一些好处,以及如何通过使您的API RESTful来隐含地获得这些好处,那么不幸的事实是,REST比URL更多,无论您是GET还是POST.超媒体起着重要作用.
最后,有时您会遇到一些问题,这些问题意味着您可能会执行SEEM非RESTful的操作.也许您需要执行POST而不是GET,因为URI(具有理论上无限量的存储空间,但存在大量技术限制)会变得太长.那么,你需要做POST.也许
更多资源:
归档时间: |
|
查看次数: |
2627 次 |
最近记录: |