@Override
  public Response serve(final IHTTPSession session) {
    Map<String, String> headers = session.getHeaders();
    if (isWebsocketRequested(session)) {
      if (!NanoWebSocketServer.HEADER_WEBSOCKET_VERSION_VALUE.equalsIgnoreCase(
          headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_VERSION))) {
        return newFixedLengthResponse(
            Response.Status.BAD_REQUEST,
            NanoHTTPD.MIME_PLAINTEXT,
            "Invalid Websocket-Version "
                + headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_VERSION));
      }

      if (!headers.containsKey(NanoWebSocketServer.HEADER_WEBSOCKET_KEY)) {
        return newFixedLengthResponse(
            Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Missing Websocket-Key");
      }

      WebSocket webSocket = openWebSocket(session);
      Response handshakeResponse = webSocket.getHandshakeResponse();
      try {
        handshakeResponse.addHeader(
            NanoWebSocketServer.HEADER_WEBSOCKET_ACCEPT,
            makeAcceptKey(headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_KEY)));
      } catch (NoSuchAlgorithmException e) {
        return newFixedLengthResponse(
            Response.Status.INTERNAL_ERROR,
            NanoHTTPD.MIME_PLAINTEXT,
            "The SHA-1 Algorithm required for websockets is not available on the server.");
      }

      if (headers.containsKey(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL)) {
        handshakeResponse.addHeader(
            NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL,
            headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL).split(",")[0]);
      }

      return handshakeResponse;
    } else {
      return super.serve(session);
    }
  }