Skip to content

Commit fc7a0bb

Browse files
Merge pull request #3 from mduesterhoeft/convenience
Add more convenience methods to request and response
2 parents 60f9e32 + 5873ea8 commit fc7a0bb

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.mduesterhoeft.router
22

33
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent
44
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent
5+
import java.net.URI
56
import java.util.Base64
67

78
fun APIGatewayProxyRequestEvent.acceptHeader() = getHeaderCaseInsensitive("accept")
@@ -13,6 +14,48 @@ fun APIGatewayProxyRequestEvent.getHeaderCaseInsensitive(httpHeader: String): St
1314
fun APIGatewayProxyResponseEvent.getHeaderCaseInsensitive(httpHeader: String): String? =
1415
getCaseInsensitive(httpHeader, headers)
1516

17+
fun GET() = APIGatewayProxyRequestEvent().withHttpMethod("get").withHeaders(mutableMapOf())
18+
fun GET(path: String) = GET().withPath(path)
19+
fun POST() = APIGatewayProxyRequestEvent().withHttpMethod("post").withHeaders(mutableMapOf())
20+
fun POST(path: String) = POST().withPath(path)
21+
fun PUT() = APIGatewayProxyRequestEvent().withHttpMethod("put").withHeaders(mutableMapOf())
22+
fun PUT(path: String) = PUT().withPath(path)
23+
fun PATCH() = APIGatewayProxyRequestEvent().withHttpMethod("patch").withHeaders(mutableMapOf())
24+
fun PATCH(path: String) = PATCH().withPath(path)
25+
fun DELETE() = APIGatewayProxyRequestEvent().withHttpMethod("delete").withHeaders(mutableMapOf())
26+
fun DELETE(path: String) = DELETE().withPath(path)
27+
28+
/**
29+
* Get a URI that can be used as location header for responses.
30+
* The host is taken from the Host header.
31+
* The protocol is taken from the x-forwarded-proto.
32+
* The port is taken from the x-forwarded-port header. Standard ports are omitted.
33+
*/
34+
fun APIGatewayProxyRequestEvent.location(path: String): URI {
35+
val host = getHeaderCaseInsensitive("host")?:"localhost"
36+
val proto = getHeaderCaseInsensitive("x-forwarded-proto")?:"http"
37+
val portPart = getHeaderCaseInsensitive("x-forwarded-port")
38+
?.let {
39+
when {
40+
proto == "https" && it == "443" -> null
41+
proto == "http" && it == "80" -> null
42+
else -> ":$it"
43+
}
44+
}?: ""
45+
return URI("$proto://$host$portPart/${path.removePrefix("/")}")
46+
}
47+
48+
fun APIGatewayProxyRequestEvent.withHeader(name: String, value: String) =
49+
this.also { if (headers == null) headers = mutableMapOf() }.also { headers[name] = value }
50+
51+
fun APIGatewayProxyResponseEvent.withHeader(name: String, value: String) =
52+
this.also { if (headers == null) headers = mutableMapOf() }.also { headers[name] = value }
53+
54+
fun APIGatewayProxyResponseEvent.withLocationHeader(request: APIGatewayProxyRequestEvent, path: String) =
55+
this.also { if (headers == null) headers = mutableMapOf() }.also { headers["location"] = request.location(path).toString() }
56+
57+
fun APIGatewayProxyResponseEvent.location() = getHeaderCaseInsensitive("location")
58+
1659
private fun getCaseInsensitive(key: String, map: Map<String, String>): String? =
1760
map.entries
1861
.firstOrNull { it.key.toLowerCase() == key.toLowerCase() }
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.github.mduesterhoeft.router
2+
3+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent
4+
import org.assertj.core.api.BDDAssertions.then
5+
import org.junit.jupiter.api.Test
6+
7+
class APIGatewayProxyEventExtensionsTest {
8+
9+
@Test
10+
fun `should add location header`() {
11+
12+
val request = GET()
13+
.withHeader("Host", "example.com")
14+
.withHeader("X-Forwarded-Proto", "http")
15+
.withHeader("X-Forwarded-Port", "8080")
16+
17+
val response = APIGatewayProxyResponseEvent()
18+
.withLocationHeader(request, "/some/path")
19+
20+
then(response.location()).isEqualTo("http://example.com:8080/some/path")
21+
}
22+
23+
@Test
24+
fun `should add location header with default host and proto and without port`() {
25+
26+
val request = GET()
27+
28+
val response = APIGatewayProxyResponseEvent()
29+
.withLocationHeader(request, "/some/path")
30+
31+
then(response.location()).isEqualTo("http://localhost/some/path")
32+
}
33+
34+
@Test
35+
fun `should omit default https port`() {
36+
37+
val request = GET()
38+
.withHeader("Host", "example.com")
39+
.withHeader("X-Forwarded-Proto", "https")
40+
.withHeader("X-Forwarded-Port", "443")
41+
42+
val location = request.location("some/path")
43+
44+
then(location.toString()).isEqualTo("https://example.com/some/path")
45+
}
46+
47+
@Test
48+
fun `should omit default http port`() {
49+
50+
val request = GET()
51+
.withHeader("Host", "example.com")
52+
.withHeader("X-Forwarded-Proto", "http")
53+
.withHeader("X-Forwarded-Port", "80")
54+
55+
val location = request.location("/some/path")
56+
57+
then(location.toString()).isEqualTo("http://example.com/some/path")
58+
}
59+
}

0 commit comments

Comments
 (0)