def handleDataRequest(cmd): savedError = None incomplete = True while incomplete: response = Web.sendDataMsgFromThread(cmd, timeout=60) if response.get('status') != 200: raise RequestError('handleDataRequest: status not 200: {}'.format(response.get('status'))) try: data = unpackDataMessage(response) except Exception as err: logging.error('handleDataRequest: unpackDataMessage: {}'.format(err)) if savedError is None: savedError = err cmd['callId'] = response.get('callId', -1) incomplete = response.get('incomplete', False) if savedError: raise RequestError('handleDataRequest: unpackDataMessage: {}'.format(savedError)) return data
def handleRPCRequest(self, channelName, cmd, timeout=60): """Process RPC requests using websocket RequestHandler to send the request""" """Caller will catch exceptions""" handler = self.handlers[channelName] if handler is None: raise StateError(f'RPC Handler {channelName} not registered') savedError = None incomplete = True # print(f'handle request {cmd}') if cmd.get('cmd') == 'rpc': # if cmd is rpc, check and encode any byte args as base64 cmd = encodeByteTypeArgs(cmd) # Convert numpy arguments to native python types cmd['args'] = npToPy(cmd.get('args', ())) cmd['kwargs'] = npToPy(cmd.get('kwargs', {})) while incomplete: response = handler.doRequest(cmd, timeout) if response.get('status') != 200: errStr = 'handleDataRequest: status {}, err {}'.format( response.get('status'), response.get('error')) self.setError(errStr) raise RequestError(errStr) try: data = unpackDataMessage(response) except Exception as err: errStr = 'handleDataRequest: unpackDataMessage: {}'.format(err) logging.error(errStr) if savedError is None: savedError = errStr incomplete = response.get('incomplete', False) cmd['callId'] = response.get('callId', -1) cmd['incomplete'] = incomplete if savedError: self.setError(savedError) raise RequestError(savedError) serializationType = response.get('dataSerialization') if serializationType == 'json': if type(data) is bytes: data = data.decode() data = json.loads(data) elif serializationType == 'pickle': data = pickle.loads(data) return data
def on_message(client, message): fileWatcher = WsFileWatcher.fileWatcher response = {'status': 400, 'error': 'unhandled request'} try: request = json.loads(message) response = request.copy() if 'data' in response: del response['data'] cmd = request.get('cmd') dir = request.get('dir') filename = request.get('filename') timeout = request.get('timeout', 0) compress = request.get('compress', False) logging.log(logging.INFO, "{}: {} {}".format(cmd, dir, filename)) # Do Validation Checks if cmd not in ['getAllowedFileTypes', 'ping', 'error']: # All other commands must have a filename or directory parameter if dir is None and filename is not None: dir, filename = os.path.split(filename) if filename is None: errStr = "{}: Missing filename param".format(cmd) return send_error_response(client, response, errStr) if dir is None: errStr = "{}: Missing dir param".format(cmd) return send_error_response(client, response, errStr) if cmd in ('watchFile', 'getFile', 'getNewestFile'): if not os.path.isabs(dir): # make path relative to the watch dir dir = os.path.join(fileWatcher.watchDir, dir) if WsFileWatcher.validateRequestedFile(dir, filename, cmd) is False: errStr = '{}: {}'.format(cmd, WsFileWatcher.validationError) return send_error_response(client, response, errStr) if cmd in ('putTextFile', 'putBinaryFile', 'dataLog'): if not os.path.exists(dir): os.makedirs(dir) if not os.path.exists(dir): errStr = '{}: No such directory: {}'.format(cmd, dir) return send_error_response(client, response, errStr) # Now handle requests if cmd == 'initWatch': minFileSize = request.get('minFileSize') demoStep = request.get('demoStep') if minFileSize is None: errStr = "InitWatch: Missing minFileSize param" return send_error_response(client, response, errStr) WsFileWatcher.fileWatchLock.acquire() try: fileWatcher.initFileNotifier(dir, filename, minFileSize, demoStep) finally: WsFileWatcher.fileWatchLock.release() response.update({'status': 200}) return send_response(client, response) elif cmd == 'watchFile': WsFileWatcher.fileWatchLock.acquire() filename = os.path.join(dir, filename) try: retVal = fileWatcher.waitForFile(filename, timeout=timeout) finally: WsFileWatcher.fileWatchLock.release() if retVal is None: errStr = "WatchFile: 408 Timeout {}s: {}".format( timeout, filename) response.update({'status': 408, 'error': errStr}) logging.log(logging.WARNING, errStr) return send_response(client, response) else: response.update({'status': 200, 'filename': filename}) return send_data_response(client, response, compress) elif cmd == 'getFile': filename = os.path.join(dir, filename) if not os.path.exists(filename): errStr = "GetFile: File not found {}".format(filename) return send_error_response(client, response, errStr) response.update({'status': 200, 'filename': filename}) return send_data_response(client, response, compress) elif cmd == 'getNewestFile': resultFilename = findNewestFile(dir, filename) if resultFilename is None or not os.path.exists( resultFilename): errStr = 'GetNewestFile: file not found: {}'.format( os.path.join(dir, filename)) return send_error_response(client, response, errStr) response.update({'status': 200, 'filename': resultFilename}) return send_data_response(client, response, compress) elif cmd == 'listFiles': if not os.path.isabs(dir): errStr = "listFiles must have an absolute path: {}".format( dir) return send_error_response(client, response, errStr) filePattern = os.path.join(dir, filename) fileList = [x for x in glob.iglob(filePattern, recursive=True)] fileList = WsFileWatcher.filterFileList(fileList) response.update({ 'status': 200, 'filePattern': filePattern, 'fileList': fileList }) return send_response(client, response) elif cmd == 'getAllowedFileTypes': response.update({ 'status': 200, 'fileTypes': WsFileWatcher.allowedTypes }) return send_response(client, response) elif cmd == 'putTextFile': text = request.get('text') if text is None: errStr = 'PutTextFile: Missing text field' return send_error_response(client, response, errStr) elif type(text) is not str: errStr = "PutTextFile: Only text data allowed" return send_error_response(client, response, errStr) fullPath = os.path.join(dir, filename) with open(fullPath, 'w') as volFile: volFile.write(text) response.update({'status': 200}) return send_response(client, response) elif cmd == 'putBinaryFile': try: data = unpackDataMessage(request) except Exception as err: errStr = 'putBinaryFile: {}'.format(err) return send_error_response(client, response, errStr) # If data is None - Incomplete multipart data, more will follow if data is not None: fullPath = os.path.join(dir, filename) with open(fullPath, 'wb') as binFile: binFile.write(data) response.update({'status': 200}) return send_response(client, response) elif cmd == 'dataLog': logLine = request.get('logLine') if logLine is None: errStr = 'DataLog: Missing logLine field' return send_error_response(client, response, errStr) fullPath = os.path.join(dir, filename) with open(fullPath, 'a') as logFile: logFile.write(logLine + '\n') response.update({'status': 200}) return send_response(client, response) elif cmd == 'ping': response.update({'status': 200}) return send_response(client, response) elif cmd == 'error': errorCode = request.get('status', 400) errorMsg = request.get('error', 'missing error msg') if errorCode == 401: WsFileWatcher.needLogin = True WsFileWatcher.sessionCookie = None errStr = 'Error {}: {}'.format(errorCode, errorMsg) logging.log(logging.ERROR, errStr) return else: errStr = 'OnMessage: Unrecognized command {}'.format(cmd) return send_error_response(client, response, errStr) except Exception as err: errStr = "OnMessage Exception: {}: {}".format(cmd, err) send_error_response(client, response, errStr) if cmd == 'error': sys.exit() return errStr = 'unhandled request' send_error_response(client, response, errStr) return