Skip to content

Commit

Permalink
feat: allows random generator to be used in scripts.
Browse files Browse the repository at this point in the history
  • Loading branch information
outofcoffee committed Oct 16, 2024
1 parent 6604338 commit 3325d97
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ package io.gatehill.imposter.service.script
import com.google.common.cache.CacheBuilder
import io.gatehill.imposter.ImposterConfig
import io.gatehill.imposter.config.util.EnvVars
import io.gatehill.imposter.expression.helper.RandomHelper
import io.gatehill.imposter.http.HttpExchange
import io.gatehill.imposter.http.HttpRouter
import io.gatehill.imposter.lifecycle.EngineLifecycleHooks
Expand Down Expand Up @@ -251,9 +252,12 @@ class ScriptedResponseServiceImpl @Inject constructor(
scriptEngineName: String,
executionContext: ExecutionContext
): Map<String, Any> {
val additionalBindings = mutableMapOf<String, Any>(
"random" to RandomHelper
)

// fire pre-context build hooks
if (!scriptLifecycle.isEmpty) {
val additionalBindings = mutableMapOf<String, Any>()
scriptLifecycle.forEach { listener ->
listener.beforeBuildingRuntimeContext(
httpExchange,
Expand All @@ -262,11 +266,8 @@ class ScriptedResponseServiceImpl @Inject constructor(
executionContext
)
}
if (additionalBindings.isNotEmpty()) {
return additionalBindings
}
}
return emptyMap()
return additionalBindings
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,13 @@

package io.gatehill.imposter.expression.eval

import io.gatehill.imposter.expression.helper.RandomHelper
import io.gatehill.imposter.util.splitOnCommaAndTrim
import org.apache.logging.log4j.LogManager
import java.util.UUID

object RandomEvaluator : ExpressionEvaluator<String> {
override val name = "random"

val alphabetUpper = ('A'..'Z')
val alphabetLower = ('a'..'z')
val numbers = ('0'..'9')

private val LOGGER = LogManager.getLogger(RandomEvaluator::class.java)

override fun eval(expression: String, context: Map<String, *>): String? {
Expand Down Expand Up @@ -92,27 +88,16 @@ object RandomEvaluator : ExpressionEvaluator<String> {
it.substring(1, it.length - 1)
}

val random = when (type) {
"alphabetic" -> getRandomString(length, alphabetUpper + alphabetLower)
"alphanumeric" -> getRandomString(length, alphabetUpper + alphabetLower + numbers)
"any" -> {
if (chars == null) {
LOGGER.warn("chars string must be provided for random type 'any'")
return null
}
getRandomString(length, chars.toList())
}
"numeric" -> getRandomString(length, numbers.toList())
"uuid" -> UUID.randomUUID().toString()
return when (type) {
"alphabetic" -> RandomHelper.alphabetic(length, uppercase)
"alphanumeric" -> RandomHelper.alphanumeric(length, uppercase)
"any" -> RandomHelper.any(length, uppercase, chars)
"numeric" -> RandomHelper.numeric(length, uppercase)
"uuid" -> RandomHelper.uuid(uppercase)
else -> {
LOGGER.warn("Could not parse random expression: $randomConfig")
return null
null
}
}
return if (uppercase) random.uppercase() else random
}

private fun getRandomString(length: Int, allowedChars: List<Char>) = (1..length)
.map { allowedChars.random() }
.joinToString("")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2024-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.expression.helper

import org.apache.logging.log4j.LogManager
import java.util.*

/**
* Generates random values in different formats.
*/
object RandomHelper {
private val logger = LogManager.getLogger(RandomHelper::class.java)

internal val alphabetUpper = ('A'..'Z')
internal val alphabetLower = ('a'..'z')
internal val numbers = ('0'..'9')

fun alphabetic(length: Int, uppercase: Boolean): String {
return applyCase(uppercase, getRandomString(length, alphabetUpper + alphabetLower))
}

fun alphanumeric(length: Int, uppercase: Boolean): String {
return applyCase(uppercase, getRandomString(length, alphabetUpper + alphabetLower + numbers))
}

fun any(length: Int, uppercase: Boolean, chars: String?): String? {
if (chars == null) {
logger.warn("chars string must be provided for random type 'any'")
return null
}
return applyCase(uppercase, getRandomString(length, chars.toList()))
}

fun numeric(length: Int, uppercase: Boolean): String {
return applyCase(uppercase, getRandomString(length, numbers.toList()))
}

fun uuid(uppercase: Boolean): String {
return applyCase(uppercase, UUID.randomUUID().toString())
}

private fun applyCase(uppercase: Boolean, value: String): String =
if (uppercase) value.uppercase() else value

private fun getRandomString(length: Int, allowedChars: List<Char>) = (1..length)
.map { allowedChars.random() }
.joinToString("")
}

0 comments on commit 3325d97

Please sign in to comment.