Compare commits

...

6 Commits

12 changed files with 274 additions and 204 deletions

View File

@ -6,7 +6,6 @@ var logger = require('morgan');
var iti65Router = require('./routes/iti65'); var iti65Router = require('./routes/iti65');
var iti67Router = require('./routes/iti67'); var iti67Router = require('./routes/iti67');
var iti68Router = require('./routes/iti68');
var iti78Router = require('./routes/iti78'); var iti78Router = require('./routes/iti78');
var iti104Router = require('./routes/iti104'); var iti104Router = require('./routes/iti104');
var vhlRouter = require('./routes/vhl'); var vhlRouter = require('./routes/vhl');
@ -16,16 +15,14 @@ var app = express();
app.use(logger('dev')); app.use(logger('dev'));
app.use(express.json({ type: ['application/json', 'application/fhir+json'] })); app.use(express.json({ type: ['application/json', 'application/fhir+json'] }));
// ITI-65: Provide Document Bundle → POST /fhir // ITI-65: Provide Document Bundle → POST /fhir/IPSTransaction (transaction Bundle)
// POST /fhir/IPSDocument (IPS document Bundle)
app.use('/fhir', iti65Router); app.use('/fhir', iti65Router);
// ITI-67: Find Document References → GET /fhir/DocumentReference // ITI-67: Find Document References → GET /fhir/DocumentReference
app.use('/fhir', iti67Router); app.use('/fhir', iti67Router);
// ITI-68: Retrieve Document → GET /fhir/Binary?url=[URL_Directa] // ITI-78: Patient Demographics → GET /fhir/Patient, GET /fhir/Patient/:id
app.use('/fhir', iti68Router);
// ITI-78: Patient Demographics → GET /fhir/Patient[/:id]
app.use('/fhir', iti78Router); app.use('/fhir', iti78Router);
// ITI-104: Patient Identity Feed → POST /fhir/Patient, PUT /fhir/Patient/:id // ITI-104: Patient Identity Feed → POST /fhir/Patient, PUT /fhir/Patient/:id
@ -58,6 +55,15 @@ app.use(function (req, res, next) {
// Error handler // Error handler
app.use(function (err, req, res, _next) { app.use(function (err, req, res, _next) {
// Error proveniente de HAPI FHIR o del Bus: reenviar la respuesta tal como llegó
if (err.response) {
const status = err.response.status;
console.warn(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl} -> ${status} (upstream)`);
const contentType = err.response.headers?.['content-type'];
if (contentType) res.setHeader('Content-Type', contentType);
return res.status(status).json(err.response.data);
}
const status = err.status || 500; const status = err.status || 500;
if (status >= 500) { if (status >= 500) {
console.error(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl} -> ${status}`, err); console.error(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl} -> ${status}`, err);

View File

@ -1,68 +1,51 @@
#!/usr/bin/env node #!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app'); var app = require('../app');
var debug = require('debug')('bus-gateway:server'); var debug = require('debug')('bus-gateway:server');
var http = require('http'); var http = require('http');
var axios = require('axios');
/** var config = require('../config');
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000'); var port = normalizePort(process.env.PORT || '3000');
app.set('port', port); app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app); var server = http.createServer(app);
/** const HAPI_HEALTH_URL = `${config.fhir.url}/metadata`;
* Listen on provided port, on all network interfaces. const RETRY_DELAY_MS = 5000;
*/ const MAX_ATTEMPTS = 36; // 3 minutos máximo
async function waitForHapi() {
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
try {
await axios.get(HAPI_HEALTH_URL, { timeout: 5000 });
console.log(`[${new Date().toISOString()}] HAPI FHIR está listo`);
return;
} catch {
console.log(`[${new Date().toISOString()}] Esperando HAPI FHIR (intento ${attempt}/${MAX_ATTEMPTS})...`);
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS));
}
}
console.error(`[${new Date().toISOString()}] HAPI FHIR no respondió en el tiempo máximo de espera`);
process.exit(1);
}
waitForHapi().then(() => {
server.listen(port); server.listen(port);
server.on('error', onError); server.on('error', onError);
server.on('listening', onListening); server.on('listening', onListening);
});
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) { function normalizePort(val) {
var port = parseInt(val, 10); var port = parseInt(val, 10);
if (isNaN(port)) return val;
if (isNaN(port)) { if (port >= 0) return port;
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false; return false;
} }
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) { function onError(error) {
if (error.syscall !== 'listen') { if (error.syscall !== 'listen') throw error;
throw error; var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) { switch (error.code) {
case 'EACCES': case 'EACCES':
console.error(bind + ' requires elevated privileges'); console.error(bind + ' requires elevated privileges');
@ -77,14 +60,9 @@ function onError(error) {
} }
} }
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() { function onListening() {
var addr = server.address(); var addr = server.address();
var bind = typeof addr === 'string' var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind); debug('Listening on ' + bind);
console.log(`[${new Date().toISOString()}] bus-gateway escuchando en ${bind}`);
} }

View File

@ -70,45 +70,120 @@ function generateDocumentReferenceResource(subjectReference, bundleUrl) {
async function getResourcesFromTransactionResponse(transactionResponse) { async function getResourcesFromTransactionResponse(transactionResponse) {
const promises = transactionResponse.entry.map(async (e) => { const promises = transactionResponse.entry.map(async (e) => {
const resource = getResourceByUrl(`${config.fhir.url}/${e.response.location}`); const resource = await getResourceByUrl(`${config.fhir.url}/${e.response.location}`);
return resource; return resource;
}); });
return Promise.all(promises); return Promise.all(promises);
} }
/** /**
* ITI-65: Provide Document Bundle (MHD) * Construye un Bundle de tipo transaction a partir de un Bundle de tipo document (IPS).
* * Genera Patient, Bundle (IPS), DocumentReference y List (SubmissionSet MHD).
* POST /fhir/Bundle * Usa urn:uuid: como fullUrl para que HAPI FHIR resuelva las referencias internas.
*
* Flow:
* 1. Store the IPS Bundle in HAPI FHIR.
* 2. Resolve the patient national identifier via Bus $match.
* 3. Register a DocumentReference in the Bus pointing to the stored Bundle.
*
* Required header:
* x-custodian-id Efector identifier value in the Federador MSAL system.
*/ */
async function provideDocumentBundle(req, res, next) { function buildTransactionFromIPSDocument(ipsBundle) {
try { if (ipsBundle.type !== 'document') {
const transaction = req.body; throw createError(400, 'Bundle must be of type document');
const token = await getBusToken( }
config.bus.url, const patientEntry = (ipsBundle.entry || []).find(
config.bus.jwtSecret, e => e.resource && e.resource.resourceType === 'Patient'
config.bus.issuer,
[config.bus.mpiScope, config.bus.documentRegistryScope].join(',')
); );
if (!patientEntry) {
throw createError(400, 'IPS Bundle must contain a Patient resource');
}
// Paso 1: Ejecuto la transcción en el servidor hapi subyacente const patientFullUrl = `urn:uuid:${uuidv4()}`;
const bundleFullUrl = `urn:uuid:${uuidv4()}`;
const documentReferenceFullUrl = `urn:uuid:${uuidv4()}`;
const now = new Date().toISOString();
const localDocumentReference = {
resourceType: 'DocumentReference',
status: 'current',
masterIdentifier: {
use: 'usual',
system: MASTER_ID_SYSTEM,
value: `urn:uuid:${uuidv4()}`
},
type: {
coding: [{
system: 'http://loinc.org',
code: '60591-5',
display: 'Patient Summary Document',
}]
},
date: now,
subject: { reference: patientFullUrl },
custodian: {
identifier: { system: CUSTODIAN_ID_SYSTEM, value: config.bus.issuer }
},
content: [{
attachment: {
url: bundleFullUrl,
contentType: 'application/fhir+json'
}
}]
};
const submissionSetList = {
resourceType: 'List',
status: 'current',
mode: 'working',
code: {
coding: [{
system: 'https://profiles.ihe.net/ITI/MHD/CodeSystem/MHDlistTypes',
code: 'submissionset'
}]
},
date: now,
subject: { reference: patientFullUrl },
source: {
identifier: { system: CUSTODIAN_ID_SYSTEM, value: config.bus.issuer }
},
entry: [
{ item: { reference: documentReferenceFullUrl } },
{ item: { reference: bundleFullUrl } }
]
};
return {
resourceType: 'Bundle',
type: 'transaction',
entry: [
{
fullUrl: patientFullUrl,
resource: patientEntry.resource,
request: { method: 'POST', url: 'Patient' }
},
{
fullUrl: bundleFullUrl,
resource: ipsBundle,
request: { method: 'POST', url: 'Bundle' }
},
{
fullUrl: documentReferenceFullUrl,
resource: localDocumentReference,
request: { method: 'POST', url: 'DocumentReference' }
},
{
resource: submissionSetList,
request: { method: 'POST', url: 'List' }
}
]
};
}
/**
* Lógica central de ITI-65: persiste la transacción en HAPI FHIR, resuelve el
* paciente en el Bus y registra un DocumentReference apuntando al Bundle guardado.
*/
async function executeITI65(transaction, token) {
const transactionResponse = await processDocumentBundleTransaction(transaction); const transactionResponse = await processDocumentBundleTransaction(transaction);
const resources = await getResourcesFromTransactionResponse(transactionResponse); const resources = await getResourcesFromTransactionResponse(transactionResponse);
// Paso 2: Obtengo el paciente local (tal como se guardo en la trasnaccion)
const localPatient = extractResource(resources, PATIENT_RESOURCE_TYPE); const localPatient = extractResource(resources, PATIENT_RESOURCE_TYPE);
// Paso 3: Obtengo el documento IPS local (tal como se guardo en la transacción) const localIPSDocument = extractResource(resources, IPS_DOCUMENT_RESOURCE_TYPE);
const localIPSDocument = extractResource(resources, IPS_DOCUMENT_RESOURCE_TYPE)
const localPatientIdentifier = extractLocalIdentifier(localPatient); const localPatientIdentifier = extractLocalIdentifier(localPatient);
const patientSearchset = await findPatient(token, { identifier: `${localPatientIdentifier.system}|${localPatientIdentifier.value}` }); const patientSearchset = await findPatient(token, { identifier: `${localPatientIdentifier.system}|${localPatientIdentifier.value}` });
@ -118,16 +193,59 @@ async function provideDocumentBundle(req, res, next) {
const nationalPatientId = patientSearchset.entry[0].fullUrl; const nationalPatientId = patientSearchset.entry[0].fullUrl;
const bundleReference = `${config.baseURL}/fhir/Bundle/${localIPSDocument.id}`; const bundleReference = `${config.baseURL}/fhir/Bundle/${localIPSDocument.id}`;
const documentReference = generateDocumentReferenceResource(nationalPatientId, bundleReference); const documentReference = generateDocumentReferenceResource(nationalPatientId, bundleReference);
return createDocumentReference(token, documentReference);
}
const createdDocumentReference = await createDocumentReference(token, documentReference); /**
* ITI-65: Provide Document Bundle (MHD) variante transacción
return res.status(200).json(createdDocumentReference); *
* POST /fhir/iti65
*
* Espera un Bundle de tipo transaction construido por el cliente.
*/
async function provideIPSTransaction(req, res, next) {
try {
const transaction = req.body;
const token = await getBusToken(
config.bus.url,
config.bus.jwtSecret,
config.bus.issuer,
[config.bus.mpiScope, config.bus.documentRegistryScope].join(',')
);
const result = await executeITI65(transaction, token);
return res.status(200).json(result);
} catch (err) { } catch (err) {
next(err); next(err);
} }
} }
module.exports = { provideDocumentBundle }; /**
* ITI-65: Provide Document Bundle (MHD) variante IPS document
*
* POST /fhir/Bundle
*
* Espera un Bundle de tipo document (IPS). Genera internamente el Bundle
* transaction y ejecuta el mismo flujo que provideDocumentBundle.
*/
async function provideIPSDocumentBundle(req, res, next) {
try {
const ipsBundle = req.body;
if (!ipsBundle || ipsBundle.resourceType !== 'Bundle') {
throw createError(400, 'Request body must be a FHIR Bundle resource');
}
const transaction = buildTransactionFromIPSDocument(ipsBundle);
const token = await getBusToken(
config.bus.url,
config.bus.jwtSecret,
config.bus.issuer,
[config.bus.mpiScope, config.bus.documentRegistryScope].join(',')
);
const result = await executeITI65(transaction, token);
return res.status(200).json(result);
} catch (err) {
next(err);
}
}
module.exports = { provideIPSTransaction, provideIPSDocumentBundle };

View File

@ -1,46 +0,0 @@
const createError = require('http-errors');
const axios = require('axios');
/**
* ITI-68: Retrieve Document (MHD)
*
* GET /fhir/Binary?url=[URL_Directa]
*
* Flow (diagram iti67.mmd, step 21-24):
* 1. HIS_A supplies the direct document URL obtained from a prior ITI-67 response.
* 2. This gateway performs a P2P GET to that URL, bypassing the Bus.
* 3. The raw document (PDF, XML, etc.) is forwarded back to HIS_A.
*/
async function getBundleById(req, res, next) {
try {
const url = req.query.url;
if (!url) {
throw createError(400, 'Missing required query parameter: url');
}
let parsedUrl;
try {
parsedUrl = new URL(url);
} catch {
throw createError(400, 'Invalid document URL');
}
const response = await getDocumentBundleByUrl(url);
const contentType = response.headers['content-type'];
if (contentType) res.setHeader('Content-Type', contentType);
const contentDisposition = response.headers['content-disposition'];
if (contentDisposition) res.setHeader('Content-Disposition', contentDisposition);
res.status(200).send(response.data);
} catch (err) {
if (err.response) {
return next(createError(err.response.status, `Document source returned ${err.response.status}`));
}
next(err);
}
}
module.exports = { getBundleById };

View File

@ -3,8 +3,7 @@ const router = express.Router();
const { createPatient, updatePatient } = require('../controllers/iti104'); const { createPatient, updatePatient } = require('../controllers/iti104');
// ITI-104: Patient Identity Feed FHIR // ITI-104: Patient Identity Feed FHIR
// TODO: Cambiar ruta por ITI104 router.post('/Patient', createPatient);
router.post('/iti104', createPatient); router.put('/Patient/:id', updatePatient);
router.put('/iti104/:id', updatePatient);
module.exports = router; module.exports = router;

View File

@ -1,9 +1,11 @@
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
const { provideDocumentBundle } = require('../controllers/iti65'); const { provideIPSTransaction, provideIPSDocumentBundle } = require('../controllers/iti65');
// ITI-65: Provide Document Bundle // ITI-65: Provide Document Bundle — variante transaction Bundle
// TODO: Cambiar la ruta de acceso para que no se confunda con el recurso Bundle cambiar por iti65 router.post('/IPSTransaction', provideIPSTransaction);
router.post('/iti65', provideDocumentBundle);
// ITI-65: Provide Document Bundle — variante IPS document Bundle (type: document)
router.post('/IPSDocument', provideIPSDocumentBundle);
module.exports = router; module.exports = router;

View File

@ -3,7 +3,6 @@ const router = express.Router();
const { listDocumentReference } = require('../controllers/iti67'); const { listDocumentReference } = require('../controllers/iti67');
// ITI-67: Find Document References // ITI-67: Find Document References
// TODO: Cambiar ruta por ITI67 router.get('/DocumentReference', listDocumentReference);
router.get('/iti67', listDocumentReference);
module.exports = router; module.exports = router;

View File

@ -1,8 +0,0 @@
const express = require('express');
const router = express.Router();
const { getBundleById } = require('../controllers/iti68');
// ITI-68: Retrieve Document → GET /fhir/Binary?url=[URL_Directa]
router.get('/Bundle', getBundleById);
module.exports = router;

View File

@ -3,8 +3,7 @@ const router = express.Router();
const { listPatient, getPatientById } = require('../controllers/iti78'); const { listPatient, getPatientById } = require('../controllers/iti78');
// ITI-78: Mobile Patient Demographics Query // ITI-78: Mobile Patient Demographics Query
// TOOD: Cambiar ruta por ITI78 router.get('/Patient', listPatient);
router.get('/iti78', listPatient); router.get('/Patient/:id', getPatientById);
router.get('/iti78/:id', getPatientById);
module.exports = router; module.exports = router;

View File

@ -1,5 +1,6 @@
services: services:
hapi-fhir: hapi-fhir:
container_name: hapi-fhir
image: "hapiproject/hapi:latest" image: "hapiproject/hapi:latest"
depends_on: depends_on:
- hapi-db - hapi-db
@ -15,8 +16,8 @@ services:
SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT: ${SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT} SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT: ${SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT}
networks: networks:
- hapi-network - hapi-network
hapi-db: hapi-db:
container_name: hapi-db
image: "postgres:14.6" image: "postgres:14.6"
restart: always restart: always
user: root user: root
@ -42,19 +43,19 @@ services:
ports: ports:
- 8182:8080 - 8182:8080
secrets: secrets:
- signature-cert - trust-network-cert
- trust-network-key
- signature-key - signature-key
- dsc-key
environment: environment:
- POSTGRES_DB=gdhcn-validator - POSTGRES_DB=gdhcn-validator
- SERVER_PORT=8080 - SERVER_PORT=8080
- SPRING_DATASOURCE_URL=jdbc:postgresql://gdhcn-db:5432/gdhcn-validator - SPRING_DATASOURCE_URL=jdbc:postgresql://gdhcn-db:5432/gdhcn-validator
- SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=root - SPRING_DATASOURCE_PASSWORD=root
- TNG_TLS_PEM=/run/secrets/signature-cert - TNG_TLS_PEM=/run/secrets/trust-network-cert
- TNG_TLS_KEY=/run/secrets/signature-key - TNG_TLS_KEY=/run/secrets/trust-network-key
- TNG_DSC_PRIVATEKEY=/run/secrets/dsc-key - TNG_DSC_PRIVATEKEY=/run/secrets/signature-key
- TNG_COUNTRY=XJ - TNG_COUNTRY=AR
- TNG_DSC_PRIVATEKEY_KID=I1BAX8FATLs= - TNG_DSC_PRIVATEKEY_KID=I1BAX8FATLs=
- GDHCN_BASEURL=${NODO_BASE_URL:-http://localhost}/gdhcn - GDHCN_BASEURL=${NODO_BASE_URL:-http://localhost}/gdhcn
networks: networks:
@ -63,6 +64,7 @@ services:
- ./json:/json - ./json:/json
gdhcn-db: gdhcn-db:
container_name: gdhcn-db
image: postgres:16-alpine image: postgres:16-alpine
restart: always restart: always
volumes: volumes:
@ -75,6 +77,7 @@ services:
- POSTGRES_PASSWORD=root - POSTGRES_PASSWORD=root
bus-gateway: bus-gateway:
container_name: bus-gateway
build: build:
context: ./bus-gateway context: ./bus-gateway
environment: environment:
@ -96,6 +99,7 @@ services:
command: node --inspect=0.0.0.0:9229 ./bin/www command: node --inspect=0.0.0.0:9229 ./bin/www
nginx: nginx:
container_name: nginx
image: nginx:alpine image: nginx:alpine
depends_on: depends_on:
- hapi-fhir - hapi-fhir
@ -130,9 +134,9 @@ secrets:
file: ${SSL_CERT_PATH:-./certs/server.crt} file: ${SSL_CERT_PATH:-./certs/server.crt}
ssl_key: ssl_key:
file: ${SSL_KEY_PATH:-./certs/server.key} file: ${SSL_KEY_PATH:-./certs/server.key}
signature-cert: trust-network-cert:
file: ${SIGNATURE_CERT_PATH:-./certs/signature.crt} file: ${SIGNATURE_CERT_PATH:-./certs/trust-network.pem}
trust-network-key:
file: ${SIGNATURE_KEY_PATH:-./certs/trust-network.key}
signature-key: signature-key:
file: ${SIGNATURE_KEY_PATH:-./certs/signature.key} file: ${SSL_DCC_KEY_PATH:-./certs/signature.key}
dsc-key:
file: ${SSL_DCC_KEY_PATH:-./certs/dcc.key}

View File

@ -14,7 +14,9 @@ http {
server_name _; server_name _;
# Rutas del bus-gateway (prefijo más específico gana sobre /fhir/) # Rutas del bus-gateway (prefijo más específico gana sobre /fhir/)
location /fhir/iti65 {
# ITI-65: Provide Document Bundle — transaction Bundle
location /fhir/IPSTransaction {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -23,7 +25,8 @@ http {
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /fhir/iti67 { # ITI-65: Provide Document Bundle — IPS document Bundle
location /fhir/IPSDocument {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -32,7 +35,8 @@ http {
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /fhir/iti78 { # ITI-67: Find Document References
location /fhir/DocumentReference {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -40,7 +44,10 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /fhir/iti104 {
# ITI-78: Mobile Patient Demographics Query
# ITI-104: Patient Identity Feed FHIR
location /fhir/Patient {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -48,6 +55,7 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /vhl/ { location /vhl/ {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
@ -56,6 +64,7 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
# Resto de /fhir/* va a hapi-fhir # Resto de /fhir/* va a hapi-fhir
location /fhir/ { location /fhir/ {
proxy_pass http://hapi_fhir; proxy_pass http://hapi_fhir;
@ -74,6 +83,7 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
# Todo lo demás va a hapi-fhir # Todo lo demás va a hapi-fhir
location / { location / {
proxy_pass http://hapi_fhir; proxy_pass http://hapi_fhir;

View File

@ -30,8 +30,9 @@ http {
ssl_session_timeout 10m; ssl_session_timeout 10m;
# Rutas del bus-gateway (prefijo más específico gana sobre /fhir/) # Rutas del bus-gateway (prefijo más específico gana sobre /fhir/)
# Rutas del bus-gateway (prefijo más específico gana sobre /fhir/)
location /fhir/iti65 { # ITI-65: Provide Document Bundle — transaction Bundle
location /fhir/IPSTransaction {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -40,7 +41,8 @@ http {
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /fhir/iti67 { # ITI-65: Provide Document Bundle — IPS document Bundle
location /fhir/IPSDocument {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -49,7 +51,8 @@ http {
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /fhir/iti78 { # ITI-67: Find Document References
location /fhir/DocumentReference {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -57,7 +60,10 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /fhir/iti104 {
# ITI-78: Mobile Patient Demographics Query
# ITI-104: Patient Identity Feed FHIR
location /fhir/Patient {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
@ -65,6 +71,7 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
location /vhl/ { location /vhl/ {
proxy_pass http://bus_gateway; proxy_pass http://bus_gateway;
proxy_set_header Host $host; proxy_set_header Host $host;
@ -73,6 +80,7 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
# Resto de /fhir/* va a hapi-fhir # Resto de /fhir/* va a hapi-fhir
location /fhir/ { location /fhir/ {
proxy_pass http://hapi_fhir; proxy_pass http://hapi_fhir;
@ -91,6 +99,7 @@ http {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; proxy_read_timeout 90s;
} }
# Todo lo demás va a hapi-fhir # Todo lo demás va a hapi-fhir
location / { location / {
proxy_pass http://hapi_fhir; proxy_pass http://hapi_fhir;