ContentCachingRequestWrapper supports content cache limit

Issue: SPR-14829
This commit is contained in:
Juergen Hoeller
2017-01-17 20:42:19 +01:00
parent 976d32fc59
commit ad5386773e
4 changed files with 98 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -159,7 +159,7 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
}
/**
* Sets the maximum length of the payload body to be included in the log message.
* Set the maximum length of the payload body to be included in the log message.
* Default is 50 characters.
* @since 3.0
*/
@@ -233,7 +233,7 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
HttpServletRequest requestToUse = request;
if (isIncludePayload() && isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) {
requestToUse = new ContentCachingRequestWrapper(request);
requestToUse = new ContentCachingRequestWrapper(request, getMaxPayloadLength());
}
boolean shouldLog = shouldLog(requestToUse);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,6 +53,8 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
private final ByteArrayOutputStream cachedContent;
private final Integer contentCacheLimit;
private ServletInputStream inputStream;
private BufferedReader reader;
@@ -66,6 +68,20 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
super(request);
int contentLength = request.getContentLength();
this.cachedContent = new ByteArrayOutputStream(contentLength >= 0 ? contentLength : 1024);
this.contentCacheLimit = null;
}
/**
* Create a new ContentCachingRequestWrapper for the given servlet request.
* @param request the original servlet request
* @param contentCacheLimit the maximum number of bytes to cache per request
* @since 4.3.6
* @see #handleContentOverflow(int)
*/
public ContentCachingRequestWrapper(HttpServletRequest request, int contentCacheLimit) {
super(request);
this.cachedContent = new ByteArrayOutputStream(contentCacheLimit);
this.contentCacheLimit = contentCacheLimit;
}
@@ -162,16 +178,33 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
/**
* Return the cached request content as a byte array.
* <p>The returned array will never be larger than the content cache limit.
* @see #ContentCachingRequestWrapper(HttpServletRequest, int)
*/
public byte[] getContentAsByteArray() {
return this.cachedContent.toByteArray();
}
/**
* Template method for handling a content overflow: specifically, a request
* body being read that exceeds the specified content cache limit.
* <p>The default implementation is empty. Subclasses may override this to
* throw a payload-too-large exception or the like.
* @param contentCacheLimit the maximum number of bytes to cache per request
* which has just been exceeded
* @since 4.3.6
* @see #ContentCachingRequestWrapper(HttpServletRequest, int)
*/
protected void handleContentOverflow(int contentCacheLimit) {
}
private class ContentCachingInputStream extends ServletInputStream {
private final ServletInputStream is;
private boolean overflow = false;
public ContentCachingInputStream(ServletInputStream is) {
this.is = is;
}
@@ -179,8 +212,14 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
@Override
public int read() throws IOException {
int ch = this.is.read();
if (ch != -1) {
cachedContent.write(ch);
if (ch != -1 && !this.overflow) {
if (contentCacheLimit != null && cachedContent.size() == contentCacheLimit) {
this.overflow = true;
handleContentOverflow(contentCacheLimit);
}
else {
cachedContent.write(ch);
}
}
return ch;
}