R语言Plumber生成Swagger文档时,POST参数为何仍挂在URL上?
我在使用Plumber包写接口时,发现了我设定的是POST请求,也能接收到query-string中参数的现象:
#* 细胞搜索 #* @param id 数据集id #* @param cell 细胞 #* @serializer unboxedJSON #* @post /sc_RNA/cell_remote function(id,cell) { promises::future_promise({ # 业务逻辑 source("apps/get_data.R") result <- getCellRemote(id,cell) # 返回成功结果 list(status = 200, message = "success", data = result) }) %>% # 异常处理 promises::catch(function(e) { log_error("Error in getVocanoPlot endpoint: {e}") list(status = 500, message = conditionMessage(e), data = NULL) }) }
Swagger中的请求URL:
curl -X 'POST' \ 'http://192.168.1.112:8080/sc_RNA/cell_remote?id=1&cell=1' \ -H 'accept: application/json' \ -d ''

为什么依旧能解析到参数呢?
我是习惯于把参数放请求体里的,所以见到这种情况觉得很奇怪,于是去了解了一下,发现Plumer默认从三个地方取值:路径片段、query-string、请求体,所以当我把参数拼到URL后面时,Plumber依旧能解析到。
为什么Swagger会拼到URL上呢?
Swagger-OpenAPI规范里,一个参数必须显式标注in: query、in: path或in: body。
Plumber 在生成OpenAPI文档时,默认把所有@param都当成in: query(除非你在路径模板里写了{})。结果Swagger-UI收到的是“query 参数”的schema,它自然就把表单渲染成 ?id=xxx&cell=xxx并挂在URL后面,即使方法是POST。
要想参数真正走请求体,有以下几种方法
1.把参数从@param改成接收JSON体:
#* @post /sc_RNA/cell_remote #* @serializer unboxedJSON function(req, res) { body <- jsonlite::fromJSON(req$postBody) id <- body$id cell <- body$cell ... }
2.把参数声明为路径变量:
#* @post /sc_RNA/cell_remote/<id:int>/<cell> #* @serializer unboxedJSON function(id, cell) { ... }
3.利用Plumber自带的POST解析器(删掉@param)
#* @post /sc_RNA/cell_remote #* @serializer unboxedJSON function(id, cell) { # Plumber 会自动从 JSON body 里找 id、cell ... }

浙公网安备 33010602011771号