Concept: API Clients
Each system API Client is modelled as a single function with arity 1 (that is it takes only a single parameter) returning a Result4k Success/Failure monad type), which is known as an Action. The Client is responsible for managing the overall protocol with the remote system. There are also a set of extension methods generated to provide a more traditional function-based version of the same interface.
The module naming scheme for API Clients is:
org.http4k:http4k-connect-{vendor}-{system}
Action classes are responsible for constructing the HTTP requests and unmarshalling their responses into the http4k-connect types. There are lots of common actions built-in, but you can provide your own by simply implementing the relevant Action interface. The recommended pattern in http4k-connect is to use a Result monad type (we use Result4k) to represent the result type, but you can use anything to suit your programming model.
package content.ecosystem.connect.concepts.clients
import dev.forkhandles.result4k.Result
import org.http4k.connect.Action
import org.http4k.connect.RemoteFailure
// Generic system interface
interface Example {
operator fun <R : Any> invoke(request: ExampleAction<R>): Result<R, RemoteFailure>
companion object
}
// System-specific action
interface ExampleAction<R> : Action<Result<R, RemoteFailure>>
// Action and response classes
data class Echo(val value: String) : ExampleAction<Echoed> {
override fun toRequest() = org.http4k.core.Request(org.http4k.core.Method.GET, "/echo").body(value)
override fun toResult(response: org.http4k.core.Response) = dev.forkhandles.result4k.Success(Echoed(response.bodyString()))
}
data class Echoed(val value: String)
// Traditional function helpers
fun Example.echo(value: String): Result<Echoed, RemoteFailure> = this(Echo(value))
Example usage
package content.ecosystem.connect.concepts.clients
import dev.forkhandles.result4k.Result
import org.http4k.connect.RemoteFailure
import org.http4k.core.HttpHandler
import org.http4k.core.Response
import org.http4k.core.Status.Companion.OK
// constructing and using the clients
val httpHandler: HttpHandler = { Response(OK) }
//val example = Example.Http(httpHandler)
//val echoed: Result<Echoed, RemoteFailure> = example.echo("hello world")
// or...
//val alsoEchoed: Result<Echoed, RemoteFailure> = example(Echo("hello world"))
