Skip to content

Commit

Permalink
refactor: allows script engines to customise request object.
Browse files Browse the repository at this point in the history
  • Loading branch information
outofcoffee committed May 8, 2024
1 parent 4eaffdd commit 0e7f3d8
Show file tree
Hide file tree
Showing 16 changed files with 406 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,13 @@
*/
package io.gatehill.imposter.script

import io.gatehill.imposter.util.CollectionUtil
import java.util.function.Supplier

/**
* Wrapper for context variables available during script execution.
*
* @author Pete Cornish
*/
class ExecutionContext(
request: Request
request: ScriptRequest
) : HashMap<String, Any>() {

init {
Expand All @@ -73,115 +70,4 @@ class ExecutionContext(

return super.get(key)
}

interface Request {
val path: String
val method: String
val uri: String
val headers: Map<String, String>

/**
* @return the request path parameters
*/
val pathParams: Map<String, String>

/**
* @return the request query parameters
*/
val queryParams: Map<String, String>

/**
* @return the request form parameters
*/
val formParams: Map<String, String>

/**
* @return the request body
*/
val body: String?

/**
* @return the [headers] map, but with all keys in lowercase
*/
val normalisedHeaders: Map<String, String>

/**
* Legacy property removed.
*/
@get:Deprecated("Use queryParams instead.", ReplaceWith("queryParams"))
val params: Map<String, String>
}

/**
* Representation of the request, supporting lazily-initialised collections for params and headers.
*/
class RequestImpl(
override val path: String,
override val method: String,
override val uri: String,
private val headersSupplier: Supplier<Map<String, String>>,
private val pathParamsSupplier: Supplier<Map<String, String>>,
private val queryParamsSupplier: Supplier<Map<String, String>>,
private val formParamsSupplier: Supplier<Map<String, String>>,
private val bodySupplier: Supplier<String?>,
) : Request {
override val headers: Map<String, String> by lazy {
headersSupplier.get()
}

/**
* @return the request path parameters
*/
override val pathParams: Map<String, String> get() {
return pathParamsSupplier.get()
}

/**
* @return the request query parameters
*/
override val queryParams: Map<String, String> by lazy {
queryParamsSupplier.get()
}

/**
* @return the request form parameters
*/
override val formParams: Map<String, String> by lazy {
formParamsSupplier.get()
}

/**
* @return the request body
*/
override val body: String? by lazy {
bodySupplier.get()
}

/**
* @return the [headers] map, but with all keys in lowercase
*/
override val normalisedHeaders: Map<String, String>
get() = CollectionUtil.convertKeysToLowerCase(headers)

/**
* Legacy property removed.
*/
@get:Deprecated("Use queryParams instead.", ReplaceWith("queryParams"))
override val params: Map<String, String>
get() = throw UnsupportedOperationException(
"Error: the deprecated 'context.request.params' property was removed. Use 'context.request.queryParams' or 'context.request.pathParams' instead."
)

override fun toString(): String {
return "Request{" +
"path='" + path + '\'' +
", method='" + method + '\'' +
", uri='" + uri + '\'' +
", pathParams=" + pathParams +
", queryParams=" + queryParams +
", headers=" + headers +
", body=<" + (body?.let { "${it.length} bytes" } ?: "null") + '>' +
'}'
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2024.
*
* This file is part of Imposter.
*
* "Commons Clause" License Condition v1.0
*
* The Software is provided to you by the Licensor under the License, as
* defined below, subject to the following condition.
*
* Without limiting other conditions in the License, the grant of rights
* under the License will not include, and the License does not grant to
* you, the right to Sell the Software.
*
* For purposes of the foregoing, "Sell" means practicing any or all of
* the rights granted to you under the License to provide to third parties,
* for a fee or other consideration (including without limitation fees for
* hosting or consulting/support services related to the Software), a
* product or service whose value derives, entirely or substantially, from
* the functionality of the Software. Any license notice or attribution
* required by the License must also include this Commons Clause License
* Condition notice.
*
* Software: Imposter
*
* License: GNU Lesser General Public License version 3
*
* Licensor: Peter Cornish
*
* Imposter is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Imposter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Imposter. If not, see <https://www.gnu.org/licenses/>.
*/

package io.gatehill.imposter.script

interface ScriptRequest {
val path: String
val method: String
val uri: String
val headers: Map<String, String>

/**
* @return the request path parameters
*/
val pathParams: Map<String, String>

/**
* @return the request query parameters
*/
val queryParams: Map<String, String>

/**
* @return the request form parameters
*/
val formParams: Map<String, String>

/**
* @return the request body
*/
val body: String?

/**
* @return the [headers] map, but with all keys in lowercase
*/
val normalisedHeaders: Map<String, String>

/**
* Legacy property removed.
*/
@get:Deprecated("Use queryParams instead.", ReplaceWith("queryParams"))
val params: Map<String, String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,17 @@
*/
package io.gatehill.imposter.service

import io.gatehill.imposter.http.HttpRequest
import io.gatehill.imposter.script.ReadWriteResponseBehaviour
import io.gatehill.imposter.script.RuntimeContext
import io.gatehill.imposter.script.ScriptRequest

/**
* @author Pete Cornish
*/
interface ScriptService {
val requestBuilder: ScriptRequestBuilder

fun initScript(script: ScriptSource) {
// no op
}
Expand All @@ -67,4 +71,7 @@ interface ScriptService {

fun evalInlineScript(scriptId: String, scriptCode: String, runtimeContext: RuntimeContext): Boolean =
throw NotImplementedError()

}

typealias ScriptRequestBuilder = (request: HttpRequest) -> ScriptRequest
Loading

0 comments on commit 0e7f3d8

Please sign in to comment.