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

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

package notion.api.v1.http

import notion.api.v1.http.UrlConnPatchMethodWorkaround.setPatchRequestMethod
import notion.api.v1.logging.NotionLogger
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL


class UrlConnNotionHttpClient(
    private val connectTimeoutMillis: Int = 1_000,
    private val readTimeoutMillis: Int = 10_000,
) : NotionHttpClient {

    override fun get(
        logger: NotionLogger,
        url: String,
        query: Map,
        headers: Map
    ): NotionHttpResponse {
        val q = buildQueryString(query)
        val fullUrl = buildFullUrl(url, q)
        val conn = buildConnectionObject(fullUrl, headers)
        try {
            conn.requestMethod = "GET"
            debugLogStart(logger, conn, fullUrl, null)
            connect(conn).use { input ->
                val response = NotionHttpResponse(
                    status = conn.responseCode,
                    body = readResponseBody(input),
                    headers = conn.headerFields
                )
                debugLogSuccess(logger, response)
                return response
            }
        } finally {
            disconnect(conn, logger)
        }
    }

    override fun postTextBody(
        logger: NotionLogger,
        url: String,
        query: Map,
        body: String,
        headers: Map
    ): NotionHttpResponse {
        val q = buildQueryString(query)
        val fullUrl = buildFullUrl(url, q)
        val conn = buildConnectionObject(fullUrl, headers)
        try {
            conn.requestMethod = "POST"
            debugLogStart(logger, conn, fullUrl, body)
            setRequestBody(conn, body)
            connect(conn).use { input ->
                val response = NotionHttpResponse(
                    status = conn.responseCode,
                    body = readResponseBody(input),
                    headers = conn.headerFields
                )
                debugLogSuccess(logger, response)
                return response
            }
        } finally {
            disconnect(conn, logger)
        }
    }

    override fun patchTextBody(
        logger: NotionLogger,
        url: String,
        query: Map,
        body: String,
        headers: Map
    ): NotionHttpResponse {
        val q = buildQueryString(query)
        val fullUrl = buildFullUrl(url, q)
        val conn = buildConnectionObject(fullUrl, headers)
        try {
            setPatchRequestMethod(conn)
            debugLogStart(logger, conn, fullUrl, body)
            setRequestBody(conn, body)
            connect(conn).use { input ->
                val response = NotionHttpResponse(
                    status = conn.responseCode,
                    body = readResponseBody(input),
                    headers = conn.headerFields
                )
                debugLogSuccess(logger, response)
                return response
            }
        } finally {
            disconnect(conn, logger)
        }
    }

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

    private fun buildConnectionObject(fullUrl: String, headers: Map): HttpURLConnection {
        val conn = URL(fullUrl).openConnection() as HttpURLConnection
        conn.setRequestProperty("Connection", "close")
        conn.connectTimeout = connectTimeoutMillis
        conn.readTimeout = readTimeoutMillis
        headers.forEach { (name, value) -> conn.setRequestProperty(name, value) }
        return conn
    }

    private fun setRequestBody(conn: HttpURLConnection, body: String) {
        conn.doOutput = true
        conn.outputStream.use { out -> out.write(body.toByteArray(Charsets.UTF_8)) }
    }

    private fun connect(conn: HttpURLConnection): InputStream = try {
        conn.connect()
        conn.inputStream
    } catch (e: IOException) {
        conn.errorStream
    }

    private fun readResponseBody(input: InputStream?): String {
        return input?.bufferedReader(Charsets.UTF_8).use { it?.readText() } ?: "";
    }

    private fun disconnect(conn: HttpURLConnection, logger: NotionLogger) {
        try {
            conn.disconnect()
        } catch (e: Exception) {
            debugLogFailure(logger, e)
        }
    }

    private fun debugLogStart(
        logger: NotionLogger,
        conn: HttpURLConnection,
        fullUrl: String,
        body: String?,
    ) {
        val b = if (body == null || body.isEmpty()) "" else "body: $body\n"
        logger.debug("Sending a request:\n${conn.requestMethod} $fullUrl\n$b")
    }

    private fun debugLogFailure(logger: NotionLogger, e: Exception) {
        logger.info("Failed to disconnect from Notion: ${e.message}", e)
    }

    private fun debugLogSuccess(
        logger: NotionLogger,
        response: NotionHttpResponse
    ) {
        logger.debug("Received a response:\nstatus ${response.status}\nbody ${response.body}\n")
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy