Directive for extractScheme does not work with https #658

michael-smith opened this Issue Dec 14, 2016 · 6 comments


None yet

4 participants

michael-smith commented Dec 14, 2016 edited

The extractScheme directive always returns "http" even when "https" is being used.

A basic example using an https context results in "Scheme: http" ...

package org.example

import scala.collection.immutable.Seq
import akka.http._
import akka.http.scaladsl.server._
import akka.http.scaladsl._
import akka.http.scaladsl.model._
import akka.http.scaladsl.server._
import akka.http.scaladsl.server.Directives._

object Main {

  private val httpsConnectionContext = ConnectionContext.https(createSslContext)

  def main(args: Array[String]) {
    implicit val system = ActorSystem("my-system")
    implicit val materializer = ActorMaterializer()
    implicit val executionContext = system.dispatcher

    val route =
      extractScheme { scheme =>
        get {
          println("Scheme is: " + scheme)
          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, s"<h1>Scheme: ${scheme}</h1>"))

    val bindingFuture = Http().bindAndHandle(route, "localhost", 8443, connectionContext = httpsConnectionContext)

    println(s"Server online at https://localhost:8443/\nPress RETURN to stop...")
      .onComplete(_ => system.terminate())

  private def createSslContext: SSLContext = {
    val context = SSLContext.getInstance("TLSv1")
    context.init(keyManagers(context), Array.empty, null)

  private final def keyManagers(sslContext: SSLContext): Array[KeyManager] = {
    val kmf = KeyManagerFactory.getInstance("SunX509")
    val ks = KeyStore.getInstance("JKS")
    val ksPass = "changeit".toCharArray()
    var kms: Array[KeyManager] = null
    val is = getClass.getResourceAsStream("keystore.jks")
    try {
      ks.load(is, ksPass)
      kmf.init(ks, ksPass)
      kms = kmf.getKeyManagers
    } finally { is.close }

Looks like the information if the session is encrypted or not is lost here:
from that point on only the byte content is passed on if I am not mistaken.
Passing that information on would allow to guess the right schema afterwards.


As far as i can see the HttpEntity is created by using information from the passed in via the bystream. All additional information known when receiving this byte stream is not being used to create the HttpEntity. This is can be seen with this example. I would assume that other information is also lost due to this behaviour


The error seems to be done here:

The blueprint needs a flag to be passed in from the outside whether it runs on TLS or not and then at the line above the secureConnection flag must be set accordingly.


No, it should probably be passed from Http.scala.

ktoso commented Jan 5, 2017 edited

Solved 45ce8ad, thanks @zettelmj !

@ktoso ktoso closed this Jan 5, 2017
@ktoso ktoso removed the 1 - triaged label Jan 5, 2017
@ktoso ktoso added this to the 10.0.2 milestone Jan 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment