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

notion.api.v1.http.OkHttp5Client.kt Maven / Gradle / Ivy

The newest version!
package notion.api.v1.http

import java.util.concurrent.TimeUnit
import notion.api.v1.logging.NotionLogger
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response

class OkHttp5Client : NotionHttpClient {
  private val client: OkHttpClient

  companion object {
    private val MEDIA_TYPE_APPLICATION_JSON = "application/json; charset=utf-8".toMediaType()

    private const val DEFAULT_CONNECT_TIMEOUT_MILLIS = 3_000
    private const val DEFAULT_READ_TIMEOUT_MILLIS = 30_000
    private const val DEFAULT_WRITE_TIMEOUT_MILLIS = 30_000

    fun buildOkHttpClient(
        connectTimeoutMillis: Int = DEFAULT_CONNECT_TIMEOUT_MILLIS,
        writeTimeoutMillis: Int = DEFAULT_CONNECT_TIMEOUT_MILLIS,
        readTimeoutMillis: Int = DEFAULT_CONNECT_TIMEOUT_MILLIS,
    ): OkHttpClient {
      val client: OkHttpClient.Builder = OkHttpClient.Builder()
      client.addInterceptor(UserAgentInterceptor)
      client.connectTimeout(connectTimeoutMillis.toLong(), TimeUnit.MILLISECONDS)
      client.writeTimeout(writeTimeoutMillis.toLong(), TimeUnit.MILLISECONDS)
      client.readTimeout(readTimeoutMillis.toLong(), TimeUnit.MILLISECONDS)
      return client.build()
    }
  }

  object UserAgentInterceptor : Interceptor {
    private val userAgent = UserAgent.buildUserAgent()

    override fun intercept(chain: Interceptor.Chain): Response {
      val request = chain.request().newBuilder().header("User-Agent", userAgent).build()
      return chain.proceed(request)
    }
  }

  constructor() {
    this.client = buildOkHttpClient()
  }

  // TODO: proxy support
  constructor(
      connectTimeoutMillis: Int = DEFAULT_CONNECT_TIMEOUT_MILLIS,
      writeTimeoutMillis: Int = DEFAULT_WRITE_TIMEOUT_MILLIS,
      readTimeoutMillis: Int = DEFAULT_READ_TIMEOUT_MILLIS,
  ) {
    this.client =
        buildOkHttpClient(
            connectTimeoutMillis = connectTimeoutMillis,
            writeTimeoutMillis = writeTimeoutMillis,
            readTimeoutMillis = readTimeoutMillis,
        )
  }

  override fun get(
      logger: NotionLogger,
      url: String,
      query: Map>,
      headers: Map
  ): NotionHttpResponse {
    val fullUrl = buildFullUrl(url, buildQueryString(query))
    val req = Request.Builder().url(fullUrl).get()
    headers.forEach { (name, value) -> req.header(name, value) }
    return perform(req, "", logger)
  }

  override fun postTextBody(
      logger: NotionLogger,
      url: String,
      query: Map>,
      body: String,
      headers: Map
  ): NotionHttpResponse {
    val fullUrl = buildFullUrl(url, buildQueryString(query))
    val req = Request.Builder().url(fullUrl).post(body.toRequestBody(MEDIA_TYPE_APPLICATION_JSON))
    headers.forEach { (name, value) -> req.header(name, value) }
    return perform(req, body, logger)
  }

  override fun patchTextBody(
      logger: NotionLogger,
      url: String,
      query: Map>,
      body: String,
      headers: Map
  ): NotionHttpResponse {
    val fullUrl = buildFullUrl(url, buildQueryString(query))
    val req = Request.Builder().url(fullUrl).patch(body.toRequestBody(MEDIA_TYPE_APPLICATION_JSON))
    headers.forEach { (name, value) -> req.header(name, value) }
    return perform(req, body, logger)
  }

  override fun delete(
      logger: NotionLogger,
      url: String,
      query: Map>,
      headers: Map
  ): NotionHttpResponse {
    val fullUrl = buildFullUrl(url, buildQueryString(query))
    val req = Request.Builder().url(fullUrl).delete()
    headers.forEach { (name, value) -> req.header(name, value) }
    return perform(req, "", logger)
  }

  @Throws(Exception::class)
  override fun close() {
    this.client.dispatcher.executorService.shutdown()
    this.client.connectionPool.evictAll()
    client.cache?.close()
  }

  // ---------------------------------------

  private fun perform(
      req: Request.Builder,
      body: String,
      logger: NotionLogger
  ): NotionHttpResponse {
    val startTimeMillis = System.currentTimeMillis()
    val request = req.build()
    debugLogStart(logger, request.method, request.url.toUrl().toString(), body)
    val resp = client.newCall(req.build()).execute()
    try {
      val response =
          NotionHttpResponse(
              status = resp.code,
              headers = resp.headers.toMultimap(),
              body = resp.body?.string() ?: "")
      debugLogSuccess(logger, startTimeMillis, response)
      return response
    } catch (e: Exception) {
      warnLogFailure(logger, e)
      throw e
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy