Skip to content

Commit 58cde5f

Browse files
committed
fix(awslambda): extends path param normalisation to all adapters.
1 parent 096eb22 commit 58cde5f

File tree

20 files changed

+466
-154
lines changed

20 files changed

+466
-154
lines changed

adapter/awslambda/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ apply plugin: 'java-library'
22
apply plugin: 'kotlin'
33

44
ext {
5-
version_junit_jupiter = '5.10.0'
65
version_lambda_logger = '1.5.1'
76
}
87

adapter/awslambda/src/main/java/io/gatehill/imposter/awslambda/impl/ServerV1.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import io.gatehill.imposter.util.HttpUtil
5959
*/
6060
class ServerV1(
6161
responseService: ResponseService,
62-
router: HttpRouter,
62+
private val router: HttpRouter,
6363
) : LambdaServer<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent>(responseService, router) {
6464

6565
init {
@@ -74,7 +74,7 @@ class ServerV1(
7474
return HttpUtil.readAcceptedContentTypes(event.headers["Accept"]).contains(HttpUtil.CONTENT_TYPE_HTML)
7575
}
7676

77-
override fun buildRequest(event: APIGatewayProxyRequestEvent, route: HttpRoute?) = LambdaHttpRequestV1(event, route)
77+
override fun buildRequest(event: APIGatewayProxyRequestEvent, route: HttpRoute?) = LambdaHttpRequestV1(event, router, route)
7878

7979
override fun buildResponse(response: LambdaHttpResponse) = APIGatewayProxyResponseEvent().apply {
8080
// read status again in case modified by error handler

adapter/awslambda/src/main/java/io/gatehill/imposter/awslambda/impl/ServerV2.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import io.gatehill.imposter.util.HttpUtil
5959
*/
6060
class ServerV2(
6161
responseService: ResponseService,
62-
router: HttpRouter,
62+
private val router: HttpRouter,
6363
) : LambdaServer<APIGatewayV2HTTPEvent, APIGatewayV2HTTPResponse>(responseService, router) {
6464

6565
init {
@@ -74,7 +74,7 @@ class ServerV2(
7474
return HttpUtil.readAcceptedContentTypes(event.headers["Accept"]).contains(HttpUtil.CONTENT_TYPE_HTML)
7575
}
7676

77-
override fun buildRequest(event: APIGatewayV2HTTPEvent, route: HttpRoute?) = LambdaHttpRequestV2(event, route)
77+
override fun buildRequest(event: APIGatewayV2HTTPEvent, route: HttpRoute?) = LambdaHttpRequestV2(event, router, route)
7878

7979
override fun buildResponse(response: LambdaHttpResponse) = APIGatewayV2HTTPResponse().apply {
8080
// read status again in case modified by error handler

adapter/awslambda/src/main/java/io/gatehill/imposter/awslambda/impl/model/LambdaHttpRequestV1.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ import io.gatehill.imposter.awslambda.util.FormParserUtil
4949
import io.gatehill.imposter.http.HttpMethod
5050
import io.gatehill.imposter.http.HttpRequest
5151
import io.gatehill.imposter.http.HttpRoute
52+
import io.gatehill.imposter.http.HttpRouter
53+
import io.gatehill.imposter.http.util.PathNormaliser
5254
import io.gatehill.imposter.script.LowercaseKeysMap
5355
import io.vertx.core.buffer.Buffer
5456
import io.vertx.core.json.JsonObject
@@ -58,6 +60,7 @@ import io.vertx.core.json.JsonObject
5860
*/
5961
class LambdaHttpRequestV1(
6062
private val event: APIGatewayProxyRequestEvent,
63+
private val router: HttpRouter,
6164
private val currentRoute: HttpRoute?,
6265
) : HttpRequest {
6366
private val baseUrl: String
@@ -91,10 +94,10 @@ class LambdaHttpRequestV1(
9194
}
9295

9396
override val pathParams: Map<String, String>
94-
get() = pathParameters
97+
get() = PathNormaliser.denormaliseParams(router.normalisedParams, pathParameters)
9598

9699
override fun getPathParam(paramName: String): String? {
97-
return pathParameters[paramName]
100+
return pathParameters[PathNormaliser.getNormalisedParamName(router.normalisedParams, paramName)]
98101
}
99102

100103
override val queryParams: Map<String, String>

adapter/awslambda/src/main/java/io/gatehill/imposter/awslambda/impl/model/LambdaHttpRequestV2.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ import io.gatehill.imposter.awslambda.util.FormParserUtil
4949
import io.gatehill.imposter.http.HttpMethod
5050
import io.gatehill.imposter.http.HttpRequest
5151
import io.gatehill.imposter.http.HttpRoute
52+
import io.gatehill.imposter.http.HttpRouter
53+
import io.gatehill.imposter.http.util.PathNormaliser
5254
import io.gatehill.imposter.script.LowercaseKeysMap
5355
import io.vertx.core.buffer.Buffer
5456
import io.vertx.core.json.JsonObject
@@ -58,6 +60,7 @@ import io.vertx.core.json.JsonObject
5860
*/
5961
class LambdaHttpRequestV2(
6062
private val event: APIGatewayV2HTTPEvent,
63+
private val router: HttpRouter,
6164
private val currentRoute: HttpRoute?,
6265
) : HttpRequest {
6366
private val baseUrl: String
@@ -91,10 +94,10 @@ class LambdaHttpRequestV2(
9194
}
9295

9396
override val pathParams: Map<String, String>
94-
get() = pathParameters
97+
get() = PathNormaliser.denormaliseParams(router.normalisedParams, pathParameters)
9598

9699
override fun getPathParam(paramName: String): String? {
97-
return pathParameters[paramName]
100+
return pathParameters[PathNormaliser.getNormalisedParamName(router.normalisedParams, paramName)]
98101
}
99102

100103
override val queryParams: Map<String, String>

adapter/vertxweb/build.gradle

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ apply plugin: 'java-library'
22
apply plugin: 'kotlin'
33
apply plugin: 'maven-publish'
44

5-
ext {
6-
version_junit_jupiter = '5.10.0'
7-
}
8-
95
compileJava {
106
sourceCompatibility = JavaVersion.VERSION_11
117
}

adapter/vertxweb/src/main/java/io/gatehill/imposter/server/vertxweb/VertxWebServerFactoryImpl.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,22 +134,21 @@ class VertxWebServerFactoryImpl : ServerFactory {
134134
}
135135

136136
private fun convertRouterToVertx(router: HttpRouter) = Router.router(router.vertx).also { vertxRouter ->
137-
val normalisedParams = mutableMapOf<String, String>()
138137
router.routes.forEach { httpRoute ->
139138
val vertxRoute = httpRoute.regex?.let { regex ->
140139
httpRoute.method?.let { method -> vertxRouter.routeWithRegex(method.convertMethodToVertx(), regex) }
141140
?: vertxRouter.routeWithRegex(regex)
142141

143142
} ?: httpRoute.path?.let { path ->
144-
val normalisedPath = VertxResourceUtil.normalisePath(normalisedParams, path)
145-
httpRoute.method?.let { method -> vertxRouter.route(method.convertMethodToVertx(), normalisedPath) }
146-
?: vertxRouter.route(normalisedPath)
143+
val convertedPath = VertxResourceUtil.convertPath(path)
144+
httpRoute.method?.let { method -> vertxRouter.route(method.convertMethodToVertx(), convertedPath) }
145+
?: vertxRouter.route(convertedPath)
147146

148147
} ?: vertxRouter.route()
149148

150149
val handler = httpRoute.handler ?: throw IllegalStateException("No route handler set for: $httpRoute")
151150
vertxRoute.handler { rc ->
152-
val exchange = VertxHttpExchange(router, normalisedParams, rc, httpRoute)
151+
val exchange = VertxHttpExchange(router, httpRoute, rc)
153152

154153
// don't block the event loop
155154
handler(exchange).handle { _, t ->
@@ -161,7 +160,7 @@ class VertxWebServerFactoryImpl : ServerFactory {
161160

162161
router.errorHandlers.forEach { (statusCode, errorHandler) ->
163162
vertxRouter.errorHandler(statusCode) { rc ->
164-
errorHandler(VertxHttpExchange(router, normalisedParams, rc, null))
163+
errorHandler(VertxHttpExchange(router, null, rc))
165164
}
166165
}
167166
}

adapter/vertxweb/src/main/java/io/gatehill/imposter/server/vertxweb/impl/VertxHttpExchange.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,13 @@ import io.vertx.ext.web.impl.ParsableMIMEValue
5656
*/
5757
class VertxHttpExchange(
5858
private val router: HttpRouter,
59-
normalisedParams: Map<String, String>,
60-
internal val routingContext: RoutingContext,
6159
override val currentRoute: HttpRoute?,
60+
internal val routingContext: RoutingContext,
6261
) : HttpExchange {
6362
override var phase = ExchangePhase.REQUEST_RECEIVED
6463

6564
override val request: HttpRequest by lazy {
66-
VertxHttpRequest(normalisedParams, routingContext)
65+
VertxHttpRequest(router, routingContext)
6766
}
6867

6968
override val response: HttpResponse by lazy {

adapter/vertxweb/src/main/java/io/gatehill/imposter/server/vertxweb/impl/VertxHttpRequest.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ package io.gatehill.imposter.server.vertxweb.impl
4444

4545
import io.gatehill.imposter.http.HttpMethod
4646
import io.gatehill.imposter.http.HttpRequest
47-
import io.gatehill.imposter.server.vertxweb.util.VertxResourceUtil
47+
import io.gatehill.imposter.http.HttpRouter
48+
import io.gatehill.imposter.http.util.PathNormaliser
4849
import io.gatehill.imposter.server.vertxweb.util.VertxResourceUtil.convertMethodFromVertx
4950
import io.gatehill.imposter.util.CollectionUtil
5051
import io.vertx.core.buffer.Buffer
@@ -55,7 +56,7 @@ import io.vertx.ext.web.RoutingContext
5556
* @author Pete Cornish
5657
*/
5758
class VertxHttpRequest(
58-
private val normalisedParams: Map<String, String>,
59+
private val router: HttpRouter,
5960
private val routingContext: RoutingContext,
6061
) : HttpRequest {
6162
private val vertxRequest = routingContext.request()
@@ -80,10 +81,10 @@ class VertxHttpRequest(
8081
}
8182

8283
override val pathParams: Map<String, String>
83-
get() = VertxResourceUtil.denormaliseParams(normalisedParams, routingContext.pathParams())
84+
get() = PathNormaliser.denormaliseParams(router.normalisedParams, routingContext.pathParams())
8485

8586
override fun getPathParam(paramName: String): String? {
86-
return routingContext.pathParam(VertxResourceUtil.getNormalisedParamName(normalisedParams, paramName))
87+
return routingContext.pathParam(PathNormaliser.getNormalisedParamName(router.normalisedParams, paramName))
8788
}
8889

8990
override val queryParams: Map<String, String>

adapter/vertxweb/src/main/java/io/gatehill/imposter/server/vertxweb/util/VertxResourceUtil.kt

Lines changed: 7 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -42,32 +42,16 @@
4242
*/
4343
package io.gatehill.imposter.server.vertxweb.util
4444

45-
import com.google.common.base.Strings
4645
import com.google.common.collect.BiMap
4746
import com.google.common.collect.HashBiMap
4847
import io.gatehill.imposter.config.util.EnvVars
4948
import io.gatehill.imposter.http.HttpMethod
5049
import io.gatehill.imposter.http.HttpRoute
51-
import org.apache.logging.log4j.LogManager
52-
import java.util.UUID
5350

5451
/**
5552
* @author Pete Cornish
5653
*/
5754
object VertxResourceUtil {
58-
private val LOGGER = LogManager.getLogger(VertxResourceUtil::class.java)
59-
60-
/**
61-
* Vert.x documentation says:
62-
* > The placeholders consist of : followed by the parameter name.
63-
* > Parameter names consist of any alphabetic character, numeric character or underscore.
64-
*
65-
* See: https://vertx.io/docs/vertx-web/java/#_capturing_path_parameters
66-
*
67-
* This regex pattern does not include the colon prefix.
68-
*/
69-
private val VERTX_PATH_PARAM_NAME = Regex("[a-zA-Z0-9_]+")
70-
7155
private val METHODS: BiMap<HttpMethod, io.vertx.core.http.HttpMethod?> = HashBiMap.create()
7256

7357
/**
@@ -100,10 +84,7 @@ object VertxResourceUtil {
10084
METHODS.inverse()[this] ?: throw UnsupportedOperationException("Unknown method: $this")
10185

10286
/**
103-
* Normalises path parameters to Vert.x format.
104-
*
105-
* If a path parameter name does not match the Vert.x format, it is replaced with a UUID,
106-
* and a mapping is added to the `normalisedParams` map.
87+
* Converts path parameters to Vert.x format.
10788
*
10889
* For example:
10990
* ```
@@ -113,62 +94,27 @@ object VertxResourceUtil {
11394
* ```
11495
* /:pathParam/notParam
11596
* ```
116-
*
117-
* A path parameter name that does not match the Vert.x format, such as:
118-
* ```
119-
* /{param-with-dashes}
120-
* ```
121-
* will be converted to:
122-
* ```
123-
* /:123e4567e89b12d3a4564266141740000
124-
* ```
125-
* and the mapping `param-with-dashes -> 123e4567e89b12d3a4564266141740000`
126-
* will be added to the `normalisedParams` map.
127-
*
128-
* @param normalisedParams a map to store the normalised parameter names
12997
* @param rawPath the path to normalise
13098
*/
131-
fun normalisePath(normalisedParams: MutableMap<String, String>, rawPath: String): String {
99+
fun convertPath(rawPath: String): String {
132100
var path = rawPath
133-
if (!Strings.isNullOrEmpty(path)) {
101+
if (path.isNotEmpty()) {
134102
if (escapeColonsInPath) {
135103
path = path.replace(":", "%3A")
136104
}
137105

106+
// convert to colon format
138107
var matchFound: Boolean
139108
do {
140109
val matcher = HttpRoute.PATH_PARAM_PLACEHOLDER.matcher(path)
141110
matchFound = matcher.find()
142111
if (matchFound) {
143-
val finalParamName = matcher.group(1).let { paramName ->
144-
if (paramName.matches(VERTX_PATH_PARAM_NAME)) {
145-
paramName
146-
} else {
147-
val existingMapping = normalisedParams.entries.find { it.value == paramName }
148-
if (null != existingMapping) {
149-
return@let existingMapping.key
150-
}
151-
val normalisedName = UUID.randomUUID().toString().replace("-", "")
152-
normalisedParams[normalisedName] = paramName
153-
normalisedName
154-
}
155-
}
156-
path = matcher.replaceFirst(":$finalParamName")
112+
val paramName = matcher.group(1)
113+
path = matcher.replaceFirst(":$paramName")
157114
}
158115
} while (matchFound)
159116
}
160-
return path
161-
}
162-
163-
fun getNormalisedParamName(normalisedParams: Map<String, String>, originalParamName: String): String {
164-
if (originalParamName.matches(VERTX_PATH_PARAM_NAME)) {
165-
return originalParamName
166-
}
167-
return normalisedParams.entries.find { it.value == originalParamName }?.key ?: originalParamName
168-
}
169117

170-
fun denormaliseParams(normalisedParams: Map<String, String>, vertxParams: Map<String, String>): Map<String, String> {
171-
// if it's not in the map it doesn't need to be denormalised
172-
return vertxParams.mapKeys { normalisedParams[it.key] ?: it.key }
118+
return path
173119
}
174120
}

0 commit comments

Comments
 (0)