【问题标题】:how to handle url encoded payload with spring web flux如何使用 Spring Web Flux 处理 url 编码的有效负载
【发布时间】:2020-08-29 01:13:48
【问题描述】:

客户端正在发送编码的有效负载(编码百分比),而给定的代码适用于未编码的有效负载/XML(内容类型:应用程序/xml),但它会因 http 415 编码的有效负载/XML 文件(内容类型)而失败:应用程序/x-www-form-urlencoded)。

我注意到 FormHttpMessageReader.java 成功解码了有效负载(在调试日志中看到)但是在请求流中的某个地方之后我的代码无法将解码的 XML 正确映射到 POJO。

卷曲请求 -

curl -H 'Content-type: application/x-www-form-urlencoded' http://localhost:8081/api/v1/app/test  -d @encodedpyaload.xml -i-H 'Accept: application/xml, text/xml, application/x-www-form-urlencoded, */*’
HTTP/1.1 100 Continue

HTTP/1.1 415 Unsupported Media Type
Content-Type: application/json
Content-Length: 158
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Referrer-Policy: no-referrer

{"error":"415 UNSUPPORTED_MEDIA_TYPE \"Content type 'application/x-www-form-urlencoded' not supported for bodyType=test.package.Pojo\””}

配置类-

@Bean
public RouterFunction<ServerResponse> testRoute() {
    return route(POST(“/app/test”).and(contentType(MediaType.APPLICATION_FORM_URLENCODED)),
            handler::testHandler);
}

处理程序类

public Mono<ServerResponse> testHandler(final ServerRequest request) {

    return dataManager.testSave(request.bodyToMono(Pojo.class))
            .flatMap(uri -> ServerResponse.ok().build())
            .switchIfEmpty(ServerResponse.badRequest().build());
}

更新 Handler 类代码

处理程序类


return dataManager.testSave(request.bodyToMono(String.class)
        .flatMap(body -> Mono.just(URLDecoder.decode(body, StandardCharsets.UTF_8))
                .map(s -> createBody(s))).cast(Pojo.class))
        .flatMap(uri -> ServerResponse.ok().build())
        .switchIfEmpty(ServerResponse.badRequest().build());



private Pojo createBody(String s)  {
    XmlMapper mapper = new XmlMapper();
    Pojo pojo = new Pojo();
    try {
        pojo = mapper.readValue(s, Pojo.class);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return pojo;
}

POJO 类

@XmlRootElement(name = “root”)
public class Pojo {

@XmlElement(name = “id”)
public long getId() {
    return id;
}

public void setId(long id) {
    this.id= id;
}

}

【问题讨论】:

  • 以这种方式发送 xml 数据不是标准,这就是为什么没有标准的方式。表单数据在正文中以键:值格式发送,因此无法正常工作。我的建议是要么尝试将常规的application/xml 设置为内容类型。并使用bodyToMono,但我怀疑这会起作用,或者您将正文作为字符串处理,然后将百分比编码数据转换为标准编码并解析数据。为什么你甚至会将百分比编码的数据作为 xml 发送?为什么?
  • 这是经过百分比编码和发送的 xml 数据。在一个简单的 servlet 中,从 HttpServletRequest URLDecoder.decode(percentencodedstring, "UTF-8") 读取编码的 InputStream 后,我将对其进行如下解码
  • 我无意冒犯你。 servlet 参考是希望有人可以在这些方面提出解决方案。我正在处理您的建议并尝试解码从 request.exchange.getRequest().getBody() 获取的数据。
  • 按照request.bodyToMono(String.class).flatMap(body -&gt; Mono.just(URLDecoder.decode(body, "UTF-8")).map( // parse your decoded string )的行做点什么
  • 在上面的问题中添加了 Handler 的更新代码。映射到 Pojo 仍然有问题。 dataManager.testSave() 需要 Mono&lt;Pojo&gt;

标签: java spring-boot http-headers spring-webflux project-reactor


【解决方案1】:

这里添加了 3 个额外的步骤,因为我们偏离了处理标准的“Content-type:application/xml”-

1) 解码(百分比编码的请求正文)有效负载

2) 将解码后的字符串编码为 XML

3) 将 XML 转换为 Mono

代码更改:

处理函数:

就像托马斯建议的那样 -

request.bodyToMono(String.class).flatmap(body -> Mono.just(decode(body)).map(decodedstring -> createXML(decodedstring))).cast(Pojo.class))

private String decode(String body){
String str1 = "";
String str2 = body;

//if percent content is re-encoded multiple times
while(!str1.equals(str2)) {
str1=str2;
str2=URLDecoder.decode(str2,StandardCharsets.UTF_8)
}
return str2;
}

private Pojo createXML(String decodedstring) {
InputStream is = new ByteArrayInputStream(decodedstring.getBytes(Charset.forName("UTF-8")));
Pojo pojo = JAXB.unmarshal(is, Pojo.class);
return pojo;
}

【讨论】:

    猜你喜欢
    • 2016-03-21
    • 1970-01-01
    • 2014-08-16
    • 2013-12-06
    • 2018-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多