Skip to content

Commit a2ab411

Browse files
committed
use aws request and response classes
1 parent be5e8be commit a2ab411

File tree

13 files changed

+128
-179
lines changed

13 files changed

+128
-179
lines changed

.gitignore

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@ bin/
1010
.idea/
1111
out/
1212

13-
# Package Files
14-
*.jar
15-
*.war
16-
*.eargit
17-
1813
# Serverless directories
1914
.serverless
2015

build.gradle.kts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,19 @@ dependencies {
3030
compile(kotlin("stdlib-jdk8"))
3131
compile(kotlin("reflect"))
3232
compile("com.amazonaws:aws-lambda-java-core:1.2.0")
33-
compile("com.amazonaws:aws-lambda-java-log4j2:1.1.0")
34-
compile("com.fasterxml.jackson.core:jackson-databind:2.9.5")
35-
compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.5")
33+
compile("com.amazonaws:aws-lambda-java-events:2.2.5")
34+
35+
compile("org.slf4j:slf4j-api:1.7.26")
36+
compile("com.fasterxml.jackson.core:jackson-databind:2.9.8")
37+
compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8")
3638
compile("com.google.guava:guava:23.0")
37-
compile("com.google.protobuf:protobuf-java:3.5.1")
38-
compile("com.google.protobuf:protobuf-java-util:3.5.1")
39+
compile("com.google.protobuf:protobuf-java:3.6.1")
40+
compile("com.google.protobuf:protobuf-java-util:3.6.1")
3941

40-
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.3.1")
42+
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.4.0")
4143
testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.12")
4244
testImplementation("io.mockk:mockk:1.8.13.kotlin13")
45+
testImplementation("org.slf4j:slf4j-simple:1.7.26")
4346
}
4447

