Eri*_*k B 426 api rest search filter
我目前正在设计和实现PHP中的RESTful API.但是,我没有成功实施我的初始设计.
GET /users # list of users
GET /user/1 # get user with id 1
POST /user # create new user
PUT /user/1 # modify user with id 1
DELETE /user/1 # delete user with id 1
Run Code Online (Sandbox Code Playgroud)
到目前为止标准相当,对吗?
我的问题是第一个问题GET /users.我正在考虑在请求正文中发送参数来过滤列表.这是因为我希望能够在不获取超长URL的情况下指定复杂的过滤器,例如:
GET /users?parameter1=value1¶meter2=value2¶meter3=value3¶meter4=value4
Run Code Online (Sandbox Code Playgroud)
相反,我希望有类似的东西:
GET /users
# Request body:
{
"parameter1": "value1",
"parameter2": "value2",
"parameter3": "value3",
"parameter4": "value4"
}
Run Code Online (Sandbox Code Playgroud)
它更具可读性,为您提供设置复杂过滤器的绝佳机会.
无论如何,file_get_contents('php://input')没有返回请求的请求体GET.我也尝试过http_get_request_body(),但我正在使用的共享主机没有pecl_http.不确定它会有所帮助.
我发现了这个问题,并意识到GET可能不应该有一个请求体.这有点不确定,但他们建议不要这样做.
所以现在我不知道该怎么做.你如何设计RESTful搜索/过滤功能?
我想我可以使用POST,但这似乎不太RESTful.
小智 383
实现RESTful搜索的最佳方法是将搜索本身视为资源.然后您可以使用POST动词,因为您正在创建搜索.您不必在数据库中逐字创建以使用POST.
例如:
Accept: application/json
Content-Type: application/json
POST http://example.com/people/searches
{
"terms": {
"ssn": "123456789"
},
"order": { ... },
...
}
Run Code Online (Sandbox Code Playgroud)
您正在从用户的角度创建搜索.这个实现细节是无关紧要的.一些RESTful API甚至可能不需要持久性.这是一个实现细节.
jfc*_*edo 132
如果在GET请求中使用请求主体,则会违反REST原则,因为您的GET请求将无法缓存,因为缓存系统仅使用URL.
更糟糕的是,您的URL无法加入书签,因为该URL不包含将用户重定向到此页面所需的所有信息
使用URL或Query参数代替请求正文参数.
例如:
/myapp?var1=xxxx&var2=xxxx
/myapp;var1=xxxx/resource;var2=xxxx
Run Code Online (Sandbox Code Playgroud)
事实上,HTTP RFC 7231说:
GET请求消息中的有效负载没有定义的语义; 在GET请求上发送有效负载主体可能会导致某些现有实现拒绝该请求.
有关更多信息,请查看此处
Opa*_*pal 68
似乎资源过滤/搜索可以以RESTful方式实现.我们的想法是引入一个名为/filters/或的新端点/api/filters/.
使用此端点过滤器可以视为资源,因此通过POST方法创建.这种方式 - 当然 - 身体可用于携带所有参数以及可以创建复杂的搜索/过滤器结构.
创建此类过滤器后,有两种方法可以获得搜索/过滤结果.
将返回具有唯一ID的新资源以及201 Created状态代码.然后使用此ID GET可以使请求/api/users/如下:
GET /api/users/?filterId=1234-abcd
Run Code Online (Sandbox Code Playgroud)新的过滤器通过创建后POST它将不会与回复201 Created,但在一次与303 SeeOther一起Location头指向/api/users/?filterId=1234-abcd.此重定向将通过底层库自动处理.
在这两种情况下,需要进行两次请求以获取过滤结果 - 这可能被视为缺点,尤其是对于移动应用程序.对于移动应用程序,我会使用单个POST调用/api/users/filter/.
如何保持创建的过滤器?
它们可以存储在DB中,以后再使用.它们也可以存储在一些临时存储器中,例如redis,并且有一些TTL,之后它们将过期并将被删除.
这个想法有什么好处?
过滤器,过滤结果可以缓存,甚至可以加入书签.
因为我正在使用laravel/php后端,所以我倾向于使用这样的东西:
/resource?filters[status_id]=1&filters[city]=Sydney&page=2&include=relatedResource
Run Code Online (Sandbox Code Playgroud)
PHP会自动将[]params转换为数组,所以在这个例子中,我最终会得到一个$filter包含过滤器数组/对象的变量,以及一个页面和我想要加载的任何相关资源.
如果您使用其他语言,这可能仍然是一个很好的约定,您可以创建一个解析器来转换[]为数组.
如果您的初始API完全是RESTful(特别是当您处于alpha阶段时),请不要担心太多.让后端管道首先工作.您可以随时进行某种URL转换/重写以映射事物,迭代完善,直到您获得足够稳定的广泛测试("beta").
您可以定义URI,其参数按URI上的位置和约定进行编码,前缀为您知道始终映射到某个内容的路径.我不知道PHP,但我认为这样的工具存在(因为它存在于其他语言的Web框架中):
.IE.对商店#1的i = 1..4使用param [i] = value [i]执行"用户"类型的搜索(使用value1,value2,value3,...作为URI查询参数的简写):
1) GET /store1/search/user/value1,value2,value3,value4
Run Code Online (Sandbox Code Playgroud)
要么
2) GET /store1/search/user,value1,value2,value3,value4
Run Code Online (Sandbox Code Playgroud)
或者如下(尽管我不推荐它,稍后会详细介绍)
3) GET /search/store1,user,value1,value2,value3,value4
Run Code Online (Sandbox Code Playgroud)
使用选项1,您将所有带前缀的URI映射/store1/search/user到搜索处理程序(或PHP指定的任何一个)默认搜索store1下的资源(相当于/search?location=store1&type=user.
按照API的记录和强制执行的惯例,参数值1到4用逗号分隔并按顺序显示.
选项2将搜索类型(在本例中user)添加为位置参数#1.这两种选择都只是一种美容选择.
选项3也是可能的,但我不认为我会喜欢它.我认为在某些资源中搜索的能力应该在搜索本身之前的URI本身中呈现(好像在URI中清楚地表明搜索在资源中是特定的.)
相对于URI传递参数的优点是搜索是URI的一部分(因此将搜索视为资源,其内容可以 - 并且将随时间变化的资源.)缺点是参数顺序是强制性的.
一旦你做了这样的事情,你可以使用GET,它将是一个只读资源(因为你不能POST或PUT到它 - 它得到GET时更新).它也是一种资源,只有在被调用时才会存在.
也可以通过将结果缓存一段时间或使用DELETE导致缓存被删除来为其添加更多语义.但是,这可能与人们通常使用DELETE的方式背道而驰(因为人们通常使用缓存头来控制缓存.)
你如何去做这将是一个设计决定,但这将是我的方式.它并不完美,我相信会有这样的情况,这样做不是最好的事情(特别是对于非常复杂的搜索标准).
| 归档时间: |
|
| 查看次数: |
311937 次 |
| 最近记录: |