我希望堆栈溢出可以接受这个问题,而不是标记为“基于意见”。至少我试试......
我与一家必须为我们开发Web应用程序的供应商进行了交谈,协议是使用RESTful接口访问我的基础架构提供的服务。
REST界面将由我的团队开发,他们的团队将开发UI界面。 API处于高级开发状态,并且由我公司使用的主应用程序使用,因此我必须扩展它以适应这个新的webapp。
他向我发送了一份草稿文档,用于连接他们的客户端应用程序,告诉我开发这样的服务:
http://1.2.3.4:8080/getGPSPositions
告诉我:1)Web前端将使用POST在上述URL上询问其请求 2)前端将发送使用JSON序列化的对象,格式为s(简化)
{
serviceID: <number>
fromDate: <date>
toDate: <date>
customSQLWhere: <string>
customSQLOrderBy: <string>
}
并且响应如下:
{
gps_points:
{
#some data object
}
}
这对我来说不是REST,而是带有一些嵌入式SQL代码的JSON + HTTP + RPC,攻击者可以使用它来做一些SQL注入...
我认为上述示例(关于gpsPositions)的正确资源是:
http://1.2.3.4:8080/gPSPositions?fromDate=...&toDate= ...
使用HTTP / GET而非HTTP / POST(使用来回CRUD操作GET,DELETE,PUT和POST)。
我想知道这种方法对我的项目可能产生的技术影响。 API将在互联网上公开,并且将来它应该由更多供应商用于不同类型的应用程序。我还担心开发一个具有两种不同样式(RPC和REST)的API应该难以阅读和理解,这将是未来的问题。
感谢您的建议。
答案 0 :(得分:0)
实际上,OP和他的供应商都没有正确理解REST,IMO。
REST是一种架构风格,它基本上描述了客户端和服务器应如何相互交互,以便将前者与后者分离。通过使用支持协议(在您的情况下为HTTP)作为传输层并利用可用操作来交换数据来实现解耦。 HTTP,其核心实际上只是一个管理远程位置资源的协议,因此定义了每个操作的语义,而不是REST。此外,通过遵守由后备传输协议概述的规则并通过生成双方可以使用的新(或利用现有)媒体类型来实现解耦。而不是客户端耦合到服务器API,而是耦合到中间媒体类型。这就是Fielding强调REST API should spend almost all of their descriptive efforts in defining the media types used for representing resources
。
媒体类型本身只是语法的文本描述和期望接收注释为该类型的数据的语义。因此,它是同行如何处理数据并为数据提供一些有用含义的知识库。客户端和服务器应进一步使用内容协商来商定共同的媒体类型。即客户端可以向服务器发送客户端知道的媒体类型列表,服务器将选择可能最适合可用数据的媒体类型,或者将不支持的媒体类型故障发送回客户端以指示没有请求媒体类型为服务器所知。
服务器向客户端提供客户端可能需要采取进一步操作的所有信息,这一点非常重要。客户端不应该从提供的URI中解析含义,而是使用关系名称,并在交换的媒体类型中查找关系名称的语义,即依赖于next
,{{1等通用标准集合中的},prev
,first
和last
。这使服务器可以自由地更改URI(从而自由地移动资源)而不会破坏客户端。
所谓的RESTful API(以及使用它们的客户端)的一个常见错误是,数据仅作为self
或application/json
或类似的媒体类型进行交换,并且客户希望资源具有某种特定的类型(typed resources),已将客户端耦合到API。首先,application/hal+json
或application/json
通常是一种不良媒体类型,因为它没有提示用户文档可能包含哪些内容。由于示例代码包含地理位置数据,因此在该特定情况下application/vnd.geo+json
可能更合适。
由于REST专注于资源,如果地理位置数据能够弥补良好的资源,那么IMO是值得怀疑的。我至少认为它们更像某种实体的某种属性,我将其表达为资源。由于位置似乎随时间而变化,这可能是某种车辆信息(汽车,公共汽车,卡车,飞机,轮船......)等。拟议的答复本身并不是非常自我描述的。因此,客户端必须具有一些知识,即JSON有效负载中的application/xml
之类的某些内容可能包含可能作为某些时间序列的GPS数据。
如果服务器决定以稍微不同的方式返回数据,则客户端可能会以这种方式轻易破解。在依赖共同媒体类型的情况下,除非双方都遵守媒体类型规范,否则这种风险几乎被抹去。
如果gps_points
请求可行而不是POST
请求检索数据,那么您的实际帖子或多或少会有问题:
通过使用规范中定义的可用操作之一,客户端HTTP表达了他的意图。 GET
实际上是一个可选操作,如果其他操作都不符合需要,则应该使用它。这是一种瑞士军刀,很容易被误解。将它用于其他操作本身并没有错。这里的规范说明:
POST方法请求目标资源根据资源自身的特定语义处理请求中包含的表示。
在检索数据时,POST
是最好的操作,以防请求不修改服务器上的任何状态或需要通过正文中的大量数据(因为大量HTTP客户端限制了可以使用的URI的长度)被调用)。
通过POST接受数据检索的实际意义是,这成为API的一部分,您必须进一步支持它。如果您决定稍后修复&#34;这个问题可能会破坏使用这种与API通信的客户端。一些遗留系统可能会强迫您使用此类构造。我们有一些类似于RPC的Web服务,我们必须为各种各样的客户提供服务。其中一些是旧SAP版本中的SOAP客户端,为了将数据发送到我们的服务而被误导。由于在该ABAP版本中实际上没有对HTTP的内置支持(据我所知),我们也必须接受每个POST的这种检索请求。当我改变我们的API一次以便只接受GET数据检索时,我无意中破坏了大量遗留客户端(甚至一旦可以通过GET实际检索),因为开发人员刚刚使用了文档中的第一个示例,这仍然是POST那时。简而言之,从现在开始,我不得不回滚更改并支持这两种查询。