Yes, I solved the problem using my own CompatibilityRequestWrapper
HttpServletRequestWrapper wrappedRequest;
try {
wrappedRequest = new RestReadingServletRequest((HttpServletRequest) request);
if (isConfluenceApplication) {
wrappedRequest = new CompatibilityRequestWrapper(wrappedRequest);
}
} catch (Exception e) {
log.error(e);
chain.doFilter(request, response);
return;
}
chain.doFilter(wrappedRequest, response);
RestReadingServletRequest have logic to create multi-readable request that reads request body to temp var and overrides getReader and getInputStream to return this temp stored data
import java.io.BufferedReader;
import java.io.IOException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* This class in needed to fix error in Confluence 9.3.1: "Trailing token (of type START_OBJECT)
* found after value: not allowed as per `DeserializationFeature.FAIL_ON_TRAILING_TOKENS`" error.
*/
public class CompatibilityRequestWrapper extends HttpServletRequestWrapper {
private static final FormattingLogger log =
FormattingLogger.getLogger(CompatibilityRequestWrapper.class);
private CompatibilityInputStream compatibilityInputStream;
private CompatibilityBufferedReader compatibilityBufferedReader;
public CompatibilityRequestWrapper(HttpServletRequest httpServletRequest) {
super(httpServletRequest);
}
public ServletInputStream getInputStream() throws IOException {
if (this.compatibilityInputStream == null) {
this.compatibilityInputStream = new CompatibilityInputStream(super.getInputStream());
}
return this.compatibilityInputStream;
}
public BufferedReader getReader() throws IOException {
if (this.compatibilityBufferedReader == null) {
this.compatibilityBufferedReader = new CompatibilityBufferedReader(super.getReader());
}
return this.compatibilityBufferedReader;
}
private class CompatibilityInputStream extends ServletInputStream {
private final ServletInputStream delegate;
private CompatibilityInputStream(ServletInputStream delegate) {
this.delegate = delegate;
}
@Override
public int read() throws IOException {
return this.delegate.read();
}
@Override
public int read(byte[] b) throws IOException {
return this.delegate.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return this.delegate.read(b, off, len);
}
@Override
public int readLine(byte[] b, int off, int len) throws IOException {
return this.delegate.readLine(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return this.delegate.skip(n);
}
@Override
public int available() throws IOException {
return this.delegate.available();
}
@Override
public void close() throws IOException {
this.delegate.close();
}
@Override
public void mark(int readlimit) {
this.delegate.mark(readlimit);
}
@Override
public void reset() throws IOException {
this.delegate.reset();
}
@Override
public boolean markSupported() {
return this.delegate.markSupported();
}
}
private class CompatibilityBufferedReader extends BufferedReader {
private final BufferedReader delegate;
private CompatibilityBufferedReader(BufferedReader delegate) {
super(delegate);
this.delegate = delegate;
}
@Override
public int read() throws IOException {
return this.delegate.read();
}
@Override
public String readLine() throws IOException {
return this.delegate.readLine();
}
@Override
public int read(char[] cbuf) throws IOException {
return this.delegate.read(cbuf);
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return this.delegate.read(cbuf, off, len);
}
@Override
public long skip(long n) throws IOException {
return this.delegate.skip(n);
}
@Override
public boolean ready() throws IOException {
return this.delegate.ready();
}
@Override
public boolean markSupported() {
return this.delegate.markSupported();
}
@Override
public void mark(int readAheadLimit) throws IOException {
this.delegate.mark(readAheadLimit);
}
@Override
public void reset() throws IOException {
this.delegate.reset();
}
@Override
public void close() throws IOException {
this.delegate.close();
}
}
}