/**
   * Handle all requests, except the first one, to receive messages on a SockJS HTTP transport based
   * session.
   *
   * <p>Long polling-based transports (e.g. "xhr", "jsonp") complete the request after writing any
   * buffered message frames (or the next one). Streaming-based transports ("xhr_streaming",
   * "eventsource", and "htmlfile") leave the response open longer for further streaming of message
   * frames but will also close it eventually after some amount of data has been sent.
   *
   * @param request the current request
   * @param response the current response
   * @param frameFormat the transport-specific SocksJS frame format to use
   */
  public void handleSuccessiveRequest(
      ServerHttpRequest request, ServerHttpResponse response, SockJsFrameFormat frameFormat)
      throws SockJsException {

    synchronized (this.responseLock) {
      try {
        if (isClosed()) {
          response.getBody().write(SockJsFrame.closeFrameGoAway().getContentBytes());
        }
        this.response = response;
        this.frameFormat = frameFormat;
        this.asyncRequestControl = request.getAsyncRequestControl(response);
        writePrelude(request, response);
        startAsyncRequest();
      } catch (Throwable ex) {
        tryCloseWithSockJsTransportError(ex, CloseStatus.SERVER_ERROR);
        throw new SockJsTransportFailureException(
            "Failed to handle SockJS receive request", getId(), ex);
      }
    }
  }
  protected void handleRequestInternal(
      ServerHttpRequest request,
      ServerHttpResponse response,
      AbstractHttpSockJsSession sockJsSession)
      throws SockJsException {

    if (sockJsSession.isNew()) {
      if (logger.isDebugEnabled()) {
        logger.debug(request.getMethod() + " " + request.getURI());
      }
      sockJsSession.handleInitialRequest(request, response, getFrameFormat(request));
    } else if (sockJsSession.isClosed()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Connection already closed (but not removed yet) for " + sockJsSession);
      }
      SockJsFrame frame = SockJsFrame.closeFrameGoAway();
      try {
        response.getBody().write(frame.getContentBytes());
      } catch (IOException ex) {
        throw new SockJsException("Failed to send " + frame, sockJsSession.getId(), ex);
      }
    } else if (!sockJsSession.isActive()) {
      if (logger.isTraceEnabled()) {
        logger.trace("Starting " + getTransportType() + " async request.");
      }
      sockJsSession.handleSuccessiveRequest(request, response, getFrameFormat(request));
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Another " + getTransportType() + " connection still open for " + sockJsSession);
      }
      String formattedFrame =
          getFrameFormat(request).format(SockJsFrame.closeFrameAnotherConnectionOpen());
      try {
        response.getBody().write(formattedFrame.getBytes(SockJsFrame.CHARSET));
      } catch (IOException ex) {
        throw new SockJsException("Failed to send " + formattedFrame, sockJsSession.getId(), ex);
      }
    }
  }