You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by mt...@apache.org on 2019/10/25 21:49:35 UTC
svn commit: r1868963 - in /ofbiz/ofbiz-framework/trunk: ./
framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/
framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/
Author: mthl
Date: Fri Oct 25 21:49:35 2019
New Revision: 1868963
URL: http://svn.apache.org/viewvc?rev=1868963&view=rev
Log:
Implemented: Handle URI templates in request maps
(OFBIZ-11007)
It is now possible to use segmented paths by using URI templates like
‘/foo/bar/{baz}’ in the ‘uri’ attribute of <request-map> elements.
Thanks: Artemiy Rozovyk for your contribution.
Modified:
ofbiz/ofbiz-framework/trunk/build.gradle
ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java
ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java
ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java
Modified: ofbiz/ofbiz-framework/trunk/build.gradle
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/build.gradle?rev=1868963&r1=1868962&r2=1868963&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/build.gradle (original)
+++ ofbiz/ofbiz-framework/trunk/build.gradle Fri Oct 25 21:49:35 2019
@@ -307,7 +307,7 @@ checkstyle {
// the sum of errors that were present before introducing the
// âcheckstyleâ tool present in the framework and in the official
// plugins.
- maxErrors = 37915
+ maxErrors = 37880
// Currently there are a lot of errors so we need to temporarily
// hide them to avoid polluting the terminal output.
showViolations = false
Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java?rev=1868963&r1=1868962&r2=1868963&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ControlServlet.java Fri Oct 25 21:49:35 2019
@@ -77,15 +77,35 @@ public class ControlServlet extends Http
}
@Override
- public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- doGet(request, response);
+ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ handle(req, resp);
+ }
+
+ @Override
+ public void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ handle(req, resp);
+ }
+
+ @Override
+ public void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ handle(req, resp);
+ }
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ handle(req, resp);
}
/**
- * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ * Invokes {@link RequestHandler#doRequest} with error handling.
+ *
+ * @param req an {@link HttpServletRequest} object that contains the request
+ * the client has made of the servlet
+ * @param resp an {@link HttpServletResponse} object that contains the response
+ * the servlet sends to the client
+ * @throws IOException if an output error is detected when trying to write on the response.
*/
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException {
long requestStartTime = System.currentTimeMillis();
HttpSession session = request.getSession();
Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java?rev=1868963&r1=1868962&r2=1868963&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java Fri Oct 25 21:49:35 2019
@@ -41,7 +41,9 @@ import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import javax.ws.rs.core.MultivaluedHashMap;
+import org.apache.cxf.jaxrs.model.URITemplate;
import org.apache.ofbiz.base.location.FlexibleLocation;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.SSLUtil;
@@ -183,7 +185,7 @@ public class RequestHandler {
}
/**
- * Find a collection of request maps in {@code ccfg} matching {@code req}.
+ * Finds a collection of request maps in {@code ccfg} matching {@code req}.
* Otherwise fall back to matching the {@code defaultReq} field in {@code ccfg}.
*
* @param ccfg The controller containing the current configuration
@@ -192,20 +194,23 @@ public class RequestHandler {
*/
static Collection<RequestMap> resolveURI(ControllerConfig ccfg, HttpServletRequest req) {
Map<String, List<RequestMap>> requestMapMap = ccfg.getRequestMapMap();
- Map<String, ConfigXMLReader.ViewMap> viewMapMap = ccfg.getViewMapMap();
- String defaultRequest = ccfg.getDefaultRequest();
- String path = req.getPathInfo();
- String requestUri = getRequestUri(path);
- String viewUri = getOverrideViewUri(path);
- Collection<RequestMap> rmaps;
- if (requestMapMap.containsKey(requestUri)
- // Ensure that overridden view exists.
- && (viewUri == null || viewMapMap.containsKey(viewUri))) {
- rmaps = requestMapMap.get(requestUri);
- } else if (defaultRequest != null) {
- rmaps = requestMapMap.get(defaultRequest);
- } else {
- rmaps = null;
+ Collection<RequestMap> rmaps = resolveTemplateURI(requestMapMap, req);
+ if (rmaps.isEmpty()) {
+ Map<String, ConfigXMLReader.ViewMap> viewMapMap = ccfg.getViewMapMap();
+ String defaultRequest = ccfg.getDefaultRequest();
+ String path = req.getPathInfo();
+ String requestUri = getRequestUri(path);
+ String overrideViewUri = getOverrideViewUri(path);
+ if (requestMapMap.containsKey(requestUri)
+ // Ensure that overridden view exists.
+ && (overrideViewUri == null || viewMapMap.containsKey(overrideViewUri))) {
+ rmaps = requestMapMap.get(requestUri);
+ req.setAttribute("overriddenView", overrideViewUri);
+ } else if (defaultRequest != null) {
+ rmaps = requestMapMap.get(defaultRequest);
+ } else {
+ rmaps = null;
+ }
}
return rmaps != null ? rmaps : Collections.emptyList();
}
@@ -234,6 +239,33 @@ public class RequestHandler {
}
}
+ /**
+ * Finds the request maps matching a segmented path.
+ *
+ * <p>A segmented path can match request maps where the {@code uri} attribute
+ * contains an URI template like in the {@code foo/bar/{baz}} example.
+ *
+ * @param rMapMap the map associating URIs to a list of request maps corresponding to different HTTP methods
+ * @param request the HTTP request to match
+ * @return a collection of request maps which might be empty but not {@code null}
+ */
+ private static Collection<RequestMap> resolveTemplateURI(Map<String, List<RequestMap>> rMapMap,
+ HttpServletRequest request) {
+ // Retrieve the request path without the leading '/' character.
+ String path = request.getPathInfo().substring(1);
+ MultivaluedHashMap<String, String> vars = new MultivaluedHashMap<>();
+ for (Map.Entry<String, List<RequestMap>> entry : rMapMap.entrySet()) {
+ URITemplate uriTemplate = URITemplate.createExactTemplate(entry.getKey());
+ // Check if current path the URI template exactly.
+ if (uriTemplate.match(path, vars) && vars.getFirst("FINAL_MATCH_GROUP").equals("/")) {
+ // Set attributes from template variables to be used in context.
+ uriTemplate.getVariables().forEach(var -> request.setAttribute(var, vars.getFirst(var)));
+ return entry.getValue();
+ }
+ }
+ return Collections.emptyList();
+ }
+
public void doRequest(HttpServletRequest request, HttpServletResponse response, String chain,
GenericValue userLogin, Delegator delegator) throws RequestHandlerException, RequestHandlerExceptionAllowExternalRequests {
@@ -269,7 +301,6 @@ public class RequestHandler {
String path = request.getPathInfo();
String requestUri = getRequestUri(path);
- String overrideViewUri = getOverrideViewUri(path);
Collection<RequestMap> rmaps = resolveURI(ccfg, request);
if (rmaps.isEmpty()) {
@@ -287,8 +318,11 @@ public class RequestHandler {
throw new RequestHandlerExceptionAllowExternalRequests();
}
}
+ // The "overriddenView" attribute is set by resolveURI when necessary.
+ String overrideViewUri = (String) request.getAttribute("overriddenView");
- String method = request.getMethod();
+ String restMethod = request.getParameter("restMethod");
+ String method = (restMethod != null) ? restMethod : request.getMethod();
RequestMap requestMap = resolveMethod(method, rmaps).orElseThrow(() -> {
String msg = UtilProperties.getMessage("WebappUiLabels", "RequestMethodNotMatchConfig",
UtilMisc.toList(requestUri, method), UtilHttp.getLocale(request));
Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java?rev=1868963&r1=1868962&r2=1868963&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/test/java/org/apache/ofbiz/webapp/control/RequestHandlerTests.java Fri Oct 25 21:49:35 2019
@@ -28,6 +28,8 @@ import static org.junit.Assert.assertTru
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
@@ -121,6 +123,65 @@ public class RequestHandlerTests {
assertThat(RequestHandler.resolveURI(ccfg, req), hasItem(bar));
}
+ /**
+ * Checks that segmented URIs are resolved and does not
+ * conflict with overrideViewUri mechanism
+ */
+ @Test
+ public void resolveTemplateURISergmented() {
+ RequestMap foo = new RequestMap(dummyElement);
+ RequestMap bar = new RequestMap(dummyElement);
+ RequestMap baz = new RequestMap(dummyElement);
+ reqMaps.putSingle("baz/foo", foo);
+ reqMaps.putSingle("bar", bar);
+ reqMaps.putSingle("baz", baz);
+
+ viewMaps.put("foo", new ViewMap(dummyElement));
+
+ when(req.getPathInfo()).thenReturn("/baz/foo");
+ when(ccfg.getDefaultRequest()).thenReturn("bar");
+ assertThat(RequestHandler.resolveURI(ccfg, req), both(hasItem(foo)).and(not(hasItem(baz))));
+ }
+
+ @Test
+ public void resolveTemplateURIWithVariables() {
+ RequestMap foo = new RequestMap(dummyElement);
+ RequestMap bar = new RequestMap(dummyElement);
+ reqMaps.putSingle("foo/bar/{var1}/baz/{var2}", foo);
+ reqMaps.putSingle("bar", bar);
+
+ when(req.getPathInfo()).thenReturn("/foo/bar/toto/baz/titi");
+
+ assertThat(RequestHandler.resolveURI(ccfg, req), hasItem(foo));
+ verify(req, times(1)).setAttribute("var1", "toto");
+ verify(req, times(1)).setAttribute("var2", "titi");
+ }
+
+ /**
+ * Currently it is up to the developer to manage URIs with custom
+ * variables that are conflicting with other routes by excluding
+ * them using regular expressions as shown in the test.
+ */
+ @Test
+ public void resolveTemplateURIConflictingRoutes() {
+ RequestMap foo = new RequestMap(dummyElement);
+ RequestMap bar = new RequestMap(dummyElement);
+ RequestMap baz = new RequestMap(dummyElement);
+ reqMaps.putSingle("foo/bar", foo);
+ reqMaps.putSingle("foo/qux", bar);
+ reqMaps.putSingle("foo/{var:(?!(bar)|(qux)).*}", baz);
+
+ when(req.getPathInfo()).thenReturn("/foo/bar");
+ assertThat(RequestHandler.resolveURI(ccfg, req), hasItem(foo));
+
+ when(req.getPathInfo()).thenReturn("/foo/qux");
+ assertThat(RequestHandler.resolveURI(ccfg, req), hasItem(bar));
+
+ when(req.getPathInfo()).thenReturn("/foo/toto");
+ assertThat(RequestHandler.resolveURI(ccfg, req), hasItem(baz));
+ verify(req, times(1)).setAttribute("var", "toto");
+ }
+
@Test
public void resolveURIBasicOverrideView() throws Exception {
RequestMap foo = new RequestMap(dummyElement);