我需要调用一个不需要用户任何输入,只需要触发器的流程。我计划使用没有正文的 POST /uri 来触发该过程。我想知道从 HTTP 和 REST 角度来看这是否都被认为是不好的?
几个月前我在 IETF HTTP 工作组上问过这个问题。简短的回答是:不,这不是一个坏习惯(但我建议阅读该线程以了解更多详细信息)。
使用 POST 而不是 GET 是完全合理的,因为它还指示服务器(以及沿途的网关)不要返回缓存的响应。
POST 完全没问题。与 GET 和 POST 不同,您正在更改系统的状态(很可能您的触发器是“做”某事并更改数据)。
我已经使用了没有有效负载的 POST,它“感觉”还可以。使用无负载的 POST 时应该做的一件事是:传递标头
Content-Length: 0
。我记得当我的 api-client 没有通过它时,一些代理出现了问题。
如果您使用不带正文的 POST /uri,则类似于使用不带参数的函数。例如 int post (void);因此,为资源类提供可以在没有参数的情况下更改对象状态的函数是合理的。如果你考虑为一个URI实现Unix touch功能,不是一个不错的选择吗?
是的,可以发送不带正文的 POST 请求,而是使用查询字符串参数。但要小心,如果您的参数包含 HTTP 无效的字符,您将必须对它们进行编码。
例如,如果您需要将“hello world”发布到端点,则必须使其看起来像这样:http://api.com?param=hello%20world
在这种情况下,支持 POST 可以的答案是,在 Python 的情况下,当方法(参见下面的示例)不包含 Body 部分时,OpenAPI 框架“FastAPI”会生成一个不包含 Body 部分的 Swagger GUI(参见图片)。没有一个参数来接受主体。
方法“post_disable_db”只接受路径参数“db_name”,并且没有第二个参数,这意味着强制主体。
@router.post('/{db_name}/disable',
status_code=HTTP_200_OK,
response_model=ResponseSuccess,
summary='',
description=''
)
async def post_disable_db(db_name: str):
try:
response: ResponseSuccess = Handlers.databases_handler.post_change_db_enabled_state(db_name, False)
except HTTPException as e:
raise (e)
except Exception as e:
logger.exception(f'Changing state of DB to enabled=False failed due to: {e.__repr__()}')
raise HTTPException(HTTP_500_INTERNAL_SERVER_ERROR, detail=e.__repr__())
return response
它需要身体吗?那就不要。我知道您问 REST 中是否有一些规则,但其他人已经回答了这个问题,所以一般来说:什么是可以的,什么是不可以的通常取决于场景和上下文。即使有时不遵循设计模式,或稍微改变它们,如果它完全有意义并且干净等,也可以是“好的”。
也许 API 端点只是在执行某些操作,并且没有要使用的数据或需要了解的 ID。
例如,端点
api/delete-previous-week-logs
删除上周API上的所有日志。您不会期望客户端发送要删除的日志列表,因为它首先需要从您要发送到的 API 请求 GET 来删除它们。
如果 API 具有此知识来源,或者如果执行端点操作不需要主体或 ID,那么就是这样,没有主体。