Simple FHIR Proxy integrado con Cloud Healthcare API

Hader Ceron
google-cloud-hispanoamerica
7 min readFeb 27, 2024

El estándar FHIR (Fast Healthcare Interoperability Resources) está transformando el panorama de interoperabilidad en sistemas de salud. Sin embargo, la integración directa con servidores FHIR robustos en la nube, como Google Cloud Healthcare API, puede presentar desafíos en cuanto a seguridad, personalización y control granular.

El procesamiento de mensajes FHIR para incorporar mecanismos de seguridad, enrutamiento lógico, transformaciones o auditoría, generalmente está fuera del alcance de los servidores FHIR por sí mismos. Esto hace necesaria la implementación de un FHIR Proxy que añada estas capas de funcionalidad.

En cuanto a seguridad, soluciones como FHIR Info Gateway o Apigee pueden añadir una capa extra de autenticación y autorización basada en roles. Este tema, con sus diversas implementaciones, abarca un amplio espectro que no se abordará en este artículo.

Este artículo se enfoca en la capacidad de un FHIR Proxy de realizar transformaciones que un mensaje FHIR puede requerir antes o después de su envío y recepción. FHIR se basa en bloques de construcción (Paciente, Observación, etc.), que tienen una estructura clara con elementos de datos y metadatos adicionales. Además, pueden definir relaciones lógicas (por ejemplo, una Observación puede estar vinculada a un Paciente). FHIR también admite diversos formatos de intercambio, siendo XML y JSON los más comunes. La estructura bien definida de FHIR facilita la creación de librerías para diferentes lenguajes de programación que abstraen las complejidades del procesamiento de mensajes FHIR. HAPI FHIR es una librería de código abierto popular para Java.

A continuación se presenta un ejemplo práctico para realizar transformaciones en mensajes FHIR usando FHIR Proxy. El proxy se implementa como un componente independiente frente a un servidor FHIR, permitiendo:

  • Flexibilidad en las transformaciones: Adaptar los mensajes FHIR a las necesidades específicas de tu sistema.
  • Integración con Google Cloud Healthcare API: Usar un servidor FHIR robusto y escalable en la nube.
  • Despliegue en Cloud Run: Aprovechar la escalabilidad y rentabilidad de una plataforma serverless.

Simple FHIR Proxy

SimpleFhirProxy es un proxy ligero para transformaciones de recursos FHIR. Está implementado en Cloud Run utilizando Java y la librería HAPI FHIR, que permite interceptar y modificar recursos FHIR antes de ser persistidos en un repositorio FHIR de Cloud Healthcare API.

Arquitectura

La Figura 1 ilustra los componentes principales de SimpleFhirProxy:

Figura 1. Componentes de SimpleFhirProxy
  • Servicio Cloud Run: Punto de entrada principal de SimpleFhirProxy, el cual intercepta las peticiones al servidor FHIR y modifica los recursos antes de su persistencia. Para el caso de uso implementado en el ejemplo, recursos tipo Patient y Observation se interceptan y se les añade un identificador que simplemente permite visualizar cómo el mensaje entrante es modificado en el proxy. En un escenario real, el proxy podría añadir un identificador específico para futuras referencias, auditoría o reportes. De otro lado dependiendo de las necesidades de personalización de los mensajes, una vez el mensaje es recibido en el proxy podría efectuarse cualquier tipo de transformación requerida (adicionar campos, modificar, eliminar).
  • Cloud Healthcare API (Servidor FHIR): Servicio administrado por Google, que sirve como repositorio donde se persisten los recursos FHIR.

Pre-requisitos

Antes de ejecutar la aplicación, es necesario contar con los siguientes pre-requisitos:

  • Un proyecto en Google Cloud Platform.
  • Un dataset y FHIR Store creados en Cloud Healthcare API.
  • Google Cloud CLI instalado.
  • API de Cloud Run habilitada para el proyecto de GCP.
  • Una herramienta para hacer llamados HTTP POST como curl.

Ejecución

Para la ejecución de la aplicación sigue estos pasos:

Instalación:

  1. Clonar el repositorio https://github.com/haderceron/simple-fhir-proxy.git:
git clone https://github.com/haderceron/simple-fhir-proxy.git

2. Ir a la carpeta de simple-fhir-proxy:

cd simple-fhir-proxy

3. Instalar las dependencias:

mvn clean install

Despliegue: Desplegar la aplicación en Cloud Run. Esto se puede realizar desde la consola de Google Cloud, con gcloud CLI o desde una Workstation utilizando Cloud Code. A continuación los pasos usando gcloud CLI:

  1. Crear un servicio en Cloud Run:
gcloud run deploy simple-fhir-proxy \
--image gcr.io/PROJECT_ID/simple-fhir-proxy \
--platform managed \
--region REGION \
--allow-unauthenticated

Reemplazar:

  • PROJECT_ID : ID del proyecto Google Cloud
  • REGION : la región donde se desplegará el servicio en Cloud Run

2. Obtener la URL del servicio en Cloud Run

gcloud run services describe simple-fhir-proxy \
--platform managed \
--region REGION

3. Configurar en Cloud Run las siguientes variables de entorno:

  • PROJECT_ID : ID del proyecto Google Cloud
  • DATASET_LOCATION : region del dataset
  • DATASET_ID : id del dataset
  • FHIR_STORE_ID : id del fhir store

Pruebas: Ejecuta peticiones HTTP POST con un Payload FHIR del Paciente o la Observación. El FHIR Proxy los procesará y añadirá el identificador mencionado.

  1. Crear un archivo JSON llamado patient.json que contenga un Payload de ejemplo como este:
{
"resourceType": "Patient",
"id": "1234567890",
"meta": {
"lastUpdated": "2022-01-01T00:00:00+00:00"
},
"name": [
{
"use": "official",
"family": "Simpson",
"given": [
"Homer"
]
}
],
"gender": "male",
"birthDate": "1955-05-01"
}

2. Hacer una petición POST al servicio en Cloud Run. Para ello se puede utilizar una herramienta como curl desde una terminal:

curl -i -m 70 -X POST CLOUD_RUN_SERVICE_URL/fhir-proxy \
-H "Content-Type: application/json" \
-d @patient.json

Reemplazar

  • CLOUD_RUN_SERVICE_URL : URL del servicio en Cloud Run

3. La respuesta de la ejecución retorna el mensaje “Resource created”:

Figura 2. Respuesta curl en la terminal

4. En el Cloud Healthcare API se podrá comprobar el recurso creado con el identificador adicionado en el proxy:

Figura 3. Recurso en Cloud Healthcare API

Puedes revisar el código completo y la guía paso a paso para su ejecución en el repositorio git: https://github.com/haderceron/simple-fhir-proxy.git.

Un vistazo al código

La clase principal de SimpleFhirProxy es SimpleFhirProxy. Esta clase es invocada por el controlador, que es el punto de entrada en Cloud Run. Se encarga de configurar la librería HAPI FHIR y las librerías de cliente de Google Cloud. Incluye métodos para pre-procesar recursos FHIR, crear nuevas entidades FHIR y obtener el token de acceso para la autenticación y autorización.

El método preprocessFhirResource toma como entrada un recurso FHIR en formato JSON y devuelve la versión preprocesada del mismo. En particular para este ejemplo, el preprocesamiento se encarga de añadir el siguiente identificador:

Los valores utilizados para este identificador son valores de prueba, no relevantes para efectos del ejemplo presentado, pero que ilustran el proceso de transformación y modificación de un mensaje entrante. En la práctica el FHIR Proxy puede utilizarse para cualquier tipo de transformación requerida.

Esta lógica de pre-procesamiento puede incluir las transformaciones que sean requeridas. Para facilitar dicho preprocesamiento se hace uso de los modelos definidos en la librería de HAPI FHIR que permite manipular el recurso FHIR en su forma de objeto JAVA.

public Resource preprocessFhirResource(FhirContext ctx, String requestBody) {
// Parse the FHIR resource from the request body.
Resource resource = (Resource) ctx.newJsonParser().parseResource(requestBody);
// If the resource is a Patient, add an identifier to it.
if (resource instanceof Patient) {
Patient patient = (Patient) resource;
patient.addIdentifier().setSystem("http://simple-fhi-proxy").setValue("simple-fhi-proxy");
resource = patient;
} // If the resource is an Observation, add an identifier to it.
else if (resource instanceof Observation) {
Observation observation = (Observation) resource;
observation.addIdentifier().setSystem("http://simple-fhi-proxy").setValue("simple-fhi-proxy");
resource = observation;
} // If the resource is neither a Patient nor an Observation, log an error and
// return null.
else {
logger.error("Unknown resource type");
resource = null;
}
// Return the preprocessed FHIR resource.
return resource;
}

El método createFHIREntity recibe un recurso FHIR y crea una entidad dentro del repositorio FHIR. En este método se obtiene un token de autorización para realizar la petición al Cloud Healthcare API. Luego, se instancia un Generic Client que se utiliza en la ejecución del llamado al servidor FHIR. En este caso, la librería de HAPI FHIR facilita no solo la creación del cliente para las invocaciones, sino también la ejecución. Dicha ejecución se hace directamente pasando el recurso al cliente, el cuál se encarga de abstraer la lógica necesaria para construir apropiadamente el mensaje FHIR a enviar.

public boolean createFHIREntity(FhirContext ctx, Resource resourceToCreate) {
// Create the FHIR store URL.
String fhirStoreUrl = String.format("%s/fhir", FHIR_STORE_NAME);
// Create a BearerTokenAuthInterceptor object.
BearerTokenAuthInterceptor authInterceptor = null;
try {
authInterceptor = new BearerTokenAuthInterceptor(getAccessToken());
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
// Register the auth interceptor with the FHIR client.
IGenericClient HAPIFhirClient = ctx.newRestfulGenericClient(fhirStoreUrl);
HAPIFhirClient.registerInterceptor(authInterceptor);
// Use the client to store a new resource instance.
MethodOutcome outcome = HAPIFhirClient
.create()
.resource(resourceToCreate)
.execute();
// Return true if the resource was created successfully, false otherwise.
return outcome.getCreated();
}

El método getAccessToken se encarga de devolver un token de acceso para el proyecto de GCP actual. Este método utiliza las librerías de Google API Client para establecer autenticacion y autorizacion utilizando el mecanismo de Application Default Credentials.

private String getAccessToken() throws IOException {
GoogleCredentials credential = GoogleCredentials.getApplicationDefault() .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));
return credential.refreshAccessToken().getTokenValue();
}

Conclusión

Un FHIR Proxy es un componente fundamental en una arquitectura robusta para sistemas de salud. Este componente incorpora mecanismos de seguridad, enrutamiento, auditoría y transformación de mensajes FHIR, lo que lo convierte en una herramienta vital para la interoperabilidad y el intercambio de datos entre diferentes sistemas.

Este artículo se centra en la implementación práctica de un FHIR Proxy utilizando Google Cloud Healthcare API como repositorio de datos FHIR. Se presenta una opción viable para la transformación de mensajes FHIR, un aspecto crucial para la integración de datos y la personalización de la información.

SimpleFHIRProxy es fácil de implementar y ofrece una solución FHIR usable e intuitiva, accesible incluso para desarrolladores con poca experiencia en FHIR. El despliegue en Cloud Run es sencillo y consume poco tiempo. Esto facilita las pruebas, la reutilización del código y la personalización, lo que permite adaptarlo a diferentes escenarios que la comunidad FHIR puede encontrar en sus proyectos. Mediante esta implementación de ejemplo se ilustró cómo utilizando la librería HAPI FHIR, se puede:

  • Establecer una conexión con un repositorio FHIR: En este caso, Cloud Healthcare API.
  • Modificar recursos FHIR: Agregar atributos relevantes antes de que sean persistidos en el repositorio FHIR de Cloud Healthcare API.

Por último, es importante mencionar que este proxy es un ejemplo base. Potenciales mejoras incluyen:

  • Post-procesamiento de respuestas GET: Transformación de recursos FHIR recuperados.
  • Adaptación entre versiones FHIR: Conversión entre distintas versiones de FHIR para ampliar la interoperabilidad.

--

--