mirror of
https://github.com/Sudo-JHare/FHIRFLARE-IG-Toolkit.git
synced 2025-11-05 13:35:15 +00:00
Compare commits
3 Commits
189ba1d18c
...
5f4e1b7207
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f4e1b7207 | |||
| 9729004982 | |||
| 5a6f2072d7 |
66
app.py
66
app.py
@ -5,6 +5,7 @@ CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
# Introduce app_dir variable that can be overridden by environment
|
||||
app_dir = os.environ.get('APP_DIR', CURRENT_DIR)
|
||||
sys.path.append(CURRENT_DIR)
|
||||
#sys.path.append(os.path.abspath(os.path.dirname(__file__)))
|
||||
import datetime
|
||||
import shutil
|
||||
import queue
|
||||
@ -1790,25 +1791,39 @@ def proxy_hapi(subpath):
|
||||
logger.debug(f"Proxy received request for path: '/fhir/{subpath}', cleaned subpath: '{clean_subpath}'")
|
||||
|
||||
# Determine the target FHIR server base URL
|
||||
# NEW: Check for proxy-target query parameter first
|
||||
target_server_query = request.args.get('proxy-target')
|
||||
target_server_header = request.headers.get('X-Target-FHIR-Server')
|
||||
final_base_url = None
|
||||
is_custom_target = False
|
||||
|
||||
if target_server_header:
|
||||
if target_server_query:
|
||||
try:
|
||||
parsed_url = urlparse(target_server_header)
|
||||
if not parsed_url.scheme or not parsed_url.netloc:
|
||||
raise ValueError("Invalid URL format in X-Target-FHIR-Server header")
|
||||
final_base_url = target_server_header.rstrip('/')
|
||||
is_custom_target = True
|
||||
logger.info(f"Proxy target identified from header: {final_base_url}")
|
||||
parsed_url = urlparse(target_server_query)
|
||||
if not parsed_url.scheme or not parsed_url.netloc:
|
||||
raise ValueError("Invalid URL format in proxy-target query parameter")
|
||||
final_base_url = target_server_query.rstrip('/')
|
||||
is_custom_target = True
|
||||
logger.info(f"Proxy target identified from query parameter: {final_base_url}")
|
||||
except ValueError as e:
|
||||
logger.warning(f"Invalid URL in X-Target-FHIR-Server header: '{target_server_header}'. Falling back. Error: {e}")
|
||||
final_base_url = current_app.config['HAPI_FHIR_URL'].rstrip('/')
|
||||
logger.debug(f"Falling back to default local HAPI due to invalid header: {final_base_url}")
|
||||
logger.warning(f"Invalid URL in proxy-target query parameter: '{target_server_query}'. Falling back. Error: {e}")
|
||||
final_base_url = current_app.config['HAPI_FHIR_URL'].rstrip('/')
|
||||
logger.debug(f"Falling back to default local HAPI due to invalid query: {final_base_url}")
|
||||
elif target_server_header:
|
||||
try:
|
||||
parsed_url = urlparse(target_server_header)
|
||||
if not parsed_url.scheme or not parsed_url.netloc:
|
||||
raise ValueError("Invalid URL format in X-Target-FHIR-Server header")
|
||||
final_base_url = target_server_header.rstrip('/')
|
||||
is_custom_target = True
|
||||
logger.info(f"Proxy target identified from header: {final_base_url}")
|
||||
except ValueError as e:
|
||||
logger.warning(f"Invalid URL in X-Target-FHIR-Server header: '{target_server_header}'. Falling back. Error: {e}")
|
||||
final_base_url = current_app.config['HAPI_FHIR_URL'].rstrip('/')
|
||||
logger.debug(f"Falling back to default local HAPI due to invalid header: {final_base_url}")
|
||||
else:
|
||||
final_base_url = current_app.config['HAPI_FHIR_URL'].rstrip('/')
|
||||
logger.debug(f"No target header found, proxying to default local HAPI: {final_base_url}")
|
||||
logger.debug(f"No target info found, proxying to default local HAPI: {final_base_url}")
|
||||
|
||||
# Construct the final URL for the target server request
|
||||
# Append the cleaned subpath only if it's not empty
|
||||
@ -1890,7 +1905,6 @@ def proxy_hapi(subpath):
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected proxy error for {final_url}: {str(e)}", exc_info=True)
|
||||
return jsonify({'resourceType': 'OperationOutcome', 'issue': [{'severity': 'error', 'code': 'exception', 'diagnostics': 'An unexpected error occurred within the FHIR proxy.', 'details': {'text': str(e)}}]}), 500
|
||||
|
||||
# --- End of corrected proxy_hapi function ---
|
||||
|
||||
|
||||
@ -2402,19 +2416,21 @@ def api_retrieve_bundles():
|
||||
output_zip = os.path.join(temp_dir, zip_filename)
|
||||
|
||||
def generate():
|
||||
try:
|
||||
yield from services.retrieve_bundles(
|
||||
fhir_server_url=fhir_server_url,
|
||||
resources=resources,
|
||||
output_zip=output_zip,
|
||||
validate_references=validate_references,
|
||||
fetch_reference_bundles=fetch_reference_bundles,
|
||||
auth_type=auth_type,
|
||||
auth_token=auth_token
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in retrieve_bundles: {e}", exc_info=True)
|
||||
yield json.dumps({"type": "error", "message": f"Unexpected error: {str(e)}"}) + "\n"
|
||||
# Push the application context manually for the generator's lifetime
|
||||
with app.app_context():
|
||||
try:
|
||||
yield from services.retrieve_bundles(
|
||||
fhir_server_url=fhir_server_url,
|
||||
resources=resources,
|
||||
output_zip=output_zip,
|
||||
validate_references=validate_references,
|
||||
fetch_reference_bundles=fetch_reference_bundles,
|
||||
auth_type=auth_type,
|
||||
auth_token=auth_token
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in retrieve_bundles: {e}", exc_info=True)
|
||||
yield json.dumps({"type": "error", "message": f"Unexpected error: {str(e)}"}) + "\n"
|
||||
|
||||
response = Response(generate(), mimetype='application/x-ndjson')
|
||||
response.headers['X-Zip-Path'] = os.path.join('/tmp', zip_filename)
|
||||
|
||||
13
services.py
13
services.py
@ -11,7 +11,7 @@ from flask import current_app, Blueprint, request, jsonify
|
||||
from fhirpathpy import evaluate
|
||||
from collections import defaultdict, deque
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote, urlparse
|
||||
from urllib.parse import quote, urlparse, urljoin
|
||||
from types import SimpleNamespace
|
||||
import datetime
|
||||
import subprocess
|
||||
@ -4586,16 +4586,20 @@ def retrieve_bundles(fhir_server_url, resources, output_zip, validate_references
|
||||
# Determine Base URL and Headers for Proxy
|
||||
base_proxy_url = f"{current_app.config['APP_BASE_URL'].rstrip('/')}/fhir"
|
||||
headers = {'Accept': 'application/fhir+json, application/fhir+xml;q=0.9, */*;q=0.8'}
|
||||
|
||||
is_custom_url = fhir_server_url != '/fhir' and fhir_server_url is not None and fhir_server_url.startswith('http')
|
||||
if is_custom_url:
|
||||
headers['X-Target-FHIR-Server'] = fhir_server_url.rstrip('/')
|
||||
# NEW: Add the custom URL as a query parameter for the proxy to use.
|
||||
# This bypasses issues where reverse proxies might strip custom headers.
|
||||
base_proxy_url = f"{base_proxy_url}?proxy-target={fhir_server_url.rstrip('/')}"
|
||||
|
||||
if auth_type in ['bearer', 'basic'] and auth_token:
|
||||
auth_display = 'Basic <redacted>' if auth_type == 'basic' else (auth_token[:10] + '...' if len(auth_token) > 10 else auth_token)
|
||||
yield json.dumps({"type": "info", "message": f"Using {auth_type} auth with header: Authorization: {auth_display}"}) + "\n"
|
||||
headers['Authorization'] = auth_token
|
||||
else:
|
||||
yield json.dumps({"type": "info", "message": "Using no authentication for custom URL"}) + "\n"
|
||||
logger.debug(f"Will use proxy with X-Target-FHIR-Server: {headers['X-Target-FHIR-Server']}")
|
||||
logger.debug(f"Will use proxy with proxy-target: {fhir_server_url}")
|
||||
else:
|
||||
yield json.dumps({"type": "info", "message": "Using no authentication for local HAPI server"}) + "\n"
|
||||
logger.debug("Will use proxy targeting local HAPI server")
|
||||
@ -4603,7 +4607,8 @@ def retrieve_bundles(fhir_server_url, resources, output_zip, validate_references
|
||||
# Fetch Initial Bundles
|
||||
initial_bundle_files = []
|
||||
for resource_type in resources:
|
||||
url = f"{base_proxy_url}/{quote(resource_type)}"
|
||||
#url = f"{base_proxy_url}/{quote(resource_type)}"
|
||||
url = urljoin(base_proxy_url, quote(resource_type))
|
||||
yield json.dumps({"type": "progress", "message": f"Fetching bundle for {resource_type} via proxy..."}) + "\n"
|
||||
logger.debug(f"Sending GET request to proxy {url} with headers: {json.dumps(headers)}")
|
||||
try:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user