Large Latency with streamed JSON when used with SSL/HTTPS

streams
(Marcus DeGruttola) #1

I’ve crossed posted this issue with the swagger-play issues group because it’s related to play but when we moved our website to use SSL port 433 directly off of play, out swagger ui page started showing huge latency and timeouts. I tracked the latency down to the generation of the swagger config.json from the swagger-play route helper routine…

GET           /api-docs.json                              controllers.ApiHelpController.getResources

Again this all works just fine when our play was listening on HTTP port 80 but showed huge latency when listening on HTTPS port 443.

Our workaround which eventually got us around the latency problem…

class MyApiHelpController @Inject() (components: ControllerComponents, configuration: play.api.Configuration)
  extends ApiHelpController(components, configuration) {

  def wrappedResources = Action {
    request =>
      implicit val requestHeader: RequestHeader = request
      val host: String = if (configuration.underlying.hasPath("swagger.api.host")) configuration.underlying.getString("swagger.api.host") else requestHeader.host
      val resourceListing: io.swagger.models.Swagger = getResourceListing(host)
      val response: String = returnXml(request) match {
        case true => toXmlString(resourceListing)
        case false => toJsonString(resourceListing)
      }
      myReturnValue(request, response)
  }

  private def myReturnValue(request: Request[_], obj: Any): Result = {
    val response = returnXml(request) match {
      case true => XmlResponse(obj)
      case false => Ok(obj.toString).as("application/json")
    }
    response.withHeaders(AccessControlAllowOrigin)
  }
}

The original swagger-play code had a call to …

  protected def JsonResponse(data: Any) = {
    val jsonBytes = toJsonString(data).getBytes("UTF-8")
    val source = Source.single(jsonBytes).map(ByteString.apply)
    Result (
      header = ResponseHeader(200, Map(HeaderNames.CONTENT_LENGTH -> jsonBytes.length.toString)),
      body = HttpEntity.Streamed(source, None, None)
    ).as ("application/json")
  }

… which basically means I changed swagger from parsing JSON on a paged basis to a blob basis. But there definitely something strange happening someplace is this can run fine and fast on 80/HTTP but pick up huge latency on 443/HTTPS.

Dependencies…

  "io.swagger" % "swagger-core" % "1.5.22",
  "io.swagger" %% "swagger-play2" % "1.6.1",
  "com.typesafe.play" % "sbt-plugin" % "2.6.20"