diff --git a/README.md b/README.md
index ca0af95..4cd03bb 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ repositories {
```
- Add the dependency
```
-implementation 'com.github.DaikonWeb:daikon:0.6.1'
+implementation 'com.github.DaikonWeb:daikon:0.6.2'
```
### Maven
@@ -40,7 +40,7 @@ implementation 'com.github.DaikonWeb:daikon:0.6.1'
com.github.DaikonWeb
daikon
- 0.6.1
+ 0.6.2
```
diff --git a/build.gradle b/build.gradle
index 74041eb..50fc719 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ plugins {
}
group = 'com.github.DaikonWeb'
-version '0.6.1'
+version '0.6.2'
repositories {
mavenCentral()
diff --git a/src/main/kotlin/daikon/Context.kt b/src/main/kotlin/daikon/Context.kt
new file mode 100644
index 0000000..966851d
--- /dev/null
+++ b/src/main/kotlin/daikon/Context.kt
@@ -0,0 +1,6 @@
+package daikon
+
+interface Context {
+ fun addAttribute(key: String, value: Any)
+ fun getAttribute(key: String) : T
+}
\ No newline at end of file
diff --git a/src/main/kotlin/daikon/DefaultRouteAction.kt b/src/main/kotlin/daikon/DefaultRouteAction.kt
index dced03d..aed210a 100644
--- a/src/main/kotlin/daikon/DefaultRouteAction.kt
+++ b/src/main/kotlin/daikon/DefaultRouteAction.kt
@@ -5,7 +5,7 @@ import org.eclipse.jetty.http.HttpStatus.NOT_FOUND_404
import org.eclipse.jetty.http.HttpStatus.OK_200
class DefaultRouteAction : RouteAction {
- override fun handle(request: Request, response: Response) {
+ override fun handle(request: Request, response: Response, context: Context) {
if (request.method() == GET && request.path() == "/") {
response.status(OK_200)
response.type("text/html")
diff --git a/src/main/kotlin/daikon/DummyRouteAction.kt b/src/main/kotlin/daikon/DummyRouteAction.kt
index 1122490..1fb09fc 100644
--- a/src/main/kotlin/daikon/DummyRouteAction.kt
+++ b/src/main/kotlin/daikon/DummyRouteAction.kt
@@ -1,7 +1,13 @@
package daikon
class DummyRouteAction(private val action: (Request, Response) -> Unit) : RouteAction {
- override fun handle(request: Request, response: Response) {
+ override fun handle(request: Request, response: Response, context: Context) {
action.invoke(request, response)
}
+}
+
+class ContextRouteAction(private val action: (Request, Response, Context) -> Unit) : RouteAction {
+ override fun handle(request: Request, response: Response, context: Context) {
+ action.invoke(request, response, context)
+ }
}
\ No newline at end of file
diff --git a/src/main/kotlin/daikon/HttpServer.kt b/src/main/kotlin/daikon/HttpServer.kt
index 63c4ebf..b649e54 100644
--- a/src/main/kotlin/daikon/HttpServer.kt
+++ b/src/main/kotlin/daikon/HttpServer.kt
@@ -15,9 +15,10 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
private val routes = Routing()
private val beforeActions = Routing()
private val afterActions = Routing()
- private val afterStartActions = mutableListOf<() -> Unit>()
- private val beforeStopActions = mutableListOf<() -> Unit>()
+ private val afterStartActions = mutableListOf<(Context) -> Unit>()
+ private val beforeStopActions = mutableListOf<(Context) -> Unit>()
private val basePath = mutableListOf("")
+ private val context = ServerContext()
init {
initializeActions()
@@ -30,17 +31,17 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
fun start(): HttpServer {
val beginStarting = now()
server = Server(port)
- handler.addServlet(ServletHolder(RoutingServlet(beforeActions, routes, afterActions)), "/*")
+ handler.addServlet(ServletHolder(RoutingServlet(beforeActions, routes, afterActions, context)), "/*")
server.handler = handler
server.start()
val endStarting = now()
println("Server up and running on port $port in ${beginStarting.until(endStarting, MILLIS)}ms")
- afterStartActions.forEach { it.invoke() }
+ afterStartActions.forEach { it.invoke(context) }
return this
}
override fun close() {
- beforeStopActions.forEach { it.invoke() }
+ beforeStopActions.forEach { it.invoke(context) }
server.stop()
}
@@ -49,6 +50,11 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
return this
}
+ fun get(path: String, action: (Request, Response, Context) -> Unit): HttpServer {
+ get(path, ContextRouteAction(action))
+ return this
+ }
+
fun get(path: String, action: RouteAction): HttpServer {
add(GET, path, action)
return this
@@ -59,6 +65,11 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
return this
}
+ fun post(path: String, action: (Request, Response, Context) -> Unit): HttpServer {
+ post(path, ContextRouteAction(action))
+ return this
+ }
+
fun post(path: String, action: RouteAction): HttpServer {
add(POST, path, action)
return this
@@ -69,6 +80,11 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
return this
}
+ fun head(path: String, action: (Request, Response, Context) -> Unit): HttpServer {
+ head(path, ContextRouteAction(action))
+ return this
+ }
+
fun head(path: String, action: RouteAction): HttpServer {
add(HEAD, path, action)
return this
@@ -79,6 +95,11 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
return this
}
+ fun any(path: String, action: (Request, Response, Context) -> Unit): HttpServer {
+ any(path, ContextRouteAction(action))
+ return this
+ }
+
fun any(path: String, action: RouteAction): HttpServer {
add(ANY, path, action)
return this
@@ -89,11 +110,21 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
return this
}
+ fun before(path: String = "/*", action: (Request, Response, Context) -> Unit): HttpServer {
+ beforeActions.add(Route(ANY, joinPaths(path), ContextRouteAction(action)))
+ return this
+ }
+
fun after(path: String = "/*", action: (Request, Response) -> Unit): HttpServer {
afterActions.add(Route(ANY, joinPaths(path), DummyRouteAction(action)))
return this
}
+ fun after(path: String = "/*", action: (Request, Response, Context) -> Unit): HttpServer {
+ afterActions.add(Route(ANY, joinPaths(path), ContextRouteAction(action)))
+ return this
+ }
+
fun assets(path: String): HttpServer {
val servletHolder = ServletHolder(DefaultServlet())
handler.addServlet(servletHolder, path)
@@ -108,6 +139,16 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
return this
}
+ fun afterStart(function: (Context) -> Unit): HttpServer {
+ afterStartActions.add(function)
+ return this
+ }
+
+ fun beforeStop(function: (Context) -> Unit): HttpServer {
+ beforeStopActions.add(function)
+ return this
+ }
+
private fun add(method: Method, path: String, action: RouteAction) {
routes.add(Route(method, joinPaths(path), action))
}
@@ -118,14 +159,5 @@ class HttpServer(private val port: Int = 4545, initializeActions: HttpServer.()
Log.getProperties().setProperty("org.eclipse.jetty.util.log.announce", "false")
Log.getProperties().setProperty("org.eclipse.jetty.LEVEL", "OFF")
}
-
- fun afterStart(function: () -> Unit): HttpServer {
- afterStartActions.add(function)
- return this
- }
-
- fun beforeStop(function: () -> Unit): HttpServer {
- beforeStopActions.add(function)
- return this
- }
}
+
diff --git a/src/main/kotlin/daikon/RouteAction.kt b/src/main/kotlin/daikon/RouteAction.kt
index bbdaab5..d0e8fb8 100644
--- a/src/main/kotlin/daikon/RouteAction.kt
+++ b/src/main/kotlin/daikon/RouteAction.kt
@@ -1,5 +1,5 @@
package daikon
interface RouteAction {
- fun handle(request: Request, response: Response)
+ fun handle(request: Request, response: Response, context: Context)
}
diff --git a/src/main/kotlin/daikon/RoutingServlet.kt b/src/main/kotlin/daikon/RoutingServlet.kt
index c15b184..92ba170 100644
--- a/src/main/kotlin/daikon/RoutingServlet.kt
+++ b/src/main/kotlin/daikon/RoutingServlet.kt
@@ -1,8 +1,6 @@
package daikon
import daikon.Method.ANY
-import org.eclipse.jetty.http.HttpStatus.NOT_FOUND_404
-import org.eclipse.jetty.http.HttpStatus.OK_200
import javax.servlet.GenericServlet
import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
@@ -12,7 +10,8 @@ import javax.servlet.http.HttpServletResponse
class RoutingServlet(
private val befores: Routing,
private val routes: Routing,
- private val afters: Routing
+ private val afters: Routing,
+ private val context: Context
) : GenericServlet() {
override fun service(req: ServletRequest, res: ServletResponse) {
@@ -37,6 +36,6 @@ class RoutingServlet(
}
private fun invoke(route: Route, req: HttpServletRequest, res: HttpResponse) {
- route.action.handle(HttpRequest(req, PathParams(route.path)), res)
+ route.action.handle(HttpRequest(req, PathParams(route.path)), res, context)
}
}
diff --git a/src/main/kotlin/daikon/ServerContext.kt b/src/main/kotlin/daikon/ServerContext.kt
new file mode 100644
index 0000000..8b556c6
--- /dev/null
+++ b/src/main/kotlin/daikon/ServerContext.kt
@@ -0,0 +1,15 @@
+package daikon
+
+class ServerContext : Context {
+
+ private val attributes = mutableMapOf()
+
+ override fun addAttribute(key: String, value: Any) {
+ attributes[key] = value
+ }
+
+ override fun getAttribute(key: String): T {
+ @Suppress("UNCHECKED_CAST")
+ return attributes[key] as T
+ }
+}
diff --git a/src/test/kotlin/daikon/DefaultRouteActionTest.kt b/src/test/kotlin/daikon/DefaultRouteActionTest.kt
index cfccbee..a28f81f 100644
--- a/src/test/kotlin/daikon/DefaultRouteActionTest.kt
+++ b/src/test/kotlin/daikon/DefaultRouteActionTest.kt
@@ -13,10 +13,11 @@ class DefaultRouteActionTest {
private val request: Request = mock()
private val response: Response = mock()
+ private val context: Context = mock()
@Test
fun `page not found`() {
- DefaultRouteAction().handle(request, response)
+ DefaultRouteAction().handle(request, response, context)
verify(response).status(NOT_FOUND_404)
}
@@ -26,7 +27,7 @@ class DefaultRouteActionTest {
whenever(request.method()).thenReturn(GET)
whenever(request.path()).thenReturn("/")
- DefaultRouteAction().handle(request, response)
+ DefaultRouteAction().handle(request, response, context)
verify(response).status(OK_200)
verify(response).type("text/html")
diff --git a/src/test/kotlin/daikon/HttpContextTest.kt b/src/test/kotlin/daikon/HttpContextTest.kt
new file mode 100644
index 0000000..0c91ec1
--- /dev/null
+++ b/src/test/kotlin/daikon/HttpContextTest.kt
@@ -0,0 +1,18 @@
+package daikon
+
+import daikon.Localhost.get
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+class HttpContextTest {
+
+ @Test
+ fun `context preserve attributes`() {
+ HttpServer()
+ .afterStart { ctx -> ctx.addAttribute("key", "value") }
+ .get("/") { _, res, ctx -> res.write(ctx.getAttribute("key")) }
+ .start().use {
+ assertThat(get("/").text).isEqualTo("value")
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/daikon/HttpRoutingTest.kt b/src/test/kotlin/daikon/HttpRoutingTest.kt
index f72057e..46fcf78 100644
--- a/src/test/kotlin/daikon/HttpRoutingTest.kt
+++ b/src/test/kotlin/daikon/HttpRoutingTest.kt
@@ -64,7 +64,7 @@ class HttpRoutingTest {
fun `route action`() {
HttpServer()
.get("/foo", object : RouteAction {
- override fun handle(request: Request, response: Response) {
+ override fun handle(request: Request, response: Response, context: Context) {
response.write("Hello foo")
}
})
diff --git a/src/test/kotlin/daikon/NopAction.kt b/src/test/kotlin/daikon/NopAction.kt
index 7205643..566b072 100644
--- a/src/test/kotlin/daikon/NopAction.kt
+++ b/src/test/kotlin/daikon/NopAction.kt
@@ -1,6 +1,6 @@
package daikon
class NopAction : RouteAction {
- override fun handle(request: Request, response: Response) {
+ override fun handle(request: Request, response: Response, context: Context) {
}
}
\ No newline at end of file