def decorated_method(self, path, request): if request.headers['Accept'] == self.response_type_plain: response = ApiAdapterResponse( self.response_data_plain, content_type=self.response_type_plain, status_code=self.response_code) else: response = ApiAdapterResponse( self.response_data_json, content_type=self.response_type_json, status_code=self.response_code) return response
def put(self, path, request): """ Handle an HTTP PUT request. This method handles an HTTP PUT request, returning a JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object with the appropriate response """ content_type = 'application/json' status_code = 200 response = {} checkAdapters = True if len(path) > 0 else False requestSent = False try: if checkAdapters: for name, adapter in self.adapters.items(): if path.startswith(name): relative_path = path.split(name + '/') reply = adapter.put(path=relative_path[1], request=request) requestSent = True if reply.status_code != 200: status_code = reply.status_code response = reply.data logging.debug(response) return ApiAdapterResponse( response, content_type=content_type, status_code=status_code) # Only pass request to Hexitec member if no matching adapter found if requestSent is False: data = convert_unicode_to_string(decode_request_body(request)) self.hexitec.set(path, data) response = self.hexitec.get(path) except HexitecError as e: response = {'error': str(e)} status_code = 400 except (TypeError, ValueError) as e: response = { 'error': 'Failed to decode PUT request body: {}'.format(str(e)) } status_code = 400 logging.debug(response) return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def decorated_method(self, path, request): """Decorated method having defined request, response and default types.""" if request.headers['Accept'] == self.response_type_plain: response = ApiAdapterResponse( self.response_data_plain, content_type=self.response_type_plain, status_code=self.response_code) else: response = ApiAdapterResponse(self.response_data_json, content_type=self.response_type_json, status_code=self.response_code) return response
def put(self, path, request): """Handle an HTTP PUT request. This method is the implementation of the HTTP PUT handler for ExcaliburAdapter/ :param path: URI path of the PUT request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ try: data = json_decode(request.body) self.detector.set(path, data) response = self.detector.get(path) status_code = 200 except ExcaliburDetectorError as e: response = {'error': str(e)} status_code = 400 logging.error(e) except (TypeError, ValueError) as e: response = { 'error': 'Failed to decode PUT request body: {}'.format(str(e)) } logging.error(e) status_code = 400 return ApiAdapterResponse(response, status_code=status_code)
def get(self, path, request): """ Implementation of the HTTP GET verb for OdinDataAdapter :param path: URI path of the GET request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ status_code = 200 response = {} # First check if we are interested in the config items # # Store these parameters locally: # config/hdf/file/path # config/hdf/file/name # config/hdf/file/extension # # When this arrives write all params into a single IPC message # config/hdf/write if path in self._param: response['value'] = self._param[path] else: return super(FrameProcessorAdapter, self).get(path, request) return ApiAdapterResponse(response, status_code=status_code)
def put(self, path, request): """Handle an HTTP PUT request. This method handles an HTTP PUT request, returning a JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response """ content_type = 'application/json' try: data = json_decode(request.body) self.workshop.set(path, data) response = self.workshop.get(path) status_code = 200 except WorkshopError as e: response = {'error': str(e)} status_code = 400 except (TypeError, ValueError) as e: response = { 'error': 'Failed to decode PUT request body: {}'.format(str(e)) } status_code = 400 logging.debug(response) return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def put(self, path, request): """Handle an HTTP PUT request. This method handles an HTTP PUT request routed to the adapter. This decodes the JSON body of the request into a dict, and passes the result with the request path, to the underlying PSCUData instance set method, where it is parsed and the appropriate actions performed on the PSCU. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response from the PSCU. """ try: data = json_decode(request.body) self.backplane_data.set(path, data) response = self.backplane_data.get(path, False) status_code = 200 except MetadataParameterError as e: response = {'error': str(e)} status_code = 400 except (TypeError, ValueError) as e: response = { 'error': 'Failed to decode PUT request body: {}'.format(str(e)) } status_code = 400 return ApiAdapterResponse(response, status_code=status_code)
async def get(self, path, request): """Handle an HTTP GET request. This method handles an HTTP GET request, returning a JSON response. The parameter tree data at the specified path is returned in the response. The underlying tree has a mix of sync and async parameter accessors, and GET requests simulate the concurrent operation of async adapters by sleeping for specified periods where appropriate. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response """ try: response = await self.param_tree.get(path) status_code = 200 except ParameterTreeError as param_error: response = {'error': str(param_error)} status_code = 400 logging.debug("GET on path %s : %s", path, response) content_type = 'application/json' return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def put(self, path, request): """ Handle an HTTP PUT request. This method handles an HTTP PUT request, returning a JSON response. The request is passed to the adapter proxy to set data on the remote targets and resolved into responses from those targets. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response """ # Decode the request body from JSON, handling and returning any errors that occur. Otherwise # send the PUT request to the remote target try: body = decode_request_body(request) except (TypeError, ValueError) as type_val_err: response = { 'error': 'Failed to decode PUT request body: {}'.format( str(type_val_err)) } status_code = 415 else: self.proxy_set(path, body) (response, status_code) = self._resolve_response(path) return ApiAdapterResponse(response, status_code=status_code)
def get(self, path, request): """Handle an HTTP GET request. This method handles an HTTP GET request, returning a JSON response. To facilitate testing of the background task, if the URI path is set appropriately, the task counter is returned in the JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response """ if path == 'background_task_count': response = { 'response': { 'background_task_count': self.background_task_counter } } else: response = { 'response': 'DummyAdapter: GET on path {}'.format(path) } content_type = 'application/json' status_code = 200 logging.debug(response) return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def get(self, path, request): """Implementation of the HTTP GET verb for MetaListenerAdapter :param path: URI path of the GET request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ status_code = 200 response = {} logging.debug("GET path: %s", path) logging.debug("GET request: %s", request) if path == "config/acquisition_id": response["value"] = self.acquisitionID elif path == "status/acquisition_active": response["value"] = self.acquisition_active elif path == "config/acquisitions": acquisition_tree = self.traverse_parameters( self._clients[0].parameters, ["config", "acquisitions"]) if acquisition_tree is not None: response["value"] = ",".join(acquisition_tree.keys()) else: response["value"] = None elif path in self._readback_parameters: response["value"] = self._readback_parameters[path] elif path in self._config_parameters: response["value"] = self._config_parameters[path] else: return super(MetaListenerAdapter, self).get(path, request) return ApiAdapterResponse(response, status_code=status_code)
def wrapper(_self, *args, **kwargs): # Extract version as first argument version = args[0] subsystem = args[1] rem_args = args[2:] if version != str(required_version): _self.respond(ApiAdapterResponse( "API version {} is not supported".format(version), status_code=400)) return wrap_result(None) if not _self.route.has_adapter(subsystem): _self.respond(ApiAdapterResponse( "No API adapter registered for subsystem {}".format(subsystem), status_code=400)) return wrap_result(None) return func(_self, subsystem, *rem_args, **kwargs)
def get(self, path, request): """Handle an HTTP GET request. This method handles an HTTP GET request routed to the adapter. This passes the path of the request to the underlying BackplaneData instance, where it is interpreted and returned as a dictionary containing the appropriate parameter tree. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response from the backplane """ try: #Check for metadata argument metadata = False if "Accept" in request.headers: splitted = request.headers["Accept"].split(';') if len(splitted) > 1: splitted = splitted[1:] for arg in splitted: if '=' in arg: arg = arg.split('=') if arg[0] == "metadata": metadata = bool(arg[1]) #Get response response = self.backplane_data.get(path, metadata) status_code = 200 except Exception as e: #Return the error response = {'error': str(e)} status_code = 400 return ApiAdapterResponse(response, status_code=status_code)
def put(self, path, request): """ Handle an HTTP PUT request. This method handles an HTTP PUT request, returning a JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response """ # Update the target specified in the path, or all targets if none specified try: json_decode(request.body) # ensure request body is JSON. Will throw a TypeError if not if "/" in path: path_elem, target_path = path.split('/', 1) else: path_elem = path target_path = "" for target in self.targets: if path_elem == '' or path_elem == target.name: target.remote_set(target_path, request.body) response = self.param_tree.get(path) status_code = 200 except ParameterTreeError as param_tree_err: response = {'error': str(param_tree_err)} status_code = 400 except (TypeError, ValueError) as type_val_err: response = {'error': 'Failed to decode PUT request body: {}'.format(str(type_val_err))} status_code = 415 return ApiAdapterResponse(response, status_code=status_code)
def get(self, path, request): """ Handle an HTTP GET request. This method handles an HTTP GET request, returning a JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response """ # Update the target specified in the path, or all targets if none specified if "/" in path: path_elem, target_path = path.split('/', 1) else: path_elem = path target_path = "" for target in self.targets: if path_elem == '' or path_elem == target.name: target.remote_get(target_path) # Build the response from the adapter parameter tree try: response = self.param_tree.get(path) status_code = 200 except ParameterTreeError as param_tree_err: response = {'error': str(param_tree_err)} status_code = 400 return ApiAdapterResponse(response, status_code=status_code)
def test_simple_response(self): """Test that a simple rewponse contains the correct default values in fields.""" data = 'This is a simple response' response = ApiAdapterResponse(data) assert response.data == data assert response.content_type == 'text/plain' assert response.status_code == 200
def dummy_get(self, subsystem, path=''): """Dummy HTTP GET verb method to allow the request validation decorator to be tested.""" response = ApiAdapterResponse( {'subsystem': subsystem, 'path': path }, content_type='application/json', status_code=200 ) self.respond(response)
def test_simple_response(self): data = 'This is a simple response' response = ApiAdapterResponse(data) assert_equal(response.data, data) assert_equal(response.content_type, 'text/plain') assert_equal(response.status_code, 200)
def test_handler_respond_valid_json(self, test_base_handler): """Test that the base handler respond method handles a valid JSON ApiAdapterResponse.""" data = {'valid': 'json', 'value': 1.234} valid_response = ApiAdapterResponse(data, content_type="application/json") test_base_handler.handler.respond(valid_response) assert test_base_handler.handler.get_status() == 200 assert json.loads(test_base_handler.write_data) == data
def get(self, path, request): """ HTTP Get Request Handler. Return the requested data from the parameter tree """ response = self.param_tree.get(path) content_type = 'application/json' status = 200 return ApiAdapterResponse(response, content_type, status)
def put(self, path, request): # pylint: disable=W0613 """ Implementation of the HTTP PUT verb for OdinDataAdapter :param path: URI path of the PUT request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ status_code = 200 response = {} logging.debug("PUT path: %s", path) logging.debug("PUT request: %s", request) logging.debug("PUT request.body: %s", str(escape.url_unescape(request.body))) # Clear any errors self.clear_error() request_command = path.strip('/') try: # Request should start with config/ if request_command.startswith("config/"): request_command = remove_prefix( request_command, "config/") # Take the rest of the URI # Parse the parameters parameters = None try: parameters = json.loads( str(escape.url_unescape(request.body))) except ValueError: # If the body could not be parsed into an object it may be a simple string parameters = str(escape.url_unescape(request.body)) # Do not store this configuration if it is the config file if not request_command.startswith('config_file'): # Check if the parameter is a dict, and if so then merge. Otherwise replace the value if request_command in self._config_params: if isinstance(self._config_params[request_command], dict): self._config_params[request_command].update( parameters) else: self._config_params[request_command] = parameters else: self._config_params[request_command] = parameters logging.debug("Stored config items: %s", self._config_params) response, status_code = self.process_configuration( request_command, parameters) except Exception as ex: self.set_error(str(ex)) raise return ApiAdapterResponse(response, status_code=status_code)
def test_response_with_type_and_code(self): data = '{\'some_json_value\' : 1.234}' content_type = 'application/json' status_code = 400 response = ApiAdapterResponse(data, content_type=content_type, status_code=status_code) assert_equal(response.data, data) assert_equal(response.content_type, content_type) assert_equal(response.status_code, status_code)
def decorated_method_without_default(self, path, request): if request.headers['Accept'] == self.response_type_plain: response = ApiAdapterResponse( self.response_data_plain, content_type=self.response_type_plain, status_code=self.response_code) elif request.headers['Accept'] == '*/*': response = ApiAdapterResponse( self.response_data_plain, content_type=self.response_type_plain, status_code=self.response_code) elif request.headers['Accept'] == self.response_type_json: response = ApiAdapterResponse( self.response_data_json, content_type=self.response_type_json, status_code=self.response_code) else: # pragma: no cover response = None assert ("Request type decorator failed to trap unknown content type") return response
def test_handler_respond_invalid_json(self, test_base_handler): """ Test that the base handler respond method raises an ApiError when passed an invalid response. """ invalid_response = ApiAdapterResponse(1234, content_type="application/json") with pytest.raises(ApiError) as excinfo: test_base_handler.handler.respond(invalid_response) assert 'A response with content type application/json must have str or dict data' \ in str(excinfo.value)
def get(self, path, request): """ Handle an HTTP GET request. This method handles an HTTP GET request, returning a JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object with the appropriate response """ content_type = "application/json" status_code = 200 response = {} request = ApiAdapterRequest(None, accept="application/json") # Check adapters if path isn't empty # e.g. If asking for /api/0.1/hexitec/fr/status/frames, # path = "fr/status/frames" # Compare: /api/0.1/hexitec/, path = "" checkAdapters = True if len(path) > 0 else False try: if checkAdapters: for name, adapter in self.adapters.items(): if path.startswith(name): tokens = path.split("/") path = "/".join(tokens[1:]) response = adapter.get(path=path, request=request).data logging.debug(response) return ApiAdapterResponse(response, content_type=content_type, status_code=status_code) # No matching adapter found, try Hexitec member: response = self.hexitec.get(path) except ParameterTreeError as e: response = {'error': str(e)} status_code = 400 return ApiAdapterResponse(response, content_type=content_type, status_code=status_code)
def put(self, path, request): """ HTTP Put Request Handler. Return the requested data after changes were made. """ try: data = json_decode(request.body) self.param_tree.set(path, data) response = self.param_tree.get(path) status_code = 200 except ParameterTreeError as set_err: response = {'error': str(set_err)} status_code = 400 return ApiAdapterResponse(response, status_code=status_code)
def delete(self, path, request): # pylint: disable=W0613 """ Implementation of the HTTP DELETE verb for OdinDataAdapter :param path: URI path of the DELETE request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ response = {'response': '{}: DELETE on path {}'.format(self.name, path)} status_code = 501 logging.debug(response) return ApiAdapterResponse(response, status_code=status_code)
def delete(self, path, request): """Handle an HTTP DELETE request. This method handles an HTTP DELETE request, returning a JSON response. :param path: URI path of request :param request: HTTP request object :return: an ApiAdapterResponse object containing the appropriate response """ response = 'FileInterfaceAdapter: DELETE on path {}'.format(path) status_code = 200 logging.debug(response) return ApiAdapterResponse(response, status_code=status_code)
async def put(self, path, request): """Handle an HTTP PUT request. This method is an abstract implementation of the PUT request handler for AsyncApiAdapter. :param path: URI path of resource :param request: HTTP request object passed from handler :return: ApiAdapterResponse container of data, content-type and status_code """ logging.debug('PUT on path %s from %s: method not implemented by %s', path, request.remote_ip, self.name) await asyncio.sleep(0) response = "PUT method not implemented by {}".format(self.name) return ApiAdapterResponse(response, status_code=400)
def test_response_with_type_and_code(self): """ Test that a response with explicit content type and status codes correctly populates the fields. """ data = '{\'some_json_value\' : 1.234}' content_type = 'application/json' status_code = 400 response = ApiAdapterResponse(data, content_type=content_type, status_code=status_code) assert response.data == data assert response.content_type == content_type assert response.status_code == status_code