@Test public void cachedContentWithLimit() throws Exception { this.request.setMethod("GET"); this.request.setCharacterEncoding(CHARSET); this.request.setContent("Hello World".getBytes(CHARSET)); ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(this.request, 3); byte[] response = FileCopyUtils.copyToByteArray(wrapper.getInputStream()); assertArrayEquals("Hello World".getBytes(CHARSET), response); assertArrayEquals("Hel".getBytes(CHARSET), wrapper.getContentAsByteArray()); }
/** * Extracts the message payload portion of the message created by * {@link #createMessage(HttpServletRequest, String, String)} when * {@link #isIncludePayload()} returns true. * @since 5.0.3 */ @Nullable protected String getMessagePayload(HttpServletRequest request) { ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class); if (wrapper != null) { byte[] buf = wrapper.getContentAsByteArray(); if (buf.length > 0) { int length = Math.min(buf.length, getMaxPayloadLength()); try { return new String(buf, 0, length, wrapper.getCharacterEncoding()); } catch (UnsupportedEncodingException ex) { return "[unknown]"; } } } return null; }
private boolean isFormPost() { String contentType = getContentType(); return (contentType != null && contentType.contains(FORM_CONTENT_TYPE) && HttpMethod.POST.matches(getMethod())); }
@Override public BufferedReader getReader() throws IOException { if (this.reader == null) { this.reader = new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding())); } return this.reader; }
@Override public String getParameter(String name) { if (this.cachedContent.size() == 0 && isFormPost()) { writeRequestParametersToCachedContent(); } return super.getParameter(name); }
@Test public void requestParams() throws Exception { this.request.setMethod("POST"); this.request.setContentType(FORM_CONTENT_TYPE); this.request.setCharacterEncoding(CHARSET); this.request.setParameter("first", "value"); this.request.setParameter("second", "foo", "bar"); ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(this.request); // getting request parameters will consume the request body assertFalse(wrapper.getParameterMap().isEmpty()); assertEquals("first=value&second=foo&second=bar", new String(wrapper.getContentAsByteArray())); // SPR-12810 : inputstream body should be consumed assertEquals("", new String(FileCopyUtils.copyToByteArray(wrapper.getInputStream()))); }
/** * Forwards the request to the next filter in the chain and delegates down to the subclasses * to perform the actual request logging both before and after the request is processed. * @see #beforeRequest * @see #afterRequest */ @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { boolean isFirstRequest = !isAsyncDispatch(request); HttpServletRequest requestToUse = request; if (isIncludePayload() && isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) { requestToUse = new ContentCachingRequestWrapper(request, getMaxPayloadLength()); } boolean shouldLog = shouldLog(requestToUse); if (shouldLog && isFirstRequest) { beforeRequest(requestToUse, getBeforeMessage(requestToUse)); } try { filterChain.doFilter(requestToUse, response); } finally { if (shouldLog && !isAsyncStarted(requestToUse)) { afterRequest(requestToUse, getAfterMessage(requestToUse)); } } }
throws IOException, ServletException { ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request); ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response); } finally { String requestBody = new String(requestWrapper.getContentAsByteArray()); String responseBody = new String(responseWrapper.getContentAsByteArray());
@Override public void doFilter(ServletRequest filterRequest, ServletResponse filterResponse) throws IOException, ServletException { ((HttpServletResponse) filterResponse).setStatus(HttpServletResponse.SC_OK); byte[] buf = FileCopyUtils.copyToByteArray(filterRequest.getInputStream()); assertArrayEquals(requestBody, buf); ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(filterRequest, ContentCachingRequestWrapper.class); assertArrayEquals("Hel".getBytes("UTF-8"), wrapper.getContentAsByteArray()); } };
private void writeRequestParametersToCachedContent() { try { if (this.cachedContent.size() == 0) { String requestEncoding = getCharacterEncoding(); Map<String, String[]> form = super.getParameterMap(); for (Iterator<String> nameIterator = form.keySet().iterator(); nameIterator.hasNext(); ) { String name = nameIterator.next(); List<String> values = Arrays.asList(form.get(name)); for (Iterator<String> valueIterator = values.iterator(); valueIterator.hasNext(); ) { String value = valueIterator.next(); this.cachedContent.write(URLEncoder.encode(name, requestEncoding).getBytes()); if (value != null) { this.cachedContent.write('='); this.cachedContent.write(URLEncoder.encode(value, requestEncoding).getBytes()); if (valueIterator.hasNext()) { this.cachedContent.write('&'); } } } if (nameIterator.hasNext()) { this.cachedContent.write('&'); } } } } catch (IOException ex) { throw new IllegalStateException("Failed to write request parameters to cached content", ex); } }
private void writeToCache(final byte[] b, final int off, int count) { if (!this.overflow && count > 0) { if (contentCacheLimit != null && count + cachedContent.size() > contentCacheLimit) { this.overflow = true; cachedContent.write(b, off, contentCacheLimit - cachedContent.size()); handleContentOverflow(contentCacheLimit); return; } cachedContent.write(b, off, count); } }
@Override public ServletInputStream getInputStream() throws IOException { if (this.inputStream == null) { this.inputStream = new ContentCachingInputStream(getRequest().getInputStream()); } return this.inputStream; }
@Test public void cachedContentWithOverflow() throws Exception { this.request.setMethod("GET"); this.request.setCharacterEncoding(CHARSET); this.request.setContent("Hello World".getBytes(CHARSET)); ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(this.request, 3) { @Override protected void handleContentOverflow(int contentCacheLimit) { throw new IllegalStateException(String.valueOf(contentCacheLimit)); } }; try { FileCopyUtils.copyToByteArray(wrapper.getInputStream()); fail("Should have thrown IllegalStateException"); } catch (IllegalStateException ex) { assertEquals("3", ex.getMessage()); } }
@Override public Map<String, String[]> getParameterMap() { if (this.cachedContent.size() == 0 && isFormPost()) { writeRequestParametersToCachedContent(); } return super.getParameterMap(); }
/** * Forwards the request to the next filter in the chain and delegates down to the subclasses * to perform the actual request logging both before and after the request is processed. * @see #beforeRequest * @see #afterRequest */ @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { boolean isFirstRequest = !isAsyncDispatch(request); HttpServletRequest requestToUse = request; if (isIncludePayload() && isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) { requestToUse = new ContentCachingRequestWrapper(request, getMaxPayloadLength()); } boolean shouldLog = shouldLog(requestToUse); if (shouldLog && isFirstRequest) { beforeRequest(requestToUse, getBeforeMessage(requestToUse)); } try { filterChain.doFilter(requestToUse, response); } finally { if (shouldLog && !isAsyncStarted(requestToUse)) { afterRequest(requestToUse, getAfterMessage(requestToUse)); } } }
@Override public BufferedReader getReader() throws IOException { if (this.reader == null) { this.reader = new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding())); } return this.reader; }
@ControllerAdvice(annotations = RestController.class) public class GlobalExceptionHandlingControllerAdvice { private ContentCachingRequestWrapper getUnderlyingCachingRequest(ServletRequest request) { if (ContentCachingRequestWrapper.class.isAssignableFrom(request.getClass())) { return (ContentCachingRequestWrapper) request; } if (request instanceof ServletRequestWrapper) { return getUnderlyingCachingRequest(((ServletRequestWrapper)request).getRequest()); } return null; } @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Throwable.class) public @ResponseBody Map<String, String> conflict(Throwable exception, HttpServletRequest request) { ContentCachingRequestWrapper underlyingCachingRequest = getUnderlyingCachingRequest(request); String body = new String(underlyingCachingRequest.getContentAsByteArray(),Charsets.UTF_8); .... } }
private void writeRequestParametersToCachedContent() { try { if (this.cachedContent.size() == 0) { String requestEncoding = getCharacterEncoding(); Map<String, String[]> form = super.getParameterMap(); for (Iterator<String> nameIterator = form.keySet().iterator(); nameIterator.hasNext(); ) { String name = nameIterator.next(); List<String> values = Arrays.asList(form.get(name)); for (Iterator<String> valueIterator = values.iterator(); valueIterator.hasNext(); ) { String value = valueIterator.next(); this.cachedContent.write(URLEncoder.encode(name, requestEncoding).getBytes()); if (value != null) { this.cachedContent.write('='); this.cachedContent.write(URLEncoder.encode(value, requestEncoding).getBytes()); if (valueIterator.hasNext()) { this.cachedContent.write('&'); } } } if (nameIterator.hasNext()) { this.cachedContent.write('&'); } } } } catch (IOException ex) { throw new IllegalStateException("Failed to write request parameters to cached content", ex); } }
@Override public int read() throws IOException { int ch = this.is.read(); if (ch != -1 && !this.overflow) { if (contentCacheLimit != null && cachedContent.size() == contentCacheLimit) { this.overflow = true; handleContentOverflow(contentCacheLimit); } else { cachedContent.write(ch); } } return ch; }
@Override public ServletInputStream getInputStream() throws IOException { if (this.inputStream == null) { this.inputStream = new ContentCachingInputStream(getRequest().getInputStream()); } return this.inputStream; }