Created
July 7, 2014 19:15
-
-
Save gissuebot/0bb14cbebdb458d02c25 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 807, comment 5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 6b7a884bb097aa3d70e71fbc5e5c6143d8d5be43 Mon Sep 17 00:00:00 2001 | |
From: James Moger <james.moger@gitblit.com> | |
Date: Thu, 12 Jun 2014 11:26:46 -0400 | |
Subject: [PATCH] Properly construct a wrapped servlet request before calling | |
Filter.doFilter() | |
--- | |
.../inject/servlet/FilterChainInvocation.java | 8 ++- | |
.../google/inject/servlet/FilterDefinition.java | 79 ++++++++++++++++++++++ | |
.../com/google/inject/servlet/ServletTest.java | 3 +- | |
3 files changed, 88 insertions(+), 2 deletions(-) | |
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java b/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java | |
index b4112cf..278815f 100644 | |
--- a/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java | |
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java | |
@@ -76,10 +76,16 @@ class FilterChainInvocation implements FilterChain { | |
try { | |
Filter filter = findNextFilter(request); | |
if (filter != null) { | |
+ // wrap the servlet request with filter-specific request info | |
+ FilterDefinition filterDefinition = filterDefinitions[index]; | |
+ HttpServletRequest filterRequest = filterDefinition.wrapRequest(request); | |
+ // replace the filter context | |
+ GuiceFilter.localContext.set(new GuiceFilter.Context(originalRequest, filterRequest, response)); | |
+ | |
// call to the filter, which can either consume the request or | |
// recurse back into this method. (in which case we will go to find the next filter, | |
// or dispatch to the servlet if no more filters are left) | |
- filter.doFilter(servletRequest, servletResponse, this); | |
+ filter.doFilter(filterRequest, servletResponse, this); | |
} else { | |
//we've reached the end of the filterchain, let's try to dispatch to a servlet | |
final boolean serviced = servletPipeline.service(servletRequest, servletResponse); | |
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java | |
index ff1e5b6..f900937 100644 | |
--- a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java | |
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java | |
@@ -15,6 +15,8 @@ | |
*/ | |
package com.google.inject.servlet; | |
+import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST; | |
+ | |
import com.google.common.collect.Iterators; | |
import com.google.inject.Injector; | |
import com.google.inject.Key; | |
@@ -35,6 +37,7 @@ import javax.servlet.FilterConfig; | |
import javax.servlet.ServletContext; | |
import javax.servlet.ServletException; | |
import javax.servlet.http.HttpServletRequest; | |
+import javax.servlet.http.HttpServletRequestWrapper; | |
/** | |
* An internal representation of a filter definition against a particular URI pattern. | |
@@ -160,6 +163,82 @@ class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition> | |
} | |
} | |
+ HttpServletRequest wrapRequest(final HttpServletRequest servletRequest) { | |
+ HttpServletRequest request = new HttpServletRequestWrapper(servletRequest) { | |
+ private boolean pathComputed; | |
+ private String path; | |
+ | |
+ private boolean pathInfoComputed; | |
+ private String pathInfo; | |
+ | |
+ @Override | |
+ public String getPathInfo() { | |
+ if (!isPathInfoComputed()) { | |
+ String servletPath = getServletPath(); | |
+ int servletPathLength = servletPath.length(); | |
+ String requestUri = getRequestURI(); | |
+ pathInfo = requestUri.substring(getContextPath().length()).replaceAll("[/]{2,}", "/"); | |
+ // See: http://code.google.com/p/google-guice/issues/detail?id=372 | |
+ if (pathInfo.startsWith(servletPath)) { | |
+ pathInfo = pathInfo.substring(servletPathLength); | |
+ // Corner case: when servlet path & request path match exactly (without trailing '/'), | |
+ // then pathinfo is null. | |
+ if (pathInfo.isEmpty() && servletPathLength > 0) { | |
+ pathInfo = null; | |
+ } | |
+ } else { | |
+ pathInfo = null; // we know nothing additional about the URI. | |
+ } | |
+ pathInfoComputed = true; | |
+ } | |
+ | |
+ return pathInfo; | |
+ } | |
+ | |
+ // NOTE(dhanji): These two are a bit of a hack to help ensure that request dispatcher-sent | |
+ // requests don't use the same path info that was memoized for the original request. | |
+ // NOTE(iqshum): I don't think this is possible, since the dispatcher-sent request would | |
+ // perform its own wrapping. | |
+ private boolean isPathInfoComputed() { | |
+ return pathInfoComputed | |
+ && !(null != servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST)); | |
+ } | |
+ | |
+ private boolean isPathComputed() { | |
+ return pathComputed | |
+ && !(null != servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST)); | |
+ } | |
+ | |
+ @Override | |
+ public String getServletPath() { | |
+ return computePath(); | |
+ } | |
+ | |
+ @Override | |
+ public String getPathTranslated() { | |
+ final String info = getPathInfo(); | |
+ | |
+ return (null == info) ? null : getRealPath(info); | |
+ } | |
+ | |
+ // Memoizer pattern. | |
+ private String computePath() { | |
+ if (!isPathComputed()) { | |
+ String servletPath = super.getServletPath(); | |
+ path = patternMatcher.extractPath(servletPath); | |
+ pathComputed = true; | |
+ | |
+ if (null == path) { | |
+ path = servletPath; | |
+ } | |
+ } | |
+ | |
+ return path; | |
+ } | |
+ }; | |
+ return request; | |
+ } | |
+ | |
//VisibleForTesting | |
Filter getFilter() { | |
return filter.get(); | |
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletTest.java | |
index beb0873..2645857 100644 | |
--- a/extensions/servlet/test/com/google/inject/servlet/ServletTest.java | |
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletTest.java | |
@@ -240,7 +240,8 @@ public class ServletTest extends TestCase { | |
assertSame(req, servletReqProvider.get()); | |
assertSame(req, reqProvider.get()); | |
if (previousReq[0] != null) { | |
- assertEquals(req, previousReq[0]); | |
+ ServletRequest wrappedReq = ((HttpServletRequestWrapper) req).getRequest(); | |
+ assertEquals(wrappedReq, previousReq[0]); | |
} | |
assertSame(resp, servletRespProvider.get()); | |
-- | |
1.9.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment