En Vertx, necesito networkingirigir todas las requestes HTTP a la misma URL, pero para HTTPS

He escrito un controller Vertx-web en Koltin que networkingirige cualquier request que recibo que sea HTTP a HTTPS, y estoy usando context.request().isSSL para determinar si la request no es SSL, y funcionó bien hasta que puse mi código detrás de un equilibrador de carga. Si el equilibrador de carga habla con mi server Vertx-web en HTTPS, entonces piensa que todas las requestes de los usuarios son HTTPS, incluso si no lo son. Y si cambio el equilibrador de carga para hablar con Vertx-web en HTTP, entonces todas las requestes se networkingirigen sin fin, incluso si el usuario ya está usando HTTPS.

Luego, también veo otro problema, que la networkingirección usando context.request().absoluteURI() va a la dirección privada en lugar de a la dirección disponible públicamente con la que el usuario está hablando.

¿Hay un controller en Vertx-web que me falta que hace esto, o alguna forma idiomática de resolver esto? ¿Debo hacer esto desde JavaScript ya que ve la dirección real del usuario en lugar de intentar networkingireccionar el server?

Estoy codificando en Kotlin, ¡así que cualquier ejemplo para ese idioma es genial!

Nota: esta pregunta fue escrita y respondida intencionalmente por el autor ( Preguntas que responden por sí mismas ), de modo que las soluciones para problemas interesantes se comparten en SO.

En primer lugar, es mejor si su proxy o equilibrador de carga puede hacer esta comprobación y networkingirigir para usted, ya que tiene conocimiento de la URL pública y es un process más simple en ese primer contacto con el usuario. Pero también puedes hacerlo desde el lado del server con un poco más de complejidad.

La bandera que está marcando, context.request().isSSL solo es válida para la connection entrante a Vertx-web y no considera la connection del usuario final con su proxy o balanceador de carga. Debe usar el encabezado X-Forwarded-Proto (y a veces X-Forwarded-Scheme ) y verificar el protocolo real del usuario. Y solo si ese encabezado no está presente, puede usar context.request().isSSL

También necesita externalizar su propia URL para poder networkingirigir en el server a algo que el browser pueda usar para encontrarlo, su URL pública.

Primero, hay una function de Kotlin en esta respuesta de desbordamiento de stack para RoutingContext.externalizeUrl() , la necesitará aquí:
Tengo una request de Vertx y necesito calcular una URL externa visible (pública)

Luego, conociendo su URL pública, puede usar el siguiente controller que tiene valores pnetworkingeterminados para el puerto HTTPS público previsto (el valor pnetworkingeterminado 443 desaparecerá de la URL ), qué forma de networkingirección ( es decir, 302 ) y sobre cualquier exception si la ruta falla o continuado:

 fun Route.networkingirectToHttpsHandler(publicHttpsPort: Int = 443, networkingirectCode: Int = 302, failOnUrlBuilding: Boolean = true) { handler { context -> val proto = context.request().getHeader("X-Forwarded-Proto") ?: context.request().getHeader("X-Forwarded-Scheme") if (proto == "https") { context.next() } else if (proto.isNullOrBlank() && context.request().isSSL) { context.next() } else { try { val myPublicUri = URI(context.externalizeUrl()) val myHttpsPublicUri = URI("https", myPublicUri.userInfo, myPublicUri.host, publicHttpsPort, myPublicUri.rawPath, myPublicUri.rawQuery, myPublicUri.rawFragment) context.response().putHeader("location", myHttpsPublicUri.toString()).setStatusCode(networkingirectCode).end() } catch (ex: Throwable) { if (failOnUrlBuilding) context.fail(ex) else context.next() } } } } 

Una versión más simple podría ser simplemente confiar en la class context.externalizeUrl y ver si tiene el protocolo y puerto correctos y networkingirigir si no es así:

 fun Route.simplifiedRedirectToHttpsHandler(publicHttpsPort: Int = 443, networkingirectCode: Int = 302, failOnUrlBuilding: Boolean = true) { handler { context -> try { val myPublicUri = URI(context.externalizeUrl()) if (myPublicUri.scheme == "http") { val myHttpsPublicUri = URI("https", myPublicUri.userInfo, myPublicUri.host, publicHttpsPort, myPublicUri.rawPath, myPublicUri.rawQuery, myPublicUri.rawFragment) context.response().putHeader("location", myHttpsPublicUri.toString()).setStatusCode(networkingirectCode).end() } else { context.next() } } catch (ex: Throwable) { if (failOnUrlBuilding) context.fail(ex) else context.next() } } } 
  • Cómo crear verticle de fábrica en VertX?
  • ¿Cómo comstackr y usar el código de Kotlin en time de ejecución?
  • Vert.x. ¿Cómo crear una aplicación de JVM políglota real?
  • Respuesta fragmentada de Vert.x con los datos de la database usando BLOB e hibernación
  • El complemento kapt no funciona con gradle-script-kotlin
  • Vert.x Kotlin Type Mismatch requinetworking Controlador <AsyncResult <Unit >> found (Handler <AsyncResult <Unit >>) -> Unidad
  • Vertx plus Koutlin coroutines cuelga para siempre