diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletHandler.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletHandler.java index 9ffbc009428f..88b3da899f9e 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletHandler.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletHandler.java @@ -785,14 +785,47 @@ public ServletHolder addServletWithMapping(String className, String pathSpec) * @return The servlet holder. */ public ServletHolder addServletWithMapping(Class servlet, String pathSpec) + { + return addServletWithMapping(null, servlet, pathSpec); + } + + /** + * Convenience method to add a servlet. + * + * @param servletName The name of the servlet holder or {@code null} for a default name. + * @param servlet the servlet class + * @param pathSpecs the path specs + * @return The servlet holder. + */ + public ServletHolder addServletWithMapping(String servletName, Class servlet, String... pathSpecs) { ServletHolder holder = newServletHolder(Source.EMBEDDED); + if (servletName != null) + holder.setName(servletName); holder.setHeldClass(servlet); - addServletWithMapping(holder, pathSpec); + addServletWithMappings(holder, pathSpecs); return holder; } + /** + * Convenience method to add a servlet. + * + * @param servletName The name of the servlet holder or {@code null} for a default name. + * @param servlet the servlet instance + * @param pathSpecs the path specs + * @return The servlet holder. + */ + public ServletHolder addServletWithMapping(String servletName, Servlet servlet, String... pathSpecs) + { + ServletHolder holder = newServletHolder(Source.EMBEDDED); + if (servletName != null) + holder.setName(servletName); + holder.setServlet(servlet); + addServletWithMappings(holder, pathSpecs); + return holder; + } + /** * Convenience method to add a servlet. * @@ -800,6 +833,17 @@ public ServletHolder addServletWithMapping(Class servlet, Str * @param pathSpec servlet mappings for the servletHolder */ public void addServletWithMapping(ServletHolder servlet, String pathSpec) + { + addServletWithMappings(servlet, pathSpec); + } + + /** + * Convenience method to add a servlet. + * + * @param servlet servlet holder to add + * @param pathSpecs servlet mappings for the servletHolder + */ + public void addServletWithMappings(ServletHolder servlet, String... pathSpecs) { Objects.requireNonNull(servlet); ServletHolder[] holders = getServlets(); @@ -811,10 +855,13 @@ public void addServletWithMapping(ServletHolder servlet, String pathSpec) setServlets(ArrayUtil.addToArray(holders, servlet, ServletHolder.class)); } - ServletMapping mapping = new ServletMapping(); - mapping.setServletName(servlet.getName()); - mapping.setPathSpec(pathSpec); - setServletMappings(ArrayUtil.addToArray(getServletMappings(), mapping, ServletMapping.class)); + if (pathSpecs != null && pathSpecs.length > 0) + { + ServletMapping mapping = new ServletMapping(); + mapping.setServletName(servlet.getName()); + mapping.setPathSpecs(pathSpecs); + addServletMapping(mapping); + } } catch (RuntimeException e) { diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletPathMapping.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletPathMapping.java index 491cc941a865..0c43eee22ab0 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletPathMapping.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletPathMapping.java @@ -112,10 +112,10 @@ public ServletPathMapping(PathSpec pathSpec, String servletName, String pathInCo case PREFIX_GLOB: _mappingMatch = MappingMatch.PATH; _servletPath = pathSpec.getPrefix(); - _matchValue = _servletPath.startsWith("/") ? _servletPath.substring(1) : _servletPath; _pathInfo = matchedPath != null ? matchedPath.getPathInfo() : _servletPath.length() == pathInContext.length() ? null : pathInContext.substring(_servletPath.length()); + _matchValue = _pathInfo == null ? "" : _pathInfo.startsWith("/") ? _pathInfo.substring(1) : _pathInfo; break; case SUFFIX_GLOB: diff --git a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/AsyncContextTest.java b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/AsyncContextTest.java index ba9de1136e04..0bea70cd8882 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/AsyncContextTest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/AsyncContextTest.java @@ -286,7 +286,7 @@ public void testDispatchAsyncContextEncodedUrl() throws Exception assertThat("async run attr query string", responseBody, containsString("async:run:attr:queryString:dispatch=true")); assertThat("async run context path", responseBody, containsString("async:run:attr:contextPath:/ctx")); assertThat("async run request uri has correct encoding", responseBody, containsString("async:run:attr:requestURI:/ctx/encoded/hello%20there")); - assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:encoded")); + assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:hello there")); assertThat("http servlet mapping pattern is correct", responseBody, containsString("async:run:attr:mapping:pattern:/encoded/*")); assertThat("http servlet mapping servletName is correct", responseBody, containsString("async:run:attr:mapping:servletName:")); assertThat("http servlet mapping mappingMatch is correct", responseBody, containsString("async:run:attr:mapping:mappingMatch:PATH")); @@ -333,7 +333,7 @@ public void testDispatchAsyncAmbiguousUrl() throws Exception assertThat("async run attr query string", responseBody, containsString("async:run:attr:queryString:dispatch=true")); assertThat("async run context path", responseBody, containsString("async:run:attr:contextPath:/ctx")); assertThat("async run request uri has correct encoding", responseBody, containsString("async:run:attr:requestURI:/ctx/ambiguous/hello%20there")); - assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:ambiguous")); + assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:hello there")); assertThat("http servlet mapping pattern is correct", responseBody, containsString("async:run:attr:mapping:pattern:/ambiguous/*")); assertThat("http servlet mapping servletName is correct", responseBody, containsString("async:run:attr:mapping:servletName:")); assertThat("http servlet mapping mappingMatch is correct", responseBody, containsString("async:run:attr:mapping:mappingMatch:PATH")); diff --git a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/DispatcherTest.java b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/DispatcherTest.java index da44ce74f676..8f7ed44287dc 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/DispatcherTest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/DispatcherTest.java @@ -106,8 +106,8 @@ public void destroy() throws Exception @Test public void testForwardToWelcome() throws Exception { - _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(DefaultServlet.class, "/"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("DefaultServlet", DefaultServlet.class, "/"); _server.start(); String responses = _connector.getResponse(""" @@ -123,8 +123,8 @@ public void testForwardToWelcome() throws Exception @Test public void testForward() throws Exception { - _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(AssertForwardServlet.class, "/AssertForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("AssertForwardServlet", AssertForwardServlet.class, "/AssertForwardServlet/*"); String rawResponse = _connector.getResponse(""" GET /context/ForwardServlet?do=assertforward&do=more&test=1 HTTP/1.1\r @@ -145,10 +145,10 @@ public void testForward() throws Exception } @Test - public void testFowardThenForward() throws Exception + public void testForwardThenForward() throws Exception { - _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(AlwaysForwardServlet.class, "/AlwaysForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("AlwaysForwardServlet", AlwaysForwardServlet.class, "/AlwaysForwardServlet/*"); ServletHolder holder = _contextHandler.getServletHandler().newServletHolder(Source.EMBEDDED); holder.setHeldClass(ForwardEchoURIServlet.class); holder.setName("ForwardEchoURIServlet"); //use easy-to-test name @@ -187,8 +187,8 @@ public void testFowardThenForward() throws Exception @Test public void testForwardNonUTF8() throws Exception { - _contextHandler.addServlet(ForwardNonUTF8Servlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(AssertNonUTF8ForwardServlet.class, "/AssertForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardNonUTF8Servlet", ForwardNonUTF8Servlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("AssertNonUTF8ForwardServlet", AssertNonUTF8ForwardServlet.class, "/AssertForwardServlet/*"); String rawResponse = _connector.getResponse(""" GET /context/ForwardServlet?do=assertforward&foreign=%d2%e5%ec%ef%e5%f0%e0%f2%f3%f0%e0&test=1 HTTP/1.1\r @@ -210,8 +210,8 @@ public void testForwardNonUTF8() throws Exception @Test public void testForwardWithParam() throws Exception { - _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(EchoURIServlet.class, "/EchoURI/*"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("EchoURIServlet", EchoURIServlet.class, "/EchoURI/*"); String responses = _connector.getResponse(""" GET /context/ForwardServlet;ignore=true?do=req.echo&uri=EchoURI%2Fx%2520x%3Ba=1%3Fb=2 HTTP/1.1\r @@ -241,7 +241,7 @@ public void testNamedForward() throws Exception holder.setHeldClass(NamedForwardServlet.class); holder.setName("NamedForwardServlet"); //use easy-to-test name _contextHandler.addServlet(holder, "/forward/*"); - String echo = _contextHandler.addServlet(ForwardEchoURIServlet.class, "/echo/*").getName(); + String echo = _contextHandler.getServletHandler().addServletWithMapping("ForwardEchoURIServlet", ForwardEchoURIServlet.class, "/echo/*").getName(); String rawResponse = _connector.getResponse((""" GET /context/forward/info;param=value?name=@ECHO@ HTTP/1.1\r @@ -275,8 +275,8 @@ public void testNamedForward() throws Exception @Test public void testNamedInclude() throws Exception { - _contextHandler.addServlet(NamedIncludeServlet.class, "/include/*"); - String echo = _contextHandler.addServlet(IncludeEchoURIServlet.class, "/echo/*").getName(); + _contextHandler.getServletHandler().addServletWithMapping("NamedIncludeServlet", NamedIncludeServlet.class, "/include/*"); + String echo = _contextHandler.getServletHandler().addServletWithMapping("IncludeEchoURIServlet", IncludeEchoURIServlet.class, "/echo/*").getName(); String responses = _connector.getResponse(""" GET /context/include/info;param=value?name=@ECHO@ HTTP/1.1\r @@ -311,8 +311,8 @@ public void testForwardWithBadParams() throws Exception try (StacklessLogging ignored = new StacklessLogging(ServletChannel.class)) { LOG.info("Expect Not valid UTF8 warnings..."); - _contextHandler.addServlet(AlwaysForwardServlet.class, "/forward/*"); - _contextHandler.addServlet(EchoServlet.class, "/echo/*"); + _contextHandler.getServletHandler().addServletWithMapping("AlwaysForwardServlet", AlwaysForwardServlet.class, "/forward/*"); + _contextHandler.getServletHandler().addServletWithMapping("EchoServlet", EchoServlet.class, "/echo/*"); String rawResponse; @@ -372,8 +372,8 @@ public void testForwardWithBadParams() throws Exception @Test public void testInclude() throws Exception { - _contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*"); - _contextHandler.addServlet(AssertIncludeServlet.class, "/AssertIncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("IncludeServlet", IncludeServlet.class, "/IncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("AssertIncludeServlet", AssertIncludeServlet.class, "/AssertIncludeServlet/*"); //test include, along with special extension to include that allows headers to //be set during an include @@ -403,10 +403,10 @@ public void testServletIncludeWelcome() throws Exception { _server.stop(); _contextHandler.setWelcomeFiles(new String[] {"index.x"}); - _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*"); - ServletHolder defaultHolder = _contextHandler.addServlet(DefaultServlet.class, "/"); + _contextHandler.getServletHandler().addServletWithMapping("DispatchServletServlet", DispatchServletServlet.class, "/dispatch/*"); + ServletHolder defaultHolder = _contextHandler.getServletHandler().addServletWithMapping("DefaultServlet", DefaultServlet.class, "/"); defaultHolder.setInitParameter("welcomeServlets", "true"); - _contextHandler.addServlet(RogerThatServlet.class, "*.x"); + _contextHandler.getServletHandler().addServletWithMapping("RogerThatServlet", RogerThatServlet.class, "*.x"); _server.start(); String rawResponse = _connector.getResponse(""" @@ -501,8 +501,8 @@ public void testIncludeOutputStreamWriter(boolean includeWriter, boolean helloWr @Test public void testIncludeWriterOutputStream() throws Exception { - _contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*"); - _contextHandler.addServlet(AssertIncludeServlet.class, "/AssertIncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("IncludeServlet", IncludeServlet.class, "/IncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("AssertIncludeServlet", AssertIncludeServlet.class, "/AssertIncludeServlet/*"); //test include, along with special extension to include that allows headers to //be set during an include @@ -530,7 +530,7 @@ public void testIncludeWriterOutputStream() throws Exception @Test public void testIncludeStatic() throws Exception { - _contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("IncludeServlet", IncludeServlet.class, "/IncludeServlet/*"); _contextHandler.addServlet(new ServletHolder("default", DefaultServlet.class), "/"); _server.start(); @@ -583,8 +583,8 @@ public void testIncludeStaticWithWriter() throws Exception @Test public void testForwardStatic() throws Exception { - _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(DefaultServlet.class, "/"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("DefaultServlet", DefaultServlet.class, "/"); _server.start(); String responses = _connector.getResponse(""" @@ -614,8 +614,8 @@ public void testForwardStatic() throws Exception @Test public void testForwardSendError() throws Exception { - _contextHandler.addServlet(ForwardServlet.class, "/forward/*"); - _contextHandler.addServlet(SendErrorServlet.class, "/senderr/*"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/forward/*"); + _contextHandler.getServletHandler().addServletWithMapping("SendErrorServlet", SendErrorServlet.class, "/senderr/*"); String forwarded = _connector.getResponse(""" GET /context/forward?do=ctx.echo&uri=/senderr HTTP/1.1\r @@ -631,8 +631,8 @@ public void testForwardSendError() throws Exception @Test public void testForwardExForwardEx() throws Exception { - _contextHandler.addServlet(RelativeDispatch2Servlet.class, "/RelDispatchServlet/*"); - _contextHandler.addServlet(ThrowServlet.class, "/include/throw/*"); + _contextHandler.getServletHandler().addServletWithMapping("RelativeDispatch2Servlet", RelativeDispatch2Servlet.class, "/RelDispatchServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("ThrowServlet", ThrowServlet.class, "/include/throw/*"); String rawResponse = _connector.getResponse(""" GET /context/RelDispatchServlet?path=include/throw HTTP/1.1\r @@ -657,8 +657,8 @@ public void testForwardExForwardEx() throws Exception @Test public void testIncludeExIncludeEx() throws Exception { - _contextHandler.addServlet(RelativeDispatch2Servlet.class, "/RelDispatchServlet/*"); - _contextHandler.addServlet(ThrowServlet.class, "/include/throw/*"); + _contextHandler.getServletHandler().addServletWithMapping("RelativeDispatch2Servlet", RelativeDispatch2Servlet.class, "/RelDispatchServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("ThrowServlet", ThrowServlet.class, "/include/throw/*"); String rawResponse = _connector.getResponse(""" GET /context/RelDispatchServlet?include=true&path=include/throw HTTP/1.1\r @@ -687,9 +687,9 @@ public void testIncludeExIncludeEx() throws Exception @Test public void testForwardThenInclude() throws Exception { - _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*"); - _contextHandler.addServlet(AssertForwardIncludeServlet.class, "/AssertForwardIncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("IncludeServlet", IncludeServlet.class, "/IncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("AssertForwardIncludeServlet", AssertForwardIncludeServlet.class, "/AssertForwardIncludeServlet/*"); String rawResponse = _connector.getResponse(""" GET /context/ForwardServlet/forwardpath?do=include HTTP/1.1\r @@ -713,9 +713,9 @@ public void testForwardThenInclude() throws Exception @Test public void testIncludeThenForward() throws Exception { - _contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*"); - _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*"); - _contextHandler.addServlet(AssertIncludeForwardServlet.class, "/AssertIncludeForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("IncludeServlet", IncludeServlet.class, "/IncludeServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("ForwardServlet", ForwardServlet.class, "/ForwardServlet/*"); + _contextHandler.getServletHandler().addServletWithMapping("AssertIncludeForwardServlet", AssertIncludeForwardServlet.class, "/AssertIncludeForwardServlet/*"); String rawResponse = _connector.getResponse(""" GET /context/IncludeServlet/includepath?do=forward HTTP/1.1\r @@ -738,8 +738,8 @@ public void testIncludeThenForward() throws Exception @Test public void testServletForward() throws Exception { - _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*"); - _contextHandler.addServlet(RogerThatServlet.class, "/roger/*"); + _contextHandler.getServletHandler().addServletWithMapping("DispatchServletServlet", DispatchServletServlet.class, "/dispatch/*"); + _contextHandler.getServletHandler().addServletWithMapping("RogerThatServlet", RogerThatServlet.class, "/roger/*"); String rawResponse = _connector.getResponse(""" GET /context/dispatch/test?forward=/roger/that HTTP/1.1\r @@ -761,8 +761,8 @@ public void testServletForward() throws Exception @Test public void testServletForwardDotDot() throws Exception { - _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*"); - _contextHandler.addServlet(RogerThatServlet.class, "/roger/that"); + _contextHandler.getServletHandler().addServletWithMapping("DispatchServletServlet", DispatchServletServlet.class, "/dispatch/*"); + _contextHandler.getServletHandler().addServletWithMapping("RogerThatServlet", RogerThatServlet.class, "/roger/that"); String rawRequest = """ GET /context/dispatch/test?forward=/%2e%2e/roger/that HTTP/1.1\r @@ -779,8 +779,8 @@ public void testServletForwardDotDot() throws Exception @Test public void testServletForwardEncodedDotDot() throws Exception { - _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*"); - _contextHandler.addServlet(RogerThatServlet.class, "/roger/that"); + _contextHandler.getServletHandler().addServletWithMapping("DispatchServletServlet", DispatchServletServlet.class, "/dispatch/*"); + _contextHandler.getServletHandler().addServletWithMapping("RogerThatServlet", RogerThatServlet.class, "/roger/that"); String rawRequest = """ GET /context/dispatch/test?forward=/%252e%252e/roger/that HTTP/1.1\r @@ -797,8 +797,8 @@ public void testServletForwardEncodedDotDot() throws Exception @Test public void testServletInclude() throws Exception { - _contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*"); - _contextHandler.addServlet(RogerThatServlet.class, "/roger/*"); + _contextHandler.getServletHandler().addServletWithMapping("DispatchServletServlet", DispatchServletServlet.class, "/dispatch/*"); + _contextHandler.getServletHandler().addServletWithMapping("RogerThatServlet", RogerThatServlet.class, "/roger/*"); String rawResponse = _connector.getResponse(""" GET /context/dispatch/test?include=/roger/that HTTP/1.0\r @@ -819,9 +819,9 @@ public void testServletInclude() throws Exception @Test public void testForwardFilterToRogerServlet() throws Exception { - _contextHandler.addServlet(RogerThatServlet.class, "/*"); - _contextHandler.addServlet(ReserveEchoServlet.class, "/recho/*"); - _contextHandler.addServlet(EchoServlet.class, "/echo/*"); + _contextHandler.getServletHandler().addServletWithMapping("RogerThatServlet", RogerThatServlet.class, "/*"); + _contextHandler.getServletHandler().addServletWithMapping("ReserveEchoServlet", ReserveEchoServlet.class, "/recho/*"); + _contextHandler.getServletHandler().addServletWithMapping("EchoServlet", EchoServlet.class, "/echo/*"); _contextHandler.addFilter(ForwardFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); HttpTester.Response response; @@ -1462,7 +1462,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t response.getOutputStream().println(mapping == null ? null : mapping.getServletName()); response.getOutputStream().println((String)request.getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH)); HttpServletMapping attrMapping = (HttpServletMapping)request.getAttribute(RequestDispatcher.FORWARD_MAPPING); - response.getOutputStream().println(attrMapping == null ? null : attrMapping.getMatchValue()); + response.getOutputStream().println(attrMapping == null ? null : attrMapping.getServletName()); response.getOutputStream().println((String)request.getAttribute(RequestDispatcher.FORWARD_PATH_INFO)); response.getOutputStream().println((String)request.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING)); response.getOutputStream().println((String)request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI)); @@ -1482,7 +1482,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t assertEquals("do=assertforward&do=more&test=1", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING)); HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING); assertNotNull(fwdMapping); - assertEquals("ForwardServlet", fwdMapping.getMatchValue()); + assertEquals("ForwardServlet", fwdMapping.getServletName()); List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING); @@ -1518,7 +1518,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t assertEquals("do=assertforward&foreign=%d2%e5%ec%ef%e5%f0%e0%f2%f3%f0%e0&test=1", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING)); HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING); assertNotNull(fwdMapping); - assertEquals("ForwardServlet", fwdMapping.getMatchValue()); + assertEquals("ForwardNonUTF8Servlet", fwdMapping.getServletName()); List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING); @@ -1567,7 +1567,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t assertThat((String)request.getAttribute(Dispatcher.INCLUDE_QUERY_STRING), containsString("do=end&do=the")); HttpServletMapping incMapping = (HttpServletMapping)request.getAttribute(Dispatcher.INCLUDE_MAPPING); assertNotNull(incMapping); - assertEquals("AssertIncludeServlet", incMapping.getMatchValue()); + assertEquals("AssertIncludeServlet", incMapping.getServletName()); List expectedAttributeNames = Arrays.asList(Dispatcher.INCLUDE_REQUEST_URI, Dispatcher.INCLUDE_CONTEXT_PATH, Dispatcher.INCLUDE_SERVLET_PATH, Dispatcher.INCLUDE_QUERY_STRING, Dispatcher.INCLUDE_MAPPING); @@ -1605,7 +1605,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t assertEquals("do=include", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING)); HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING); assertNotNull(fwdMapping); - assertEquals("ForwardServlet", fwdMapping.getMatchValue()); + assertEquals("ForwardServlet", fwdMapping.getServletName()); assertEquals("/context/AssertForwardIncludeServlet/assertpath", request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI)); assertEquals("/context", request.getAttribute(Dispatcher.INCLUDE_CONTEXT_PATH)); @@ -1614,7 +1614,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t assertEquals("do=end", request.getAttribute(Dispatcher.INCLUDE_QUERY_STRING)); HttpServletMapping incMapping = (HttpServletMapping)request.getAttribute(Dispatcher.INCLUDE_MAPPING); assertNotNull(incMapping); - assertEquals("AssertForwardIncludeServlet", incMapping.getMatchValue()); + assertEquals("AssertForwardIncludeServlet", incMapping.getServletName()); List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_PATH_INFO, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING, @@ -1656,7 +1656,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t assertEquals("do=forward", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING)); HttpServletMapping fwdMapping = (HttpServletMapping)request.getAttribute(Dispatcher.FORWARD_MAPPING); assertNotNull(fwdMapping); - assertEquals("IncludeServlet", fwdMapping.getMatchValue()); + assertEquals("IncludeServlet", fwdMapping.getServletName()); List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_PATH_INFO, Dispatcher.FORWARD_QUERY_STRING, Dispatcher.FORWARD_MAPPING); diff --git a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletTest.java b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletTest.java index 42c986d69079..f15bec7a39e8 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletTest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletTest.java @@ -15,23 +15,25 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletMapping; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.MappingMatch; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.IO; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertFalse; public class ServletTest @@ -197,40 +199,75 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se } } - @Test - public void testHttpServletMapping() throws Exception + public static Stream mappings() { - _context.addServlet(new HttpServlet() + return Stream.of( + // from servlet javadoc + Arguments.of("/", "", "", "CONTEXT_ROOT"), + Arguments.of("/index.html", "", "/", "DEFAULT"), + Arguments.of("/MyServlet/index.html", "", "/", "DEFAULT"), + Arguments.of("/MyServlet", "MyServlet", "/MyServlet", "EXACT"), + Arguments.of("/MyServlet/foo", "", "/", "DEFAULT"), + Arguments.of("/foo.extension", "foo", "*.extension", "EXTENSION"), + Arguments.of("/bar/foo.extension", "bar/foo", "*.extension", "EXTENSION"), + Arguments.of("/path/foo", "foo", "/path/*", "PATH"), + Arguments.of("/path/foo/bar", "foo/bar", "/path/*", "PATH"), + + // extra tests + Arguments.of("/path/", "", "/path/*", "PATH"), + Arguments.of("/path", "", "/path/*", "PATH") + ); + } + + @ParameterizedTest + @MethodSource("mappings") + public void testHttpServletMapping(String uri, String matchValue, String pattern, String mappingMatch) throws Exception + { + ServletHolder holder = new ServletHolder("MyServlet", new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpServletMapping mapping = req.getHttpServletMapping(); - assertThat(mapping.getMappingMatch(), is(MappingMatch.EXACT)); - assertThat(mapping.getMatchValue(), is("get")); - assertThat(mapping.getPattern(), is("/get")); - - mapping = ServletPathMapping.from(mapping); - assertThat(mapping.getMappingMatch(), is(MappingMatch.EXACT)); - assertThat(mapping.getMatchValue(), is("get")); - assertThat(mapping.getPattern(), is("/get")); - - mapping = ServletPathMapping.from(mapping.toString()); - assertThat(mapping.getMappingMatch(), is(MappingMatch.EXACT)); - assertThat(mapping.getMatchValue(), is("get")); - assertThat(mapping.getPattern(), is("/get")); - - resp.getWriter().println("Hello!"); + resp.getWriter().println(""" + matchValue: '%s' + pattern: '%s' + MappingMatch: '%s' + """.formatted( + mapping.getMatchValue(), + mapping.getPattern(), + mapping.getMappingMatch() + )); } - }, "/get"); + }); + ServletMapping mapping = new ServletMapping(); + mapping.setServletName(holder.getName()); + mapping.setPathSpecs(new String[] + { + "/", + "/MyServlet", + "", + "*.extension", + "/path/*" + }); + _context.getServletHandler().addServlet(holder); + _context.getServletHandler().addServletMapping(mapping); _server.start(); String response = _connector.getResponse(""" - GET /ctx/get HTTP/1.0 + GET /ctx%s HTTP/1.0 - """); + """.formatted(uri)); assertThat(response, containsString(" 200 OK")); - assertThat(response, containsString("Hello!")); + + assertThat(response, containsString(""" + matchValue: '%s' + pattern: '%s' + MappingMatch: '%s' + """.formatted( + matchValue, + pattern, + mappingMatch))); } } diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee11/websocket/tests/HttpSessionTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee11/websocket/tests/HttpSessionTest.java new file mode 100644 index 000000000000..0cf8fc5d968c --- /dev/null +++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee11/websocket/tests/HttpSessionTest.java @@ -0,0 +1,141 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.ee11.websocket.tests; + +import java.net.URI; +import java.util.concurrent.TimeUnit; + +import jakarta.servlet.http.HttpSession; +import org.eclipse.jetty.ee11.servlet.ServletContextHandler; +import org.eclipse.jetty.ee11.websocket.server.config.JettyWebSocketServletContainerInitializer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.websocket.api.Callback; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class HttpSessionTest +{ + private Server _server; + private ServerConnector _connector; + private WebSocketClient _client; + + @WebSocket + public static class HttpSessionEndpoint + { + private final HttpSession.Accessor accessor; + + public HttpSessionEndpoint(HttpSession.Accessor accessor) + { + this.accessor = accessor; + } + + @OnWebSocketOpen + public void onOpen(Session session) + { + accessor.access(httpSession -> httpSession.setAttribute("session", "setByOnOpen")); + } + + @OnWebSocketMessage + public void onMessage(Session session, String message) + { + if ("onOpenAttribute".equals(message)) + { + try + { + accessor.access(httpSession -> + { + String value = (String)httpSession.getAttribute("session"); + session.sendText(value, Callback.NOOP); + }); + } + catch (Throwable t) + { + session.sendText(t.getMessage(), Callback.NOOP); + } + } + else if ("invalidate".equals(message)) + { + accessor.access(HttpSession::invalidate); + session.sendText("success", Callback.NOOP); + } + } + } + + @BeforeEach + public void before() throws Exception + { + _server = new Server(); + _connector = new ServerConnector(_server); + _server.addConnector(_connector); + + ServletContextHandler contextHandler = new ServletContextHandler("/", true, false); + JettyWebSocketServletContainerInitializer.configure(contextHandler, ((servletContext, serverContainer) -> + { + serverContainer.addMapping("/", (req, resp) -> + { + HttpSession.Accessor accessor = req.getHttpServletRequest().getSession(true).getAccessor(); + return new HttpSessionEndpoint(accessor); + }); + })); + _server.setHandler(contextHandler); + _server.start(); + + _client = new WebSocketClient(); + _client.start(); + } + + @AfterEach + public void after() throws Exception + { + _client.stop(); + _server.stop(); + } + + @Test + public void testHttpSessionAfterWebSocketUpgrade() throws Exception + { + EventSocket clientEndpoint = new EventSocket(); + URI uri = URI.create("ws://localhost:" + _connector.getLocalPort()); + Session session = _client.connect(clientEndpoint, uri).get(); + + session.sendText("onOpenAttribute", Callback.NOOP); + String receivedMessage = clientEndpoint.textMessages.poll(5, TimeUnit.SECONDS); + assertThat(receivedMessage, equalTo("setByOnOpen")); + + session.sendText("invalidate", Callback.NOOP); + receivedMessage = clientEndpoint.textMessages.poll(5, TimeUnit.SECONDS); + assertThat(receivedMessage, equalTo("success")); + + session.sendText("onOpenAttribute", Callback.NOOP); + receivedMessage = clientEndpoint.textMessages.poll(5, TimeUnit.SECONDS); + assertThat(receivedMessage, equalTo("Invalid session")); + + session.close(); + assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(clientEndpoint.closeCode, equalTo(StatusCode.NORMAL)); + assertThat(clientEndpoint.closeReason, equalTo(null)); + } +}