4548
tasks.withType<ShadowJar> {

gradle/wrapper/gradle-wrapper.jar

53.9 KB
Binary file not shown.

gradlew

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ APP_NAME="Gradle"
2828
APP_BASE_NAME=`basename "$0"`
2929

3030
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31-
DEFAULT_JVM_OPTS=""
31+
DEFAULT_JVM_OPTS='"-Xmx64m"'
3232

3333
# Use the maximum available, or set MAX_FD != -1 to use that value.
3434
MAX_FD="maximum"

gradlew.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0
1414
set APP_HOME=%DIRNAME%
1515

1616
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17-
set DEFAULT_JVM_OPTS=
17+
set DEFAULT_JVM_OPTS="-Xmx64m"
1818

1919
@rem Find java.exe
2020
if defined JAVA_HOME goto findJavaFromJavaHome
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.github.mduesterhoeft.router
2+
3+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent
4+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent
5+
import java.util.Base64
6+
7+
fun APIGatewayProxyRequestEvent.acceptHeader() = getHeaderCaseInsensitive("accept")
8+
fun APIGatewayProxyRequestEvent.contentType() = getHeaderCaseInsensitive("content-type")
9+
10+
fun APIGatewayProxyRequestEvent.getHeaderCaseInsensitive(httpHeader: String): String? {
11+
return headers.entries
12+
.firstOrNull { it.key.toLowerCase() == httpHeader.toLowerCase() }
13+
?.value
14+
}
15+
16+
fun APIGatewayProxyResponseEvent.bodyAsBytes() = Base64.getDecoder().decode(body)

src/main/kotlin/com/github/mduesterhoeft/router/ApiRequest.kt

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/main/kotlin/com/github/mduesterhoeft/router/ApiResponse.kt

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/main/kotlin/com/github/mduesterhoeft/router/RequestHandler.kt

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@ package com.github.mduesterhoeft.router
22

33
import com.amazonaws.services.lambda.runtime.Context
44
import com.amazonaws.services.lambda.runtime.RequestHandler
5+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent
6+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent
57
import com.fasterxml.jackson.databind.ObjectMapper
68
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
79
import com.github.mduesterhoeft.router.ProtoBufUtils.toJsonWithoutWrappers
810
import com.google.common.net.MediaType
911
import com.google.protobuf.GeneratedMessageV3
10-
import org.apache.logging.log4j.LogManager
11-
import org.apache.logging.log4j.Logger
12+
import org.slf4j.Logger
13+
import org.slf4j.LoggerFactory
14+
import java.util.Base64
15+
import java.util.logging.LogManager
1216
import kotlin.reflect.KClass
1317
import kotlin.reflect.jvm.reflect
1418

15-
abstract class RequestHandler : RequestHandler<ApiRequest, ApiResponse> {
19+
abstract class RequestHandler : RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
1620

1721
open val objectMapper = jacksonObjectMapper()
1822

19-
override fun handleRequest(input: ApiRequest, context: Context): ApiResponse? {
20-
log.info("handling request with method '${input.httpMethod}' and path '${input.path}' - Accept:${input.acceptHeader} Content-Type:${input.contentType} $input")
23+
@Suppress("UNCHECKED_CAST")
24+
override fun handleRequest(input: APIGatewayProxyRequestEvent, context: Context): APIGatewayProxyResponseEvent? {
25+
log.info("handling request with method '${input.httpMethod}' and path '${input.path}' - Accept:${input.acceptHeader()} Content-Type:${input.contentType()} $input")
2126
val routes = router.routes as List<RouterFunction<Any, Any>>
2227
val matchResults: List<MatchResult> = routes.map { routerFunction: RouterFunction<Any, Any> ->
2328
val matchResult = routerFunction.requestPredicate.match(input)
@@ -36,7 +41,7 @@ abstract class RequestHandler : RequestHandler<ApiRequest, ApiResponse> {
3641

3742
private fun deserializeRequest(
3843
handler: HandlerFunction<Any, Any>,
39-
input: ApiRequest
44+
input: APIGatewayProxyRequestEvent
4045
): Any {
4146
val requestType = handler.reflect()!!.parameters.first().type.arguments.first().type?.classifier as KClass<*>
4247
return when (requestType) {
@@ -46,7 +51,7 @@ abstract class RequestHandler : RequestHandler<ApiRequest, ApiResponse> {
4651
}
4752
}
4853

49-
private fun handleNonDirectMatch(matchResults: List<MatchResult>, input: ApiRequest): ApiResponse {
54+
private fun handleNonDirectMatch(matchResults: List<MatchResult>, input: APIGatewayProxyRequestEvent): APIGatewayProxyResponseEvent {
5055
// no direct match
5156
if (matchResults.any { it.matchPath && it.matchMethod && !it.matchContentType }) {
5257
return createErrorResponse(
@@ -86,44 +91,43 @@ abstract class RequestHandler : RequestHandler<ApiRequest, ApiResponse> {
8691

8792
abstract val router: Router
8893

89-
open fun createErrorResponse(input: ApiRequest, ex: ApiException): ApiResponse =
90-
ApiJsonResponse(
91-
statusCode = ex.statusCode,
92-
headers = mapOf("Content-Type" to "application/json"),
93-
body = objectMapper.writeValueAsString(mapOf(
94+
open fun createErrorResponse(input: APIGatewayProxyRequestEvent, ex: ApiException): APIGatewayProxyResponseEvent =
95+
APIGatewayProxyResponseEvent()
96+
.withBody(objectMapper.writeValueAsString(mapOf(
9497
"message" to ex.message,
9598
"code" to ex.errorCode,
9699
"details" to ex.details
97-
))
98-
)
100+
)))
101+
.withStatusCode(ex.statusCode)
102+
.withHeaders(mapOf("Content-Type" to "application/json"))
99103

100-
open fun <T> createResponse(input: ApiRequest, response: ResponseEntity<T>): ApiResponse {
101-
val accept = MediaType.parse(input.acceptHeader)
104+
open fun <T> createResponse(input: APIGatewayProxyRequestEvent, response: ResponseEntity<T>): APIGatewayProxyResponseEvent {
105+
val accept = MediaType.parse(input.acceptHeader())
102106
return when {
103-
response.body is Unit -> ApiJsonResponse(statusCode = 204, body = null)
104-
accept.`is`(MediaType.parse("application/x-protobuf")) -> ApiProtoResponse(
105-
statusCode = 200,
106-
headers = mapOf("Accept" to "application/x-protobuf"),
107-
body = (response.body as GeneratedMessageV3).toByteArray()
108-
)
107+
response.body is Unit -> APIGatewayProxyResponseEvent()
108+
.withStatusCode(204)
109+
110+
accept.`is`(MediaType.parse("application/x-protobuf")) -> APIGatewayProxyResponseEvent()
111+
.withStatusCode(200)
112+
.withBody(Base64.getEncoder().encodeToString((response.body as GeneratedMessageV3).toByteArray()))
113+
.withHeaders(mapOf("Content-Type" to "application/x-protobuf"))
114+
109115
accept.`is`(MediaType.parse("application/json")) ->
110116
if (response.body is GeneratedMessageV3)
111-
ApiJsonResponse(
112-
statusCode = 200,
113-
headers = mapOf("Content-Type" to "application/json"),
114-
body = toJsonWithoutWrappers(response.body)
115-
)
117+
APIGatewayProxyResponseEvent()
118+
.withStatusCode(200)
119+
.withBody(toJsonWithoutWrappers(response.body))
120+
.withHeaders(mapOf("Content-Type" to "application/json"))
116121
else
117-
ApiJsonResponse(
118-
statusCode = 200,
119-
headers = mapOf("Content-Type" to "application/json"),
120-
body = response.body?.let { objectMapper.writeValueAsString(it) }
121-
)
122+
APIGatewayProxyResponseEvent()
123+
.withStatusCode(200)
124+
.withBody(response.body?.let { objectMapper.writeValueAsString(it) })
125+
.withHeaders(mapOf("Content-Type" to "application/json"))
122126
else -> throw IllegalArgumentException("unsupported response $response")
123127
}
124128
}
125129

126130
companion object {
127-
val log: Logger = LogManager.getLogger(RequestHandler::class.java)
131+
val log: Logger = LoggerFactory.getLogger(RequestHandler::class.java)
128132
}
129133
}

src/main/kotlin/com/github/mduesterhoeft/router/RequestPredicate.kt

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.mduesterhoeft.router
22

3+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent
34
import com.google.common.net.MediaType
45

56
data class RequestPredicate(
@@ -16,22 +17,16 @@ data class RequestPredicate(
1617
produces = mediaTypes.toSet()
1718
}
1819

19-
internal fun match(request: ApiRequest) =
20+
internal fun match(request: APIGatewayProxyRequestEvent) =
2021
MatchResult(
2122
matchPath = pathMatches(request),
2223
matchMethod = methodMatches(request),
23-
matchAcceptType = contentTypeMatches(
24-
request.headers.entries.firstOrNull { it.key.toLowerCase() == "accept" }?.value,
25-
produces
26-
),
27-
matchContentType = contentTypeMatches(
28-
request.headers.entries.firstOrNull { it.key.toLowerCase() == "content-type" }?.value,
29-
consumes
30-
)
24+
matchAcceptType = contentTypeMatches(request.acceptHeader(), produces),
25+
matchContentType = contentTypeMatches(request.contentType(), consumes)
3126
)
3227

33-
private fun pathMatches(request: ApiRequest) = request.path == pathPattern
34-
private fun methodMatches(request: ApiRequest) = method.equals(request.httpMethod, true)
28+
private fun pathMatches(request: APIGatewayProxyRequestEvent) = request.path == pathPattern
29+
private fun methodMatches(request: APIGatewayProxyRequestEvent) = method.equals(request.httpMethod, true)
3530
private fun contentTypeMatches(contentType: String?, accepted: Set<String>) =
3631
if (accepted.isEmpty() && contentType == null) true
3732
else if (contentType == null) false

0 commit comments

Comments
 (0)