Server IP : 103.119.228.120 / Your IP : 3.15.31.27 Web Server : Apache System : Linux v8.techscape8.com 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64 User : nobody ( 99) PHP Version : 5.6.40 Disable Function : shell_exec,symlink,system,exec,proc_get_status,proc_nice,proc_terminate,define_syslog_variables,syslog,openlog,closelog,escapeshellcmd,passthru,ocinum cols,ini_alter,leak,listen,chgrp,apache_note,apache_setenv,debugger_on,debugger_off,ftp_exec,dl,dll,myshellexec,proc_open,socket_bind,proc_close,escapeshellarg,parse_ini_filepopen,fpassthru,exec,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,proc_nice,proc_terminate,proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,dl,symlink,shell_exec,system,dl,passthru,escapeshellarg,escapeshellcmd,myshellexec,c99_buff_prepare,c99_sess_put,fpassthru,getdisfunc,fx29exec,fx29exec2,is_windows,disp_freespace,fx29sh_getupdate,fx29_buff_prepare,fx29_sess_put,fx29shexit,fx29fsearch,fx29ftpbrutecheck,fx29sh_tools,fx29sh_about,milw0rm,imagez,sh_name,myshellexec,checkproxyhost,dosyayicek,c99_buff_prepare,c99_sess_put,c99getsource,c99sh_getupdate,c99fsearch,c99shexit,view_perms,posix_getpwuid,posix_getgrgid,posix_kill,parse_perms,parsesort,view_perms_color,set_encoder_input,ls_setcheckboxall,ls_reverse_all,rsg_read,rsg_glob,selfURL,dispsecinfo,unix2DosTime,addFile,system,get_users,view_size,DirFiles,DirFilesWide,DirPrintHTMLHeaders,GetFilesTotal,GetTitles,GetTimeTotal,GetMatchesCount,GetFileMatchesCount,GetResultFiles,fs_copy_dir,fs_copy_obj,fs_move_dir,fs_move_obj,fs_rmdir,SearchText,getmicrotime MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /lib/mysqlsh/lib/python3.9/site-packages/oci/_vendor/sseclient/ |
Upload File : |
""" Server Side Events (SSE) client for Python. Provides a generator of SSE received through an existing HTTP response. """ import logging __author__ = 'Maxime Petazzoni <maxime.petazzoni@bulix.org>' __email__ = 'maxime.petazzoni@bulix.org' __all__ = ['SSEClient'] _FIELD_SEPARATOR = ':' class SSEClient(object): """Implementation of a SSE client. See http://www.w3.org/TR/2009/WD-eventsource-20091029/ for the specification. """ def __init__(self, event_source, char_enc='utf-8'): """Initialize the SSE client over an existing, ready to consume event source. The event source is expected to be a binary stream and have a close() method. That would usually be something that implements io.BinaryIOBase, like an httplib or urllib3 HTTPResponse object. """ self._logger = logging.getLogger(self.__class__.__module__) self._logger.debug('Initialized SSE client from event source %s', event_source) self._event_source = event_source self._char_enc = char_enc def _read(self): """Read the incoming event source stream and yield event chunks. Unfortunately it is possible for some servers to decide to break an event into multiple HTTP chunks in the response. It is thus necessary to correctly stitch together consecutive response chunks and find the SSE delimiter (empty new line) to yield full, correct event chunks.""" data = b'' for chunk in self._event_source: for line in chunk.splitlines(True): data += line if data.endswith((b'\r\r', b'\n\n', b'\r\n\r\n')): yield data data = b'' if data: yield data def events(self): for chunk in self._read(): event = Event() # Split before decoding so splitlines() only uses \r and \n for line in chunk.splitlines(): # Decode the line. line = line.decode(self._char_enc) # Lines starting with a separator are comments and are to be # ignored. if not line.strip() or line.startswith(_FIELD_SEPARATOR): continue data = line.split(_FIELD_SEPARATOR, 1) field = data[0] # Ignore unknown fields. if field not in event.__dict__: self._logger.debug('Saw invalid field %s while parsing ' 'Server Side Event', field) continue if len(data) > 1: # From the spec: # "If value starts with a single U+0020 SPACE character, # remove it from value." if data[1].startswith(' '): value = data[1][1:] else: value = data[1] else: # If no value is present after the separator, # assume an empty value. value = '' # The data field may come over multiple lines and their values # are concatenated with each other. if field == 'data': event.__dict__[field] += value + '\n' else: event.__dict__[field] = value # Events with no data are not dispatched. if not event.data: continue # If the data field ends with a newline, remove it. if event.data.endswith('\n'): event.data = event.data[0:-1] # Empty event names default to 'message' event.event = event.event or 'message' # Dispatch the event self._logger.debug('Dispatching %s...', event) yield event def close(self): """Manually close the event source stream.""" self._event_source.close() class Event(object): """Representation of an event from the event stream.""" def __init__(self, id=None, event='message', data='', retry=None): self.id = id self.event = event self.data = data self.retry = retry def __str__(self): s = '{0} event'.format(self.event) if self.id: s += ' #{0}'.format(self.id) if self.data: s += ', {0} byte{1}'.format(len(self.data), 's' if len(self.data) else '') else: s += ', no data' if self.retry: s += ', retry in {0}ms'.format(self.retry) return s