imposter
imposter copied to clipboard
Request to make Context.Request.toString() produce json
When I first got into the scripting side of imposter.sh I noticed that the JSObject for the context.request doesn't have many of the recommended functions for interfacing with Javascript. I first tried iterating across the queryParams but found that the keySet and the values iterator functions aren't available on the underlying Java objects. I created a dirty workaround by parsing the output of the toString() function since that's the only one available to get all of the data from the JSObject. However, obviously it would be better if I could turn the JSObject into a native Javascript one.
To me there's two options:
- Implement the
keySetandvaluesand other recommended functions on each class as an override - Write a simple JSON serialiser and do
JSON.parse(context.request.toString())
I've attached a simple Kotlin JSON serialiser but am curious to hear your opinion imposter/core/api/src/main/java/io/gatehill/imposter/script/JsonSerializer.kt
package io.gatehill.imposter.script
class JsonSerializer {
companion object {
@JvmStatic
fun serialize(obj: Any?): String {
return when (obj) {
null -> "null"
is String -> {
val escaped = obj.replace("\"", "\\\"")
"\"$escaped\""
}
is Map<*, *> -> serializeMap(obj)
is List<*> -> serializeList(obj)
else -> obj.toString()
}
}
@JvmStatic
fun serializeMap(map: Map<*, *>): String {
val entries = map.entries.map { (key, value) ->
"\"$key\": ${serialize(value)}"
}
return "{${entries.joinToString(", ")}}"
}
@JvmStatic
fun serializeList(list: List<*>): String {
val entries = list.map { serialize(it) }
return "[${entries.joinToString(", ")}]"
}
}
}
imposter/core/api/src/main/java/io/gatehill/imposter/script/ExecutionContext.kt
override fun toString(): String {
val request: Map<String, Any> = mapOf(
"path" to path,
"method" to method,
"uri" to uri,
"pathParams" to pathParams,
"queryParams" to queryParams,
"headers" to headers
)
return JsonSerializer.serialize(request)
}
PS. I'm aware there's a Graal plugin in the works
Hi @Ober3550, thanks very for much for raising this. s part of #557, we've done some work in the Graal engine that makes the Request object work like a regular JavaScript object. This means code like this gives sensible output:
print(JSON.stringify(context.request));
prints:
{"path":"/persons","method":"GET","uri":"http://localhost:8080/persons?foo=bar","headers":{"host":"localhost:8080","user-agent":"curl/8.4.0","accept":"*/*"},"pathParams":{},"queryParams":{"foo":"bar"},"formParams":{},"body":null,"normalisedHeaders":{"host":"localhost:8080","user-agent":"curl/8.4.0","accept":"*/*"}}
Similarly, you can now iterate over the request's members as you'd expect:
for (const queryParam in context.request.queryParams) {
print(queryParam);
}
@Ober3550 we've released v3.40.0, which has the improved js-graal plugin. This one has new plumbing for Graal to understand how to parse objects better.