【问题标题】:Generated Swagger REST client does not handle + character correctly for query parameter生成的 Swagger REST 客户端无法正确处理查询参数的 + 字符
【发布时间】:2018-02-21 12:31:48
【问题描述】:

我有这个 Spring REST 控制器方法:

@ApiOperation("My method")
@RequestMapping(method = RequestMethod.POST, value = "/myMethod")
public void myMethod(@RequestParam("myParam") String myParam) {
...
}

REST 客户端是使用带有语言 Java 和库 resttemplate 的 swagger codegen CLI 生成的:

public void myMethod(String myParam) throws RestClientException {
    ...
    return apiClient.invokeAPI(path, HttpMethod.POST, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType);
}

ApiClient#invokeAPI 的源代码——也是生成的——是:

public <T> T invokeAPI(String path, HttpMethod method, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames, ParameterizedTypeReference<T> returnType) throws RestClientException {
    updateParamsForAuth(authNames, queryParams, headerParams);

    final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path);
    if (queryParams != null) {
        builder.queryParams(queryParams);
    }

    final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());
    if(accept != null) {
        requestBuilder.accept(accept.toArray(new MediaType[accept.size()]));
    }
    if(contentType != null) {
        requestBuilder.contentType(contentType);
    }

    addHeadersToRequest(headerParams, requestBuilder);
    addHeadersToRequest(defaultHeaders, requestBuilder);

    RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));

    ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
    ...
}

现在,当我调用myMethod 传递一个包含+ 的字符串并登录myParam 时,在服务器上我收到一个空格字符而不是+。似乎是一个编码问题,因为加号保留在 URL 查询参数中以替换空格字符。这是来自 swagger codegen 或 Spring 类的错误,还是根本没有错误?我该如何解决?

编辑:

Swagger 定义类似于(从 Spring REST 控制器生成):

{
  "swagger": "2.0",
  ...
  "paths": {
    "/myMethod": {
      "get": {
        "operationId": "myMethod",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "myParam",
            "in": "query",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
           ...
        }
      }
    }
 ...
}

编辑:

类似的问题似乎是路径变量的编码。当我将"bla:bla/bla" 传递给路径变量时,特殊字符:/ 不会被编码,而是按原样发送,这会导致服务器端出错,因为找不到映射。

【问题讨论】:

  • 能不能也分享一下你用过的合约?
  • @TarunLalwani “合同”是什么意思?
  • 我的意思是 Swagger 合约 yaml 或 json
  • @TarunLalwani 我添加了它。
  • 您是如何发起呼叫以测试服务的?你是用 curl 还是别的?

标签: java spring-mvc resttemplate spring-web swagger-codegen


【解决方案1】:

+ 通常表示 url 参数中的空格。这是一个标准。您的网址是在下面的代码行中生成的

final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());

并且+ 未编码,因为它是一个有效值,稍后将在接收端将其转换为空间。现在,当您尝试使用%2B 时,上面的代码行发现您有一个未编码的% 字符,并将其转换为%252B

当您在 Spring 收到此回复时,它会为您将其转换回 %2B。解决该问题的一种方法是自己发送编码值。所以你会改变

 final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());

final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build(true).toUri());

然后调用API方法为

client.myMethod("tarun%2blalwani")

现在 spring 将收到tarun+lalwani 如下所示

【讨论】:

  • + 表示查询字符串参数中的空格不是标准的.. 在日期时间字符串中,例如2018-01-01T12:00:00+04:00 + 很重要,当然不代表空格。
猜你喜欢
  • 1970-01-01
  • 2022-11-03
  • 2017-08-06
  • 1970-01-01
  • 2017-08-20
  • 2018-12-24
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多