Beispiel #1
0
    def initialize(self,
                   routing: routing_reliability.RoutingAndReliability) -> None:
        """Initialise this request handler with the provided configuration values.

        :param routing: The routing and reliability component to use to look up values in SDS.
        """
        self.routing = routing
        read_tracking_id_headers(self.request.headers)
    def test_read_invalid_correlation_id(self):
        headers = HTTPHeaders()
        headers.add(CORRELATION_ID_HEADER, 'invalid_header_value')

        with self.assertRaises(tornado.web.HTTPError) as context:
            read_tracking_id_headers(headers)
        raised_exception = context.exception
        self.assertEqual(raised_exception.status_code, 400)
        self.assertEqual(
            raised_exception.log_message,
            "Invalid X-Correlation-ID header. Should be an UUIDv4 matching regex \'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$\'"
        )
    def test_read_valid_correlation_id(self):
        with self.subTest("Lower case UUID"):
            headers = HTTPHeaders()
            headers.add(CORRELATION_ID_HEADER, FIXED_UUID_LOWER_CASE)
            read_tracking_id_headers(headers)
            self.assertEqual(mdc.correlation_id.get(), FIXED_UUID_LOWER_CASE)

        mdc.correlation_id.set('')

        with self.subTest("Upper case UUID"):
            headers = HTTPHeaders()
            headers.add(CORRELATION_ID_HEADER, FIXED_UUID_UPPER_CASE)
            read_tracking_id_headers(headers)
            self.assertEqual(mdc.correlation_id.get(), FIXED_UUID_UPPER_CASE)
    async def get(self):
        read_tracking_id_headers(self.request.headers)

        self._validate_query_params()

        org_code = self.get_required_query_param(ORG_CODE_QUERY_PARAMETER_NAME,
                                                 ORG_CODE_FHIR_IDENTIFIER)
        service_id = self.get_required_query_param(
            IDENTIFIER_QUERY_PARAMETER_NAME, SERVICE_ID_FHIR_IDENTIFIER)

        managing_organization = self.get_optional_query_param(
            MANAGING_ORGANIZATION_QUERY_PARAMETER_NAME,
            MANAGING_ORGANIZATION_FHIR_IDENTIFIER)
        party_key = self.get_optional_query_param(
            IDENTIFIER_QUERY_PARAMETER_NAME, PARTY_KEY_FHIR_IDENTIFIER)

        accept_type = get_valid_accept_type(self.request.headers)

        logger.info(
            "Looking up accredited system information for {org_code}, {service_id}, {managing_organization}, {party_key}",
            fparams={
                "org_code": org_code,
                "service_id": service_id,
                'managing_organization': managing_organization,
                'party_key': party_key
            })
        ldap_result = await self.sds_client.get_as_details(
            org_code, service_id, managing_organization, party_key)
        logger.info("Obtained accredited system information. {ldap_result}",
                    fparams={"ldap_result": ldap_result})

        base_url = f"{self.request.protocol}://{self.request.host}{self.request.path}/"
        full_url = unquote(self.request.full_url())

        devices = [
            build_device_resource(ldap_attributes)
            for ldap_attributes in ldap_result
        ]

        bundle = build_bundle_resource(devices, base_url, full_url)

        self.write(json.dumps(bundle, indent=2, sort_keys=False))
        self.set_header(HttpHeaders.CONTENT_TYPE, accept_type)
        self.set_header(HttpHeaders.X_CORRELATION_ID, mdc.correlation_id.get())
    async def get(self):
        read_tracking_id_headers(self.request.headers)

        self._validate_query_params()

        org_code = self.get_required_query_param(ORG_CODE_QUERY_PARAMETER_NAME,
                                                 ORG_CODE_FHIR_IDENTIFIER)
        service_id = self.get_optional_query_param(
            IDENTIFIER_QUERY_PARAMETER_NAME, SERVICE_ID_FHIR_IDENTIFIER)
        party_key = self.get_optional_query_param(
            IDENTIFIER_QUERY_PARAMETER_NAME, PARTY_KEY_FHIR_IDENTIFIER)

        if not service_id and not party_key:
            self._raise_invalid_identifier_query_param_error()

        accept_type = get_valid_accept_type(self.request.headers)

        logger.info(
            "Looking up routing and reliability information. {org_code}, {service_id}, {party_key}",
            fparams={
                "org_code": org_code,
                "service_id": service_id,
                "party_key": party_key
            })
        ldap_result = await self.sds_client.get_mhs_details(
            org_code, service_id, party_key)
        logger.info(
            "Obtained routing and reliability information. {ldap_result}",
            fparams={"ldap_result": ldap_result})

        base_url = f"{self.request.protocol}://{self.request.host}{self.request.path}/"
        full_url = unquote(self.request.full_url())

        endpoints = []
        for ldap_attributes in ldap_result:
            endpoints += build_endpoint_resources(ldap_attributes)

        bundle = build_bundle_resource(endpoints, base_url, full_url)

        self.write(json.dumps(bundle, indent=2, sort_keys=False))
        self.set_header(HttpHeaders.CONTENT_TYPE, accept_type)
        self.set_header(HttpHeaders.X_CORRELATION_ID, mdc.correlation_id.get())
 def test_read_missing_correlation_id(self):
     read_tracking_id_headers(HTTPHeaders())
     self.assertRegex(mdc.correlation_id.get(), UUID_PATTERN)
    def write_error(self, status_code: int, **kwargs: Any) -> None:
        read_tracking_id_headers(self.request.headers, raise_error=False)

        operation_outcome = None
        additional_headers = []
        if status_code == 400:
            _, exception, _ = kwargs['exc_info']
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.required, [SpineCodings.BAD_REQUEST],
                      diagnostics=str(exception))
            ])
        elif status_code == 404:
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.not_found, [SpineCodings.NO_RECORD_FOUND],
                      diagnostics="HTTP endpoint not found")
            ])
        elif status_code == 405:
            additional_headers.append(("Allow", "GET"))
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.not_supported, [SpineCodings.NOT_IMPLEMENTED],
                      diagnostics="HTTP operation not supported")
            ])
        elif status_code == 406:
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.not_supported,
                      [SpineCodings.MISSING_OR_INVALID_HEADER],
                      diagnostics="Accept type not supported")
            ])
        elif status_code == 500:
            _, exception, _ = kwargs['exc_info']
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.exception, [SpineCodings.INTERNAL_SERVER_ERROR],
                      diagnostics=str(exception))
            ])
        elif status_code == 502:
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.exception, [SpineCodings.INTERNAL_SERVER_ERROR],
                      diagnostics="Invalid LDAP response received")
            ])
        elif status_code == 504:
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.timeout, [SpineCodings.INTERNAL_SERVER_ERROR],
                      diagnostics="LDAP request timed out")
            ])
        elif 400 <= status_code <= 499:
            _, exception, _ = kwargs['exc_info']
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.exception, [SpineCodings.BAD_REQUEST],
                      diagnostics=str(exception))
            ])
        elif 500 <= status_code < 599:
            _, exception, _ = kwargs['exc_info']
            operation_outcome = OperationOutcome([
                Issue(Severity.error,
                      Code.exception, [SpineCodings.INTERNAL_SERVER_ERROR],
                      diagnostics=str(exception))
            ])

        self.set_header(HttpHeaders.X_CORRELATION_ID, mdc.correlation_id.get())
        if operation_outcome is not None:
            operation_outcome.id = str(mdc.correlation_id.get())
            content_type = content_type_validator.APPLICATION_FHIR_JSON
            serialized = operation_outcome.to_json()
            self.set_header(HttpHeaders.CONTENT_TYPE, content_type)
            [self.set_header(kv[0], kv[1]) for kv in additional_headers]
            self.write(serialized)
        else:
            super().write_error(status_code, **kwargs)