eclipse-vertx / vert.x

Vert.x is a tool-kit for building reactive applications on the JVM
http://vertx.io
Other
14.26k stars 2.07k forks source link

Persistent HTTP/1.1 connection doesn't get upgraded to HTTP/2 #5289

Open pingw33n opened 4 weeks ago

pingw33n commented 4 weeks ago

Version

4.5.9

Steps to reproduce

Kotlin code (the issue isn't Kotlin-specific):

fun main() {
    val vertx = Vertx.vertx()
    val server = vertx.createHttpServer()

    server.requestHandler { request ->
        request.response().end("Hello World!")
    }

    Thread {
        server.listen(8123)
    }.start()

    Thread.sleep(500)

//    val hostPort = "nghttp2.org" to 80
    val hostPort = "localhost" to 8123
    val socket = Socket(hostPort.first, hostPort.second)
    val inp = BufferedReader(InputStreamReader(socket.getInputStream()))
    val out = OutputStreamWriter(socket.getOutputStream())

    fun writeRequest(upgrade: Boolean) {
        out.write("GET / HTTP/1.1\r\n")
        out.write("Host: ${hostPort.first}:${hostPort.second}\r\n")
        if (upgrade) {
            out.write("Connection: Upgrade, HTTP2-Settings\r\n")
            out.write("Upgrade: h2c\r\n")
            out.write("HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n")
        }
        out.write("\r\n")
        out.flush()
    }

    fun readResponse(): String {
        val response = StringBuilder()
        var contentLength: Int? = null
        for (i in 1..Int.MAX_VALUE) {
            val line = inp.readLine()!!
            if (line.isEmpty()) {
                break
            }
            if (line.lowercase().startsWith("content-length:")) {
                check(contentLength == null)
                contentLength = line.substring("content-length:".length).trim().toInt()
            }
            if (i == 1) {
                response.append(line + '\n')
            }
        }
        if (contentLength != null) {
            inp.skip(contentLength.toLong())
        }
        return response.toString()
    }

    writeRequest(upgrade = false)
    println(readResponse())

    writeRequest(upgrade = true)
    println(readResponse())
}

The above code prints:

HTTP/1.1 200 OK
HTTP/1.1 200 OK

While it's expected to print:

HTTP/1.1 200 OK
HTTP/1.1 101 Switching Protocols