'Get body as raw string from ServerWebExchange/ServerHttpRequest
I need to get the request body as a raw JSON string in my controller. I'm using Spring WebFlux. If I could change @PostMapper function signature, it will be so easy to get the raw JSON by using "@RequestBody String rawStudent". But I can't do that as it's auto-generated and will affect other handlers, also "@RequestBody Student" already exist and we can't have two @RequestBody.
@RestController
public class StudentController {
@PostMapping("/student")
private void newStudent(@RequestBody Student student,
ServerWebExchange exchange) {
String rawStudent = ServerExchangeUtils.getRequestRawBody(exchange); //idealy like this
System.out.println(rawStudent);
}
}
What I'm looking for is something like "getRequestRaw(exchange)"
Solution 1:[1]
i had the same problem and i cant change the signaure because it is generated by openapi generator
i found a solution by setting an exchange attribute in a WebFilter :
@Component
@Slf4j
public class SetRequestBodyAttribute implements WebFilter {
public static final String BODY_STRING_ATTRIBUTE = "BODY_STRING";
private static ServerHttpRequestPredicate requestsToServe =
MethodServerHttpRequestPredicate.of(HttpMethod.POST)
.and(PathServerHttpRequestPredicate.of("/contacts/import"))
.or(MethodServerHttpRequestPredicate.of(HttpMethod.PATCH)
.and(PathServerHttpRequestPredicate.of("/contacts/{contact_id}")));
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
if (requestsToServe.test(exchange.getRequest())) {
log.info("setting request attribute {}.", BODY_STRING_ATTRIBUTE);
exchange.getAttributes().put(BODY_STRING_ATTRIBUTE, ServerHttpRequestUtils.getBodyAsString(exchange.getRequest()));
}
return chain.filter(exchange);
}
}
@UtilityClass
public class ServerHttpRequestUtils {
public Mono<String> getBodyAsString(ServerHttpRequest request) {
return DataBufferUtils.join(request.getBody())
.map(DataBuffer::asByteBuffer)
.map(ByteBuffer::array)
.map(String::new);
}
}
public interface ServerHttpRequestPredicate {
boolean test(ServerHttpRequest request);
@NotNull
default ServerHttpRequestPredicate and(@NotNull ServerHttpRequestPredicate other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
@NotNull
default ServerHttpRequestPredicate negate() {
return (t) -> !test(t);
}
@NotNull
default ServerHttpRequestPredicate or(@NotNull ServerHttpRequestPredicate other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
}
@Value
public class PathServerHttpRequestPredicate implements ServerHttpRequestPredicate {
public static PathServerHttpRequestPredicate of(String path) {
return new PathServerHttpRequestPredicate(path);
}
PathPattern pathPattern;
public PathServerHttpRequestPredicate(String path) {
Assert.notNull(path, "path should not be null!");
this.pathPattern = PathPatternParser.defaultInstance.parse(path);
}
@Override
public boolean test(ServerHttpRequest request) {
PathContainer pathContainer = request.getPath().pathWithinApplication();
PathPattern.PathMatchInfo info = this.pathPattern.matchAndExtract(pathContainer);
return info != null;
}
}
@Value(staticConstructor = "of")
public class MethodServerHttpRequestPredicate implements ServerHttpRequestPredicate{
HttpMethod httpMethod;
public MethodServerHttpRequestPredicate(HttpMethod httpMethod) {
Assert.notNull(httpMethod, "httpMethod should not be null!");
this.httpMethod = httpMethod;
}
@Override
public boolean test(ServerHttpRequest request) {
return request.getMethod() == httpMethod;
}
}
and in the controller handler we can get the body as string even if it was injected as Object
Mono<String> bodyAsStringMono = exchange.getAttribute(SetRequestBodyAttribute.BODY_STRING_ATTRIBUTE);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |