All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ecwid.clickhouse.transport.httpclient.ApacheHttpClientTransport.kt Maven / Gradle / Ivy

package com.ecwid.clickhouse.transport.httpclient

import com.ecwid.clickhouse.ClickHouseException
import com.ecwid.clickhouse.transport.ClickhouseCredentials
import com.ecwid.clickhouse.transport.HttpResponse
import com.ecwid.clickhouse.transport.HttpTransport
import org.apache.http.HttpHeaders
import org.apache.http.client.HttpClient
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager
import org.apache.http.message.BasicHeader
import java.nio.charset.StandardCharsets
import java.util.*

private const val DEFAULT_MAX_CONNECTIONS = 100
private const val DEFAULT_MAX_PER_ROUTE_CONNECTIONS = 50

private const val DEFAULT_CONNECTION_TIMEOUT = 5000
private const val DEFAULT_READ_TIMEOUT = 10000

class ApacheHttpClientTransport @JvmOverloads constructor(
	connectTimeoutMs: Int = DEFAULT_CONNECTION_TIMEOUT,
	readTimeoutMs: Int = DEFAULT_READ_TIMEOUT,
	credentials: ClickhouseCredentials? = null
) : HttpTransport {

	private val httpClient: HttpClient

	init {
		val connectionManager = PoolingHttpClientConnectionManager()
		connectionManager.maxTotal = DEFAULT_MAX_CONNECTIONS
		connectionManager.defaultMaxPerRoute =
			DEFAULT_MAX_PER_ROUTE_CONNECTIONS

		val requestConfig = RequestConfig.custom()
			.setConnectTimeout(connectTimeoutMs)
			.setConnectionRequestTimeout(connectTimeoutMs)
			.setSocketTimeout(readTimeoutMs)
			.build()

		val httpClientBuilder = HttpClientBuilder.create()
			.setConnectionManager(connectionManager)
			.setDefaultRequestConfig(requestConfig)

		if (credentials != null) {
			val encodedCredentials = Base64.getEncoder().encodeToString(
				"${credentials.username}:${credentials.password}".toByteArray(StandardCharsets.UTF_8)
			)
			httpClientBuilder.setDefaultHeaders(
				setOf(
					BasicHeader(HttpHeaders.AUTHORIZATION, "Basic $encodedCredentials")
				)
			)
		}
		this.httpClient = httpClientBuilder.build()
	}

	override fun makePostRequest(uri: String, content: String): HttpResponse {
		val request = HttpPost(uri)
		request.entity = StringEntity(content, Charsets.UTF_8)

		val response = try {
			httpClient.execute(request)
		} catch (e: Exception) {
			throw ClickHouseException("Can't execute ClickHouse request", e)
		}

		val statusCode = response.statusLine.statusCode
		val statusMsg = response.statusLine.reasonPhrase
		val responseContent = response.entity.content

		return HttpResponse(statusCode, statusMsg, StreamContent(responseContent, response.entity))
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy