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

ai.platon.pulsar.protocol.browser.driver.cdt.detail.CDPRequest.kt Maven / Gradle / Ivy

The newest version!
package ai.platon.pulsar.protocol.browser.driver.cdt.detail

import ai.platon.pulsar.browser.driver.chrome.util.ChromeRPCException
import ai.platon.pulsar.common.http.HttpStatus
import ai.platon.pulsar.protocol.browser.driver.cdt.ChromeDevtoolsDriver
import com.github.kklisura.cdt.protocol.v2023.types.fetch.HeaderEntry
import com.github.kklisura.cdt.protocol.v2023.types.network.ErrorReason
import com.github.kklisura.cdt.protocol.v2023.types.network.Initiator
import com.github.kklisura.cdt.protocol.v2023.types.network.Request
import com.github.kklisura.cdt.protocol.v2023.types.network.ResourceType
import java.lang.ref.WeakReference
import java.util.*

class CDPRequest(
        val driver: ChromeDevtoolsDriver,
        /**
         * Request identifier.
         */
        var requestId: String,
        /**
         * Request data.
         */
        val request: Request,
        /**
         * Request identifier.
         */
        val interceptionId: String? = null,

        val allowInterception: Boolean = false,

        val redirectChain: Queue> = LinkedList()
) {
    /**
     * Loader identifier. Empty string if the request is fetched from worker.
     */
    var loaderId: String? = null
    /**
     * URL of the document this request is loaded for.
     */
    var documentURL: String? = null
    /**
     * Request initiator.
     */
    var initiator: Initiator? = null
    /**
     * Type of this resource.
     */
    var type: ResourceType? = null
    
    var response: CDPResponse? = null

    var fromMemoryCache: Boolean = false

    internal var failureText: String? = null

    var interceptionHandled = false

    val isActive get() = driver.isActive

    val url get() = request.url

    private val fetchAPI get() = driver.devTools.fetch.takeIf { isActive }

    fun finalizeInterceptions() {
    }

    fun continueRequest(overrides: ContinueRequestOverrides) {
        interceptionHandled = true

        val postDataBinaryBase64 = overrides.postData?.let { Base64.getEncoder().encodeToString(it.toByteArray()) }
        val requestId = interceptionId ?: throw ChromeRPCException("InterceptionId is required by Fetch.continueRequest")

        try {
            val interceptResponse = false
            fetchAPI?.continueRequest(requestId,
                    overrides.url, overrides.method, postDataBinaryBase64, overrides.headers, interceptResponse)
        } catch (e: Exception) {
            interceptionHandled = false
        }
    }

    fun respond(response: ResponseForRequest) {
        interceptionHandled = true

        val responseBody = when (val body = response.body) {
            is ByteArray -> body
            is String -> body.toByteArray()
            else -> body.toString().toByteArray()
        }

        val responseHeaders = response.headers.entries.mapTo(mutableListOf()) { (name, value) -> headerEntry(name, value) }
        response.contentType?.let { responseHeaders.add(headerEntry("content-type", it)) }
        if (!response.headers.containsKey("content-length")) {
            responseHeaders.add(headerEntry("content-length", responseBody.size.toString()))
        }
        val binaryResponseHeaders = responseHeaders.joinToString()

        val requestId = interceptionId ?: throw ChromeRPCException("InterceptionId is required by Fetch.fulfillRequest")

        val responseCode = response.status ?: 200
        val httpStatus = HttpStatus.valueOf(responseCode)

        try {
            val responseBodyBase64 = Base64.getEncoder().encodeToString(responseBody)
            // Provides response to the request.
            fetchAPI?.fulfillRequest(requestId,
                responseCode, responseHeaders, binaryResponseHeaders, responseBodyBase64, httpStatus.reasonPhrase)
        } catch (e: Exception) {
            interceptionHandled = false
        }
    }
    
    fun abort(abortErrorReason: ErrorReason?) {
        interceptionHandled = true
        
        interceptionId?.let { fetchAPI?.failRequest(it, abortErrorReason) }
            ?: throw ChromeRPCException("HTTPRequest is missing _interceptionId needed for Fetch.failRequest")
    }

    private fun headerEntry(name: String, value: String): HeaderEntry {
        return HeaderEntry().also { it.name = name; it.value = value }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy