首页 > 解决方案 > 如何使用 Spring Web Flux 处理 url 编码的有效负载

问题描述

客户端正在发送编码的有效负载(编码百分比),而给定的代码适用于未编码的有效负载/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;
}

}

标签: javaspring-boothttp-headersspring-webfluxproject-reactor

解决方案


当我们偏离处理标准的“内容类型:应用程序/xml”时,这里添加了 3 个额外的步骤-

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;
}


推荐阅读