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 ''

 

屏幕截图 2025-10-24 170223

为什么依旧能解析到参数呢?

我是习惯于把参数放请求体里的,所以见到这种情况觉得很奇怪,于是去了解了一下,发现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
  ...
}

 

posted @ 2025-10-28 16:41  翰佰尔HiOmics云分析  阅读(7)  评论(0)    收藏  举报