Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open API Specification - Consume Server Details & update base url with respect to server details #1440

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
15 changes: 12 additions & 3 deletions application/src/main/kotlin/application/HTTPStubEngine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ class HTTPStubEngine {
specmaticConfigPath: String? = null,
httpClientFactory: HttpClientFactory,
workingDirectory: WorkingDirectory,
gracefulRestartTimeoutInMs: Long
gracefulRestartTimeoutInMs: Long,
pathPrefix: String? = null,
serverDescription: String? = null
): HttpStub? {
val features = stubs.map { it.first }

Expand All @@ -43,11 +45,18 @@ class HTTPStubEngine {
httpClientFactory = httpClientFactory,
workingDirectory = workingDirectory,
specmaticConfigPath = specmaticConfigPath,
timeoutMillis = gracefulRestartTimeoutInMs
timeoutMillis = gracefulRestartTimeoutInMs,
pathPrefix = pathPrefix,
serverDescription = serverDescription
).also {
consoleLog(NewLineLogMessage)
val protocol = if (keyStoreData != null) "https" else "http"
consoleLog(StringLog("Stub server is running on ${protocol}://$host:$port. Ctrl + C to stop."))
val finalPathPrefix = pathPrefix?.let { "/${it.trim('/')}" } ?: it.serverUrlFromOpenSpecs?.let { java.net.URL(it).path }
consoleLog(
StringLog(
"Stub server is running on ${protocol}://${host}:$port${finalPathPrefix.orEmpty()}. Ctrl + C to stop."
)
)
}
}
}
69 changes: 56 additions & 13 deletions application/src/main/kotlin/application/StubCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import io.specmatic.core.Configuration.Companion.DEFAULT_HTTP_STUB_HOST
import io.specmatic.core.Configuration.Companion.DEFAULT_HTTP_STUB_PORT
import io.specmatic.core.log.*
import io.specmatic.core.utilities.ContractPathData
import io.specmatic.core.utilities.Flags.Companion.PATH_PREFIX
import io.specmatic.core.utilities.Flags.Companion.SERVER_DESCRIPTION
import io.specmatic.core.utilities.Flags.Companion.SPECMATIC_STUB_DELAY
import io.specmatic.core.utilities.exitIfAnyDoNotExist
import io.specmatic.core.utilities.throwExceptionIfDirectoriesAreInvalid
Expand Down Expand Up @@ -47,19 +49,31 @@ class StubCommand : Callable<Unit> {
@Option(names = ["--port"], description = ["Port for the http stub"], defaultValue = DEFAULT_HTTP_STUB_PORT)
var port: Int = 0

@Option(names = ["--pathPrefix"], description = ["Path prefix to actual url"])
var pathPrefix: String? = null

@Option(names = ["--strict"], description = ["Start HTTP stub in strict mode"], required = false)
var strictMode: Boolean = false

@Option(names = ["--passThroughTargetBase"], description = ["All requests that did not match a url in any contract will be forwarded to this service"])
@Option(
names = ["--passThroughTargetBase"],
description = ["All requests that did not match a url in any contract will be forwarded to this service"]
)
var passThroughTargetBase: String = ""

@Option(names = ["--httpsKeyStore"], description = ["Run the proxy on https using a key in this store"])
var keyStoreFile = ""

@Option(names = ["--httpsKeyStoreDir"], description = ["Run the proxy on https, create a store named $APPLICATION_NAME_LOWER_CASE.jks in this directory"])
@Option(
names = ["--httpsKeyStoreDir"],
description = ["Run the proxy on https, create a store named $APPLICATION_NAME_LOWER_CASE.jks in this directory"]
)
var keyStoreDir = ""

@Option(names = ["--httpsKeyStorePassword"], description = ["Run the proxy on https, password for pre-existing key store"])
@Option(
names = ["--httpsKeyStorePassword"],
description = ["Run the proxy on https, password for pre-existing key store"]
)
var keyStorePassword = "forgotten"

@Option(names = ["--httpsKeyAlias"], description = ["Run the proxy on https using a key by this name"])
Expand All @@ -71,7 +85,10 @@ class StubCommand : Callable<Unit> {
@Option(names = ["--debug"], description = ["Debug logs"])
var verbose = false

@Option(names = ["--config"], description = ["Configuration file name ($APPLICATION_NAME_LOWER_CASE.json by default)"])
@Option(
names = ["--config"],
description = ["Configuration file name ($APPLICATION_NAME_LOWER_CASE.json by default)"]
)
var configFileName: String? = null

@Option(names = ["--textLog"], description = ["Directory in which to write a text log"])
Expand All @@ -92,7 +109,14 @@ class StubCommand : Callable<Unit> {
@Option(names = ["--delay-in-ms"], description = ["Stub response delay in milliseconds"])
var delayInMilliseconds: Long = 0

@Option(names = ["--graceful-restart-timeout-in-ms"], description = ["Time to wait for the server to stop before starting it again"])
@Option(names = ["--description"], description = ["The server description to pickup the server url"])
var serverDescription: String? = null

@Option(
names = ["--graceful-restart-timeout-in-ms"],
description = ["Time to wait for the server to stop before starting it again"]
)

var gracefulRestartTimeoutInMs: Long = 1000

@Autowired
Expand All @@ -104,7 +128,7 @@ class StubCommand : Callable<Unit> {
@Autowired
val httpClientFactory = HttpClientFactory()

private var contractSources:List<ContractPathData> = emptyList()
private var contractSources: List<ContractPathData> = emptyList()

var specmaticConfigPath: String? = null

Expand All @@ -113,9 +137,12 @@ class StubCommand : Callable<Unit> {
System.setProperty(SPECMATIC_STUB_DELAY, delayInMilliseconds.toString())
}

pathPrefix?.let { System.setProperty(PATH_PREFIX, it) }
serverDescription?.let { System.setProperty(SERVER_DESCRIPTION, it) }

val logPrinters = configureLogPrinters()

logger = if(verbose)
logger = if (verbose)
Verbose(CompositePrinter(logPrinters))
else
NonVerbose(CompositePrinter(logPrinters))
Expand All @@ -133,6 +160,7 @@ class StubCommand : Callable<Unit> {
specmaticConfigPath = File(Configuration.configFilePath).canonicalPath
specmaticConfig.contractStubPathData()
}

else -> contractPaths.map {
ContractPathData("", it)
}
Expand All @@ -142,7 +170,7 @@ class StubCommand : Callable<Unit> {
validateContractFileExtensions(contractPaths, fileOperations)
startServer()

if(httpStub != null) {
if (httpStub != null) {
addShutdownHook()
val watcher = watchMaker.make(contractPaths.plus(exampleDirs))
watcher.watchForChanges {
Expand Down Expand Up @@ -183,7 +211,7 @@ class StubCommand : Callable<Unit> {

private fun startServer() {
val workingDirectory = WorkingDirectory()
if(strictMode) throwExceptionIfDirectoriesAreInvalid(exampleDirs, "example directories")
if (strictMode) throwExceptionIfDirectoriesAreInvalid(exampleDirs, "example directories")
val stubData = stubLoaderEngine.loadStubs(contractSources, exampleDirs, specmaticConfigPath, strictMode)

val certInfo = CertInfo(keyStoreFile, keyStoreDir, keyStorePassword, keyStoreAlias, keyPassword)
Expand All @@ -192,12 +220,25 @@ class StubCommand : Callable<Unit> {
true -> if (portIsInUse(host, port)) findRandomFreePort() else port
false -> port
}
httpStub = httpStubEngine.runHTTPStub(stubData, host, port, certInfo, strictMode, passThroughTargetBase, specmaticConfigPath, httpClientFactory, workingDirectory, gracefulRestartTimeoutInMs)
httpStub = httpStubEngine.runHTTPStub(
stubData,
host,
port,
certInfo,
strictMode,
passThroughTargetBase,
specmaticConfigPath,
httpClientFactory,
workingDirectory,
gracefulRestartTimeoutInMs,
pathPrefix,
serverDescription
)

LogTail.storeSnapshot()
}

private fun isDefaultPort(port:Int): Boolean {
private fun isDefaultPort(port: Int): Boolean {
return DEFAULT_HTTP_STUB_PORT == port.toString()
}

Expand All @@ -207,10 +248,12 @@ class StubCommand : Callable<Unit> {
stopServer()
consoleLog(StringLog("Stopped."))
} catch (e: Throwable) {
consoleLog(e,"Error stopping server")
consoleLog(e, "Error stopping server")
}

try { startServer() } catch (e: Throwable) {
try {
startServer()
} catch (e: Throwable) {
consoleLog(e, "Error starting server")
}
}
Expand Down
6 changes: 5 additions & 1 deletion application/src/main/kotlin/application/TestCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import io.specmatic.test.SpecmaticJUnitSupport.Companion.HOST
import io.specmatic.test.SpecmaticJUnitSupport.Companion.INLINE_SUGGESTIONS
import io.specmatic.test.SpecmaticJUnitSupport.Companion.OVERLAY_FILE_PATH
import io.specmatic.test.SpecmaticJUnitSupport.Companion.PORT
import io.specmatic.test.SpecmaticJUnitSupport.Companion.SERVER_DESCRIPTION
import io.specmatic.test.SpecmaticJUnitSupport.Companion.SUGGESTIONS_PATH
import io.specmatic.test.SpecmaticJUnitSupport.Companion.TEST_BASE_URL
import io.specmatic.test.SpecmaticJUnitSupport.Companion.VARIABLES_FILE_NAME
Expand Down Expand Up @@ -157,6 +158,9 @@ For example:
@Option(names = ["--overlay-file"], description = ["Overlay file for the specification"], required = false)
var overlayFilePath: String? = null

@Option(names = ["--description"], description = ["The server description to pickup the server url"])
var description: String ?= null

override fun call() = try {
setParallelism()

Expand Down Expand Up @@ -194,7 +198,7 @@ For example:
System.setProperty(FILTER, filter.joinToString(";"))
System.setProperty(FILTER_NOT, filterNot.joinToString(";"))
System.setProperty(OVERLAY_FILE_PATH, overlayFilePath.orEmpty())

System.setProperty(SERVER_DESCRIPTION, description.orEmpty())
if(exampleDirs.isNotEmpty()) {
System.setProperty(EXAMPLE_DIRECTORIES, exampleDirs.joinToString(","))
}
Expand Down
4 changes: 2 additions & 2 deletions application/src/test/kotlin/application/StubCommandTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ internal class StubCommandTest {
val port = 9000
val certInfo = CertInfo()
val strictMode = false

val baseUrl = ""
every {
httpStubEngine.runHTTPStub(
stubInfo,
Expand Down Expand Up @@ -216,7 +216,7 @@ internal class StubCommandTest {
val certInfo = CertInfo()
val strictMode = false
val passThroughTargetBase = "http://passthroughTargetBase"

val baseUrl = ""
every {
httpStubEngine.runHTTPStub(
stubInfo,
Expand Down
Loading