- package com.hexagonkt.rest.tools
- import com.hexagonkt.core.media.MediaType
- import com.hexagonkt.core.urlOf
- import com.hexagonkt.http.SslSettings
- import com.hexagonkt.http.client.HttpClient
- import com.hexagonkt.http.client.HttpClientPort
- import com.hexagonkt.http.client.HttpClientSettings
- import com.hexagonkt.http.handlers.BeforeHandler
- import com.hexagonkt.http.handlers.HttpHandler
- import com.hexagonkt.http.model.HttpRequest
- import com.hexagonkt.http.model.*
- import com.hexagonkt.http.model.HttpMethod.*
- import com.hexagonkt.http.model.HttpStatusType.SUCCESS
- import com.hexagonkt.http.patterns.createPathPattern
- import com.hexagonkt.rest.SerializeRequestCallback
- data class HttpClientTool(
- val adapter: HttpClientPort,
- val url: String? = null,
- val httpContentType: ContentType? = null,
- val httpAccept: List<ContentType> = emptyList(),
- val httpHeaders: Map<String, *> = emptyMap<String, Any>(),
- val sslSettings: SslSettings? = SslSettings(),
- val handler: HttpHandler? = serializeHandler,
- val authorization: Authorization? = null,
- val followRedirects: Boolean = false
- ) {
- companion object {
- // TODO Use SerializeRequestHandler when created
- val serializeHandler: HttpHandler = BeforeHandler("*", SerializeRequestCallback())
- }
- private val settings =
- HttpClientSettings(
- baseUrl = url?.let(::urlOf),
- contentType = httpContentType,
- accept = httpAccept,
- useCookies = true,
- headers = toHeaders(httpHeaders),
- insecure = true,
- sslSettings = sslSettings,
- authorization = authorization,
- followRedirects = followRedirects
- )
- private val client = HttpClient(adapter, settings, handler = handler)
- private lateinit var lastRequest: HttpRequest
- private lateinit var lastAttributes: Map<String, *>
- private lateinit var lastResponse: HttpResponsePort
- val request: HttpRequest get() = lastRequest
- val attributes: Map<String, *> get() = lastAttributes
- val response: HttpResponsePort get() = lastResponse
- val status: HttpStatus get() = lastResponse.status
- val body: Any get() = lastResponse.body
- val cookies: Map<String, Cookie> get() = lastResponse.cookiesMap()
- val headers: Headers get() = lastResponse.headers
- val contentType: ContentType? get() = lastResponse.contentType
- constructor(
- adapter: HttpClientPort,
- url: String? = null,
- mediaType: MediaType,
- accept: List<MediaType> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- sslSettings: SslSettings? = SslSettings(),
- handler: HttpHandler? = serializeHandler,
- ) : this(
- adapter,
- url,
- ContentType(mediaType),
- accept.map(::ContentType),
- headers,
- sslSettings,
- handler
- )
- fun start() {
- if (!client.started())
- client.start()
- }
- fun stop() {
- if (client.started())
- client.stop()
- }
- fun request(block: HttpClientTool.() -> Unit) {
- client.request { block.invoke(this@HttpClientTool) }
- }
- fun assertStatus(status: HttpStatus) {
- assert(status == lastResponse.status)
- }
- fun assertOk() {
- assertStatus(OK_200)
- }
- fun assertStatus(statusType: HttpStatusType) {
- assert(statusType == lastResponse.status.type)
- }
- fun assertSuccess() {
- assertStatus(SUCCESS)
- }
- fun assertContentType(contentType: ContentType) {
- assert(this.contentType == contentType)
- }
- fun assertContentType(mediaType: MediaType) {
- assert(contentType == ContentType(mediaType))
- }
- fun assertBody(body: Any) {
- assert(body == lastResponse.body)
- }
- fun assertBodyContains(vararg texts: String) {
- texts.forEach { assert(lastResponse.bodyString().contains(it)) }
- }
- private fun toHeaders(map: Map<String, *>): Headers = Headers(
- map.mapValues { (k, v) ->
- Header(
- k,
- when (v) {
- is Collection<*> -> v.map { it.toString() }.toList()
- else -> listOf(v.toString())
- }
- )
- }
- )
- private fun send(
- method: HttpMethod = GET,
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- attributes: Map<String, Any> = emptyMap(),
- ): HttpResponsePort =
- client
- .apply {
- if (!started())
- start()
- lastAttributes = attributes
- lastRequest = HttpRequest(
- method = method,
- path = path,
- body = body,
- headers = toHeaders(headers),
- formParameters = FormParameters(formParameters),
- parts = parts,
- contentType = contentType,
- accept = accept,
- )
- }
- .send(lastRequest, attributes = attributes)
- .apply { lastResponse = this }
- private fun send(
- method: HttpMethod = GET,
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- attributes: Map<String, Any> = emptyMap(),
- ): HttpResponsePort =
- send(
- method = method,
- path = createPathPattern(path.first, false).insertParameters(path.second),
- body = body,
- formParameters = formParameters,
- headers = toHeaders(headers),
- parts = parts,
- contentType = contentType,
- accept = accept,
- attributes = attributes
- + mapOf("pathPattern" to path.first, "pathParameters" to path.second),
- )
- fun get(
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(GET, path, body, formParameters, headers, parts, contentType, accept)
- fun put(
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(PUT, path, body, formParameters, headers, parts, contentType, accept)
- fun put(
- path: String = "/",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- body: () -> Any,
- ): HttpResponsePort =
- put(path, body(), formParameters, headers, parts, contentType, accept)
- fun post(
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(POST, path, body, formParameters, headers, parts, contentType, accept)
- fun post(
- path: String = "/",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- body: () -> Any,
- ): HttpResponsePort =
- post(path, body(), formParameters, headers, parts, contentType, accept)
- fun options(
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(OPTIONS, path, body, formParameters, headers, parts, contentType, accept)
- fun delete(
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(DELETE, path, body, formParameters, headers, parts, contentType, accept)
- fun patch(
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(PATCH, path, body, formParameters, headers, parts, contentType, accept)
- fun trace(
- path: String = "/",
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(TRACE, path, body, formParameters, headers, parts, contentType, accept)
- fun get(
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(GET, path, body, formParameters, headers, parts, contentType, accept)
- fun put(
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(PUT, path, body, formParameters, headers, parts, contentType, accept)
- fun put(
- path: Pair<String, Map<String, Any>>,
- formParameters: List<FormParameter> = emptyList(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- body: () -> Any,
- ): HttpResponsePort =
- put(path, body(), formParameters, Headers(), parts, contentType, accept)
- fun post(
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(POST, path, body, formParameters, headers, parts, contentType, accept)
- fun post(
- path: Pair<String, Map<String, Any>>,
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- body: () -> Any,
- ): HttpResponsePort =
- post(path, body(), formParameters, headers, parts, contentType, accept)
- fun options(
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(OPTIONS, path, body, formParameters, headers, parts, contentType, accept)
- fun delete(
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(DELETE, path, body, formParameters, headers, parts, contentType, accept)
- fun patch(
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(PATCH, path, body, formParameters, headers, parts, contentType, accept)
- fun trace(
- path: Pair<String, Map<String, Any>>,
- body: Any = "",
- formParameters: List<FormParameter> = emptyList(),
- headers: Map<String, *> = emptyMap<String, Any>(),
- parts: List<HttpPart> = emptyList(),
- contentType: ContentType? = settings.contentType,
- accept: List<ContentType> = settings.accept,
- ): HttpResponsePort =
- send(TRACE, path, body, formParameters, headers, parts, contentType, accept)
- }