设计合适的RESTful URI

4

我有一个Java组件,可以扫描一组文件夹(input/processing/output),并以JSON格式返回文件列表。

相应的REST URL为:

GET http://<baseurl>/files/<foldername>

现在,我需要对每个文件执行某些操作,例如验证、处理、删除等。我不确定如何设计这些操作的 REST URL 最佳方式。由于这是直接文件操作,除了文件路径之外,我没有任何唯一标识符可用。因此,我不确定以下是否是一个好的 URL:
POST http://<baseurl>/file/validate?path=<filepath>

编辑:我本来希望使用类似于 /file/fileId/validate 这样的内容。但是文件的唯一标识符仅为其路径,我不认为我可以将其用作 URL 的一部分。

最后,我不确定在这种自定义操作(例如 validate)中应使用哪个 HTTP 动词。

提前感谢!

敬礼, 安南德

3个回答

2
当您实现像http:///file/validate?path这样的路由时,您会将操作编码到资源中,这不是建模资源服务时期望的效果。
对于读取操作,您可以执行以下操作:
GET http://api.example.com/files将返回所有文件的URL引用,例如:
http://api.example.com/files/path/to/first
http://api.example.com/files/path/to/second
...

GET http://api.example.com/files/path/to/first 将返回文件的验证结果(我使用JSON来提高可读性)

{
   name : first,
   valid : true
}

那是一个简单的只读部分。现在是关于写操作
DELETE http://api.example.com/files/path/to/first 当然会删除该文件。
建模文件处理是困难的部分。但你可以将其建模为顶层资源。那样:
POST http://api.example.com/FileOperation?operation=somethingweird 将创建一个虚拟文件处理资源并执行由URL参数 'operation' 给出的操作。将这些文件操作建模为资源,可以让您异步执行操作并返回有关操作过程的附加信息等结果。
您可以查看Amazon S3 REST API获取其他示例和建模资源的灵感。我强烈推荐阅读RESTful Web Services

1
现在,我需要对每个文件执行某些操作,例如验证、处理、删除等。我不确定为这些操作设计REST URL的最佳方式。由于这是直接的文件操作,除了它们的路径之外,我没有任何唯一标识文件的信息。所以,我不确定以下是否是一个好的URL:POST http:///file/validate?path= 答案:不是。/file/validate 不描述资源,而是描述行为。这意味着它是函数式的,而不是符合REST原则的。
编辑:理想情况下,我希望使用类似 /file/fileId/validate 这样的东西。但文件的唯一标识符只有其路径,我不认为我可以将其作为URL本身的一部分使用。

没错,你可以这样做!而且你应该这样做。除了最后的validate部分;那不是任何资源的一部分,因此不应该是路径的一部分。相反,客户端应该向文件资源POST一个消息,要求它验证自己。幸运的是,POST允许您发送消息到文件,并接收回复;这对于这种情况非常理想(除非有现有的动词可用,无论是在标准HTTP中还是在扩展之一,如WebDAV中)。

最后,我不确定应该使用哪个HTTP动词来执行验证这样的自定义操作。

使用POST,由POST到资源的消息内容确定要执行的操作。当无法映射为GET、PUT或DELETE时,自定义的“执行某些非标准操作”总是映射到POST。(遗憾的是,聪明的POST不能很好地被发现,因此会对HATEOAS原则造成问题,但仍然比违反基本REST原则好。)


1

REST要求一个统一的接口,在HTTP中意味着限制自己只使用GET、PUT、POST、DELETE、HEAD等方法。

你可以以RESTful的方式检查每个文件的有效性,其中一种方法是将有效性检查视为资源本身,而不是对文件执行的操作:

GET /file/{file-id}/validity

这可能会返回一个简单的True/False,或者是特定约束违规的列表。 文件ID可以是文件名、整数文件号、URL编码的路径,或者是未编码路径,例如:

GET /file/bob/dir1/dir2/somefile/validity

另一种方法是要求提供无效文件列表:
GET /file/invalid

还有一个方法是防止无效的文件首先被添加到您的服务中,即当您的服务处理具有错误数据的PUT请求时:

PUT /file/{file-id}

如果请求不符合要求,它会拒绝并返回HTTP 400(错误请求)状态码。400响应的正文可能包含有关特定错误的信息。

更新:要删除文件,您当然可以使用标准的HTTP REST动词:

DELETE /file/{file-id}

如何“处理”一个文件,这会从上传的文件创建一个新的文件(资源)吗?例如 Flickr 会从每个上传的图像文件创建多个不同尺寸的文件。在这种情况下,您可以 PUT 一个输入文件,然后通过 GET 相应的输出文件来触发处理:
PUT /file/input/{file-id}     
GET /file/output/{file-id}

如果处理不是几乎瞬间完成的,您可以异步生成输出文件:每当新的输入文件被放入 Web 服务中时,Web 服务启动一个异步活动,最终导致创建输出文件。

根据Fielding的说法,你的第一句话是不正确的:“REST风格并不建议限制方法集是一个可取的目标。[...]特别是,REST鼓励为模糊操作创建新的方法,正是因为我们不想让常见的方法承担所有逻辑的负担,试图弄清楚特定操作是否符合99.9%的情况或占0.1%的其他情况。”来源:http://xent.com/pipermail/fork/2001-August/003191.html 话虽如此,我喜欢你将有效性作为资源本身的想法。 - tuespetre
此外,状态码 400 更多地针对服务器本身,比如 Apache,在收到格式错误的请求时使用——而不是当应用程序认为媒体类型格式错误时使用。这将使用状态码 422 不可处理实体。 - tuespetre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接