仅用四种HTTP方法创建RESTful API?
目前我正在尝试构建一个基于HTTP的RESTful后端框架。
我读过一本叫《RESTful Web Services》的书,这让我在这个领域开始思考。
现在我对资源导向架构有了更全面的理解,但仍然有一些模糊的地方我搞不清楚。我会试着解释我的想法,看看有没有人能让我更明白。
难道不能说所有东西都是对象吗?比如车、笔、书,甚至像想法和概念这样的抽象东西也可以是对象。因为“对象”这个词只是人类发明出来的,用来表示“某样东西”。
难道你也不能说每个“某样东西”都是资源吗?比如硬币、电脑,甚至债务都可以是资源。但问题是,资源对谁来说?债务是资源,但对欠债的人来说不是,而是对他所欠的人来说。人类的废弃物也是资源,但对我们来说不是,而是对大自然,因为大自然需要平衡——进与出——这是科学(编程)的基本原则。
资源(对象)似乎都是名词。那么形容词和动词呢?实际上,似乎所有东西都可以用名词来描述。例如:
- 形容词:车是红色的
- 名词:车有一种红色
- 形容词:我很累
- 名词:我有一种疲惫
- 动词:我杀了他
- 名词:我创造了一次杀戮
- 动词:我吻了她
- 名词:我创造了一次吻
这意味着资源 = 对象 = 名词。从不同的角度看同样的“某样东西”。
也许有些动词和形容词没有名词对应,但那只是人类语言的缺陷,而不是概念本身的问题。
回到最开始的问题。
当我认真思考只有四个(我知道还有更多)HTTP动词——POST、GET、PUT、DELETE——时,我觉得这不能创建强大的RESTful API,因为它们限制了API只能进行基本的CRUD操作。但经过一些阅读和思考,我意识到所有东西只是资源,可以被创建、读取、修改或删除。就像进与出,简单的规则,但却强大到可以创造任何东西。
但我又想,只有“进”和“出”。也许只有“创建”和“删除”。因为GET和PUT这两个动词可以用“创建一个读取”和“创建一个更改”来替代。
这一切只是我在玩弄自然法则的基本概念。进与出,创建与删除。前者在编程领域已经被广泛接受。但后者就不太常听到了。但如果这是正确的,那就意味着HTTP RESTful API可以用来创造任何东西,只要方法正确,而不是通过修改版本(把动词放在URI、请求体等)来黑客式实现,而是仅仅使用POST、GET、PUT、DELETE。
我们只需要把所有方法转换为资源/对象。不是:
result = Books.search("Foo");
我们需要思考:
result = Search.create(Books, "Foo");
你对此怎么看?考虑到这一点,难道仅用四个HTTP方法就能创建任何类型的RESTful API吗?“创建”和“删除”是否是自然法则的另一部分?
5 个回答
RESTful API其实就是一种和数据存储打交道的方式,比如数据库、文件系统或者分布式哈希表等等。这意味着你不需要特别复杂的操作方式,因为用GET、PUT、POST和DELETE这几个常用的方式就能完成所有的工作。
另外,RESTful API特别强调要用现有的HTTP方法来进行资源的增删改查(CRUD)。而且,API不需要复杂或者冗长才能有用,甚至能很强大。大多数情况下,简单就是你的好朋友。简单的结构和接口,往往比复杂的结构和接口更有效。比如git,它使用的数据结构非常简单,因此运行起来也非常快。
至于你的问题:没错,人们经常这样做,而且效果很好!
你可以只用两种方法来创建任何系统,分别是GET和POST。可以把GET理解为“读取”,把POST理解为“写入”。其他的方法只是为了让请求更清晰一些。
如果你真的想把REST请求用对象来表示,我会这样做:
result = new Search(Books,"Foo").Get();
不过,我不太确定这种映射是否真的有用。
我觉得你在说一个RESTful API的两个不同方面。把HTTP方法简化成IN和OUT,其实已经通过请求和响应实现了。没错,你可以把读取操作对应到GET,把创建操作对应到PUT,但那DELETE呢?它算不算是“把内容放0进去的PUT”?如果是这样的话,你就需要一些逻辑来处理这种情况。
举个例子,当你在文本编辑器里打开一个文档时,你是在往操作系统(OS)里进行一个IN操作,而操作系统则是把内容OUT到文本编辑器里。保存文档时则正好相反。
但这只是一些简单的操作机制。没错,文本编辑器可以把IN用GET表示,把OUT用PUT表示,比如“另存为”,但DELETE呢?这就需要一个自己的动词,或者把PUT/OUT的动作重载到操作系统上。还有POST,它相当于保存操作。我们要不要把PUT方法重载,去检查文件是否已经存在?为什么不直接给它一个自己的动词呢?
如果你要简化成IN和OUT,那你就得重载OUT:
if(OUT){
if(file_exists) update_file
else if(file_size==0) delete_file
else create_file
}
*当然,我说的更多是理论上的,zzzBov在他关于HTTP规范的帖子里是对的。