Skip to content

Commit

Permalink
fix(awslambda): attributes should persist between exchanges for the s…
Browse files Browse the repository at this point in the history
…ame request/response pair.
  • Loading branch information
outofcoffee committed Oct 1, 2024
1 parent 739270a commit 1c7c4ca
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ abstract class LambdaServer<Request, Response>(

fun dispatch(event: Request): Response {
val response = LambdaHttpResponse()
val attributes = mutableMapOf<String, Any>()

var failureCause: Throwable? = null
try {
val matched = matchRoutes(event)
Expand All @@ -87,7 +89,7 @@ abstract class LambdaServer<Request, Response>(
} else {
matched.forEach { route ->
val request = buildRequest(event, route)
val exchange = LambdaHttpExchange(router, route, request, response)
val exchange = LambdaHttpExchange(router, route, request, response, attributes)
val handler = route.handler ?: throw IllegalStateException("No route handler set for: $route")
try {
handler(exchange).get()
Expand All @@ -111,12 +113,12 @@ abstract class LambdaServer<Request, Response>(
when (val statusCode = response.statusCode) {
in 400..499 -> {
errorHandlers[statusCode]?.let { errorHandler ->
failExchange(event, response, statusCode, null, errorHandler)
failExchange(event, response, attributes, statusCode, null, errorHandler)
} ?: logger.warn("Unhandled client error for: ${describeRequestShort(event)} [status code: $statusCode]")
}
in 500..599 -> {
errorHandlers[statusCode]?.let { errorHandler ->
failExchange(event, response, statusCode, failureCause, errorHandler)
failExchange(event, response, attributes, statusCode, failureCause, errorHandler)
} ?: logger.error("Unhandled server error for: ${describeRequestShort(event)} [status code: $statusCode]", failureCause)
}
}
Expand All @@ -127,12 +129,13 @@ abstract class LambdaServer<Request, Response>(
private fun failExchange(
event: Request,
response: LambdaHttpResponse,
attributes: MutableMap<String, Any>,
statusCode: Int,
failureCause: Throwable?,
errorHandler: (HttpExchange) -> Unit,
) {
val request = buildRequest(event, null)
val exchange = LambdaHttpExchange(router, null, request, response)
val exchange = LambdaHttpExchange(router, null, request, response, attributes)
exchange.fail(statusCode, failureCause)
errorHandler(exchange)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,7 @@
package io.gatehill.imposter.awslambda.impl.model

import com.google.common.base.Strings
import io.gatehill.imposter.http.ExchangePhase
import io.gatehill.imposter.http.HttpExchange
import io.gatehill.imposter.http.HttpRequest
import io.gatehill.imposter.http.HttpResponse
import io.gatehill.imposter.http.HttpRoute
import io.gatehill.imposter.http.HttpRouter
import io.gatehill.imposter.http.*
import io.gatehill.imposter.util.HttpUtil
import io.vertx.core.buffer.Buffer

Expand All @@ -61,9 +56,14 @@ class LambdaHttpExchange(
override val currentRoute: HttpRoute?,
override val request: HttpRequest,
response: HttpResponse,

/**
* Externally manage the lifecycle of attributes so they persist between exchange
* instances for the same request/response pair.
*/
private val attributes : MutableMap<String, Any>,
) : HttpExchange {
override var phase = ExchangePhase.REQUEST_RECEIVED
private val attributes = mutableMapOf<String, Any>()

override var failureCause: Throwable? = null
private set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,7 @@ import com.google.common.collect.Lists
import io.gatehill.imposter.ImposterConfig
import io.gatehill.imposter.config.ResolvedResourceConfig
import io.gatehill.imposter.config.util.EnvVars
import io.gatehill.imposter.http.ExchangePhase
import io.gatehill.imposter.http.HttpExchange
import io.gatehill.imposter.http.HttpExchangeFutureHandler
import io.gatehill.imposter.http.HttpExchangeHandler
import io.gatehill.imposter.http.HttpMethod
import io.gatehill.imposter.http.HttpRouter
import io.gatehill.imposter.http.ResourceMatcher
import io.gatehill.imposter.http.*
import io.gatehill.imposter.lifecycle.SecurityLifecycleHooks
import io.gatehill.imposter.lifecycle.SecurityLifecycleListener
import io.gatehill.imposter.plugin.config.InterceptorsHolder
Expand All @@ -73,7 +67,7 @@ import kotlinx.coroutines.future.future
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.LogManager
import java.io.File
import java.util.UUID
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.regex.Pattern
import javax.inject.Inject
Expand Down Expand Up @@ -155,6 +149,8 @@ class HandlerServiceImpl @Inject constructor(
httpExchange.get<Boolean>(ResourceUtil.RC_SEND_NOT_FOUND_RESPONSE) == true
) {
// only override response processing if the 404 did not originate from the mock engine
// otherwise this will attempt to send a duplicate response to an already completed
// exchange, resulting in an IllegalStateException
logAppropriatelyForPath(httpExchange, "File not found")
responseService.sendNotFoundResponse(httpExchange)
}
Expand Down

0 comments on commit 1c7c4ca

Please sign in to comment.