@@ -403,3 +403,97 @@ def _send(self) -> None:
403403 self ._send_headers ()
404404 self ._close_connection ()
405405
406+
407+ class SSEResponse (Response ): # pylint: disable=too-few-public-methods
408+ """
409+ Specialized version of `Response` class for sending Server-Sent Events.
410+
411+ Allows one way communication with the client using a persistent connection.
412+
413+ Keep in mind, that in order to send events, the socket must be kept open. This means that you
414+ have to store the response object somewhere, so you can send events to it and close it later.
415+
416+ **It is very important to close the connection manually, it will not be done automatically.**
417+
418+ Example::
419+
420+ sse = None
421+
422+ @server.route(path, method)
423+ def route_func(request: Request):
424+
425+ # Store the response object somewhere in global scope
426+ global sse
427+ sse = SSEResponse(request)
428+
429+ return sse
430+
431+ ...
432+
433+ # Later, when you want to send an event
434+ sse.send_event("Simple message")
435+ sse.send_event("Message", event="event_name", id=1, retry=5000)
436+
437+ # Close the connection
438+ sse.close()
439+ """
440+
441+ def __init__ ( # pylint: disable=too-many-arguments
442+ self ,
443+ request : Request ,
444+ headers : Union [Headers , Dict [str , str ]] = None ,
445+ ) -> None :
446+ """
447+ :param Request request: Request object
448+ :param Headers headers: Headers to be sent with the response.
449+ """
450+ super ().__init__ (
451+ request = request ,
452+ headers = headers ,
453+ content_type = "text/event-stream" ,
454+ )
455+ self ._headers .setdefault ("Cache-Control" , "no-cache" )
456+ self ._headers .setdefault ("Connection" , "keep-alive" )
457+
458+ def _send (self ) -> None :
459+ self ._send_headers ()
460+
461+ def send_event ( # pylint: disable=too-many-arguments
462+ self ,
463+ data : str ,
464+ event : str = None ,
465+ id : int = None , # pylint: disable=redefined-builtin,invalid-name
466+ retry : int = None ,
467+ custom_fields : Dict [str , str ] = None ,
468+ ) -> None :
469+ """
470+ Send event to the client.
471+
472+ :param str data: The data to be sent.
473+ :param str event: (Optional) The name of the event.
474+ :param int id: (Optional) The event ID.
475+ :param int retry: (Optional) The time (in milliseconds) to wait before retrying the event.
476+ :param Dict[str, str] custom_fields: (Optional) Custom fields to be sent with the event.
477+ """
478+ message = f"data: { data } \n "
479+ if event :
480+ message += f"event: { event } \n "
481+ if id :
482+ message += f"id: { id } \n "
483+ if retry :
484+ message += f"retry: { retry } \n "
485+ if custom_fields :
486+ for field , value in custom_fields .items ():
487+ message += f"{ field } : { value } \n "
488+ message += "\n "
489+
490+ self ._send_bytes (self ._request .connection , message .encode ("utf-8" ))
491+
492+ def close (self ):
493+ """
494+ Close the connection.
495+
496+ **Always call this method when you are done sending events.**
497+ """
498+ self ._send_bytes (self ._request .connection , b"event: close\n " )
499+ self ._close_connection ()
0 commit comments