【问题标题】:Reading POST body: java.lang.IllegalStateException: Only one connection receive subscriber allowed阅读 POST 正文:java.lang.IllegalStateException:只允许一个连接接收订阅者
【发布时间】:2018-10-02 07:35:25
【问题描述】:

在 Spring Webflux 中,当我阅读 POST 正文并尝试使用它时,它总是会导致标题中的 IllegalStateException。

代码如下:

  @Bean
  public RouterFunction<ServerResponse> selectByPost(SasoSecurityFacade solrHandler) {
    return RouterFunctions.route(RequestPredicates.POST("/v1/{collection}/select")
                                     .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), request -> request.bodyToMono(String.class)
        .flatMap(s -> {
          System.out.println(s);
          return ServerResponse.ok()
              .syncBody(s);
        }));
  }

同样重要(事实证明),对服务器的请求:

curl 'https://<myserver>:9443/v1/banana-int/select' -H 'Pragma: no-cache' -H 'Origin: https://<myserver>:9443' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7' -H 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' -H 'Content-type: application/x-www-form-urlencoded' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'Referer: https://<myserver>:9443/banana/src/index.html' -H 'Connection: keep-alive' -H 'DNT: 1' --data 'q=*:*&rows=20&wt=json' --compressed

我做错了什么?我该如何调试呢?还有谁在阅读我的帖子正文,以便我收到此错误消息?

【问题讨论】:

  • 这是一个 Spring Boot 应用程序吗?这是完整的处理程序定义(似乎您在这里注入了一些您没有使用的东西)?您是否配置了 WebFilter 实例?请求是什么样的?这仅发生在该路径上还是其他请求路径上?
  • 我已经在这方面做了一些工作(实际上是几天,因为这似乎不可调试):没有 webfilters,它是 spring-boot,请求是一个很短的字符串,比如 "q=*:* &rows=20&wt=json”。唯一剩下的就是尝试从头开始做所有事情。
  • 那么这里肯定有一些不明显的东西在起作用,因为在 Spring Boot 应用程序中复制/粘贴这段代码 sn-p 对我有用。你有我可以看看的复制项目吗?
  • 您能回答我之前的问题并显示您向服务器发出的请求的 curl 命令吗?
  • 我发现了问题,把request.bodyToMono(String.class)换成request.formData()...

标签: spring-webflux


【解决方案1】:

您发送的请求是一个 POST 表单请求,HiddenHttpMethodFilter 会自动读取该请求。如果通过"_method" 参数指定了替代方法,此过滤器会使用表单数据来改变 HTTP 方法。

在这种情况下,使用 WebFlux annotation/functional 中的专用 request.formData() API 使用表单数据是最佳选择,它会被缓存以备将来使用并且不会触发新的订阅。

如果您希望完全禁用此行为,you'll be able to set a property in Spring Boot 2.1

【讨论】:

  • 您能否详细介绍一下专用部分?你的意思是添加这样的东西:RequestPredicates.contentType(MediaType.MULTIPART_FORM_DATA)?
  • 不,您现在使用的 API 在您的 cmets 中进行了编辑。我已经编辑了我的答案。
猜你喜欢
  • 2019-11-03
  • 2018-06-11
  • 1970-01-01
  • 2019-06-23
  • 2022-07-14
  • 1970-01-01
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多