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); |
Free forum by Nabble | Edit this page |