diff --git a/jooby-servlet/src/main/java/org/jooby/servlet/ServletServletRequest.java b/jooby-servlet/src/main/java/org/jooby/servlet/ServletServletRequest.java index 98d10c9d89..dbe770f7e1 100644 --- a/jooby-servlet/src/main/java/org/jooby/servlet/ServletServletRequest.java +++ b/jooby-servlet/src/main/java/org/jooby/servlet/ServletServletRequest.java @@ -23,12 +23,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.concurrent.Executor; +import java.util.function.Function; import java.util.stream.Collectors; import javax.servlet.ServletException; @@ -119,6 +116,16 @@ public List params(final String name) throws Exception { return Arrays.asList(values); } + @Override + public Map attributes() { + final Enumeration attributeNames = req.getAttributeNames(); + if (!attributeNames.hasMoreElements()) { + return Collections.emptyMap(); + } + return Collections.list(attributeNames).stream() + .collect(Collectors.toMap(Function.identity(), name -> req.getAttribute(name))); + } + @Override public List headers(final String name) { return toList(req.getHeaders(name)); diff --git a/jooby-servlet/src/test/java/org/jooby/servlet/ServletServletRequestTest.java b/jooby-servlet/src/test/java/org/jooby/servlet/ServletServletRequestTest.java index a10d64ee26..0efe1b303e 100644 --- a/jooby-servlet/src/test/java/org/jooby/servlet/ServletServletRequestTest.java +++ b/jooby-servlet/src/test/java/org/jooby/servlet/ServletServletRequestTest.java @@ -4,10 +4,14 @@ import static org.junit.Assert.assertEquals; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; +import com.google.common.collect.ImmutableMap; import org.jooby.MediaType; import org.jooby.test.MockUnit; import org.junit.Test; @@ -148,6 +152,45 @@ public void noparams() throws IOException, Exception { } + @Test + public void attributes() throws Exception { + String tmpdir = System.getProperty("java.io.tmpdir"); + final UUID serverAttribute = UUID.randomUUID(); + new MockUnit(HttpServletRequest.class) + .expect(unit -> { + HttpServletRequest req = unit.get(HttpServletRequest.class); + expect(req.getContentType()).andReturn("text/html"); + expect(req.getPathInfo()).andReturn("/"); + expect(req.getAttributeNames()).andReturn( + Collections.enumeration(Collections.singletonList("server.attribute"))); + expect(req.getAttribute("server.attribute")).andReturn(serverAttribute); + }) + .run(unit -> { + assertEquals(ImmutableMap.of("server.attribute", serverAttribute), + new ServletServletRequest(unit.get(HttpServletRequest.class), tmpdir) + .attributes()); + }); + + } + + @Test + public void emptyAttributes() throws Exception { + String tmpdir = System.getProperty("java.io.tmpdir"); + new MockUnit(HttpServletRequest.class) + .expect(unit -> { + HttpServletRequest req = unit.get(HttpServletRequest.class); + expect(req.getContentType()).andReturn("text/html"); + expect(req.getPathInfo()).andReturn("/"); + expect(req.getAttributeNames()).andReturn(Collections.emptyEnumeration()); + }) + .run(unit -> { + assertEquals(Collections.emptyMap(), + new ServletServletRequest(unit.get(HttpServletRequest.class), tmpdir) + .attributes()); + }); + + } + @Test(expected = IOException.class) public void filesFailure() throws IOException, Exception { String tmpdir = System.getProperty("java.io.tmpdir"); diff --git a/jooby/src/main/java/org/jooby/internal/HttpHandlerImpl.java b/jooby/src/main/java/org/jooby/internal/HttpHandlerImpl.java index d9666ebb99..3e436cbcde 100644 --- a/jooby/src/main/java/org/jooby/internal/HttpHandlerImpl.java +++ b/jooby/src/main/java/org/jooby/internal/HttpHandlerImpl.java @@ -227,6 +227,8 @@ public void handle(final NativeRequest request, final NativeResponse response) t requestPath = rpath.apply(requestPath); } + // put request attributes first to make sure we don't override defaults + locals.putAll(request.attributes()); // default locals locals.put(CONTEXT_PATH, contextPath); locals.put(PATH, requestPath); diff --git a/jooby/src/main/java/org/jooby/spi/NativeRequest.java b/jooby/src/main/java/org/jooby/spi/NativeRequest.java index 91bb5207fa..f6b18bce65 100644 --- a/jooby/src/main/java/org/jooby/spi/NativeRequest.java +++ b/jooby/src/main/java/org/jooby/spi/NativeRequest.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -71,6 +72,13 @@ public interface NativeRequest { */ List params(String name) throws Exception; + /** + * @return Map containing all request attributes + */ + default Map attributes() { + return Collections.emptyMap(); + } + /** * Get all the headers for the provided name or a empty list. *