We’ve implemented an endpoint exposing our typesafe config object (simplified from our real code):
// https://github.com/lightbend/config/blob/master/HOCON.md#mime-type
case class Hocon() extends CodecFormat {
override val mediaType: MediaType = MediaType("application", "hocon")
}
val hoconBody: EndpointIO.Body[String, Config] = EndpointIO.Body(
bodyType = stringBody.bodyType,
codec = stringBody.codec.format(Hocon()).map(s => ConfigFactory.parseString(s))(_.root().render()),
info = EndpointIO.Info.empty)
val parseJSON: String => DecodeResult[Config] = inputString => Try {
ConfigFactory.parseString(
inputString,
ConfigParseOptions
.defaults()
.setSyntax(ConfigSyntax.JSON))
}.fold(DecodeResult.Error(inputString, _), DecodeResult.Value.apply)
val formatJSON: Config => String = _.root().render(
ConfigRenderOptions
.concise()
.setJson(true))
and:
// this is probably wrong, but not sure how to fix
val configCustomJsonCodec: JsonCodec[Config] = Codec.json[Config](parseJSON)(formatJSON)(Schema.string[Config])
The endpoint itself is defined by (simplified from original):
val paths: EndpointInput.PathCapture[List[String]] = path[String]
.name("path")
.description("Configuration key paths, separated by ','")
.map(_.split(',').toList)(_.mkString(","))
val configAtPath = customBase
.name("configAtPath")
.description("Get configuration for some path(s)")
.in(paths)
.get
.out(oneOfBody(hoconBody, customCodecJsonBody[Config](configCustomJsonCodec)))
and logic is implemented with (also simplified):
val config: Config = …
configAtPath.serverLogicPure(traversePaths(config, _))
def traversePaths(config: Config, paths: List[String]): Either[ManagedError, Config] = {
val (errors, confs) = paths.partitionWith(getConfig(config, _))
if (errors.isEmpty) Right(confs.reduce(_ withFallback _))
else Left(NotFound(errors.mkString("\n")))
}
def getConfig(config: Config, path: String): Either[ManagedError, Config] =
if (config.hasPath(path)) Right(config.withOnlyPath(path))
else Left(NotFound(s"'$path' does not exist in configuration."))
The thing is, that the resulting schema has responses section that looks like:
responses:
'200':
description: ''
content:
application/hocon:
schema:
type: string
application/json:
schema:
type: string
And it seems like I should have type: object
instead of type: string
for the JSON part, but since I used Schema.string[Config]
for configCustomJsonCodec
it’s probably why it’s a string.
But I couldn’t figure out what to use for a free form JSON object like that.
Is there an easy fix I’m missing here?
Thanks!