I write a simple reverse proxy by Ktor but Error happen : io.ktor.http.UnsafeHeaderException

Viewed 1302

I learn to write a reverse proxy from Reverse Proxy and Asynchronous Streaming using Ktor Client and Server.

When I start the server and browser any Url at browser, no response and error happen.

The Error:

io.ktor.http.UnsafeHeaderException: Header Content-Type is controlled by the engine and cannot be set explicitly

My code:

package com.example

import io.ktor.application.ApplicationCallPipeline
import io.ktor.application.call
import io.ktor.client.HttpClient
import io.ktor.client.request.request
import io.ktor.client.statement.HttpResponse
import io.ktor.http.ContentType
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpStatusCode
import io.ktor.http.content.OutgoingContent
import io.ktor.response.header
import io.ktor.response.respond
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.utils.io.ByteWriteChannel
import io.ktor.utils.io.copyAndClose

fun main(args: Array<String>) {
    // Creates a Netty server
    val server = embeddedServer(Netty, port = 8080) {
        val client = HttpClient()

        intercept(ApplicationCallPipeline.Call) {
            val response = client.request<HttpResponse>("http://localhost:18080/SimpleAp/openApi/env")

            val proxiedHeaders = response.headers
            val location = proxiedHeaders[HttpHeaders.Location]
            val contentType = proxiedHeaders[HttpHeaders.ContentType]
            val contentLength = proxiedHeaders[HttpHeaders.ContentLength]

            if (location != null) {
                call.response.header(HttpHeaders.Location, location)
            }

            call.respond(object : OutgoingContent.WriteChannelContent() {
                override val contentLength: Long? = contentLength?.toLong()
                override val contentType: ContentType? = contentType?.let { ContentType.parse(it) }
//                override val headers: Headers = proxiedHeaders
                override val headers: Headers = Headers.build {
                    appendAll(proxiedHeaders)
                }

                override val status: HttpStatusCode? = response.status
                override suspend fun writeTo(channel: ByteWriteChannel) {
                    response.content.copyAndClose(channel)
                }
            })
        }
    }
    server.start(wait = true)
}

My Environment:

ktor_version=1.3.2
kotlin.code.style=official
kotlin_version=1.3.70

Could anybody help? Thank you very much.

0 Answers
Related