Compare commits

..

No commits in common. "5725f8a22f80ecde611f4e4e918a8f9082b2c75b" and "62ff8e8a281eddf5c988da10bde7c526d3cd830a" have entirely different histories.

5 changed files with 30 additions and 35 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/instance/
/logs/ /logs/
/.pydevproject /.pydevproject
/__pycache__/ /__pycache__/

16
app.py
View File

@ -1907,22 +1907,22 @@ def proxy_hapi(subpath):
return jsonify({'resourceType': 'OperationOutcome', 'issue': [{'severity': 'error', 'code': 'exception', 'diagnostics': 'An unexpected error occurred within the FHIR proxy.', 'details': {'text': str(e)}}]}), 500 return jsonify({'resourceType': 'OperationOutcome', 'issue': [{'severity': 'error', 'code': 'exception', 'diagnostics': 'An unexpected error occurred within the FHIR proxy.', 'details': {'text': str(e)}}]}), 500
@app.route('/api/stream-retrieve', methods=['GET']) @app.route('/api/stream-retrieve', methods=['POST'])
def stream_retrieve_bundles(): def stream_retrieve_bundles():
""" """
Handles streaming FHIR bundle retrieval. This endpoint directly calls the service function, Handles streaming FHIR bundle retrieval. This endpoint directly calls the service function,
bypassing the proxy to avoid conflicts. It receives the target URL, bypassing the proxy to avoid conflicts. It receives the target URL,
resources, and other parameters from the front-end via URL query parameters. resources, and other parameters from the front-end via a JSON body.
""" """
def generate_stream(): def generate_stream():
with app.app_context(): with app.app_context():
# Extract parameters from query string # Extract parameters from JSON body
fhir_server_url = request.args.get('fhir_server_url') data = request.json
resources = request.args.getlist('resources') fhir_server_url = data.get('fhir_server_url')
validate_references = request.args.get('validate_references', 'false').lower() == 'true' resources = data.get('resources')
fetch_reference_bundles = request.args.get('fetch_reference_bundles', 'false').lower() == 'true' validate_references = data.get('validate_references', False)
fetch_reference_bundles = data.get('fetch_reference_bundles', False)
# Extract authentication headers
auth_token = request.headers.get('Authorization') auth_token = request.headers.get('Authorization')
auth_type = 'bearer' if auth_token and auth_token.lower().startswith('bearer') else 'basic' if auth_token and auth_token.lower().startswith('basic') else 'none' auth_type = 'bearer' if auth_token and auth_token.lower().startswith('bearer') else 'basic' if auth_token and auth_token.lower().startswith('basic') else 'none'

Binary file not shown.

View File

@ -4584,8 +4584,7 @@ def retrieve_bundles(fhir_server_url, resources, output_zip, validate_references
yield json.dumps({"type": "info", "message": "Reference fetching OFF"}) + "\n" yield json.dumps({"type": "info", "message": "Reference fetching OFF"}) + "\n"
# Determine the final base URL for requests. # Determine the final base URL for requests.
from flask import current_app final_base_url = fhir_server_url.rstrip('/') if fhir_server_url and fhir_server_url != '/fhir' else app.config.get('HAPI_FHIR_URL', 'http://localhost:8080/fhir')
final_base_url = fhir_server_url.rstrip('/') if fhir_server_url and fhir_server_url != '/fhir' else current_app.config.get('HAPI_FHIR_URL', 'http://localhost:8080/fhir')
headers = {'Accept': 'application/fhir+json, application/fhir+xml;q=0.9, */*;q=0.8'} 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') is_custom_url = fhir_server_url != '/fhir' and fhir_server_url is not None and fhir_server_url.startswith('http')

View File

@ -27,7 +27,7 @@
</ul> </ul>
</div> </div>
{% endif %} {% endif %}
<form id="retrieveForm" method="POST"> <form id="retrieveForm" method="POST" enctype="multipart/form-data">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">FHIR Server</label> <label class="form-label fw-bold">FHIR Server</label>
@ -216,6 +216,7 @@ document.addEventListener('DOMContentLoaded', () => {
toggleServerButton.classList.remove('disabled'); toggleServerButton.classList.remove('disabled');
toggleServerButton.style.pointerEvents = 'auto'; toggleServerButton.style.pointerEvents = 'auto';
toggleServerButton.removeAttribute('aria-disabled'); toggleServerButton.removeAttribute('aria-disabled');
toggleServerButton.title = "Toggle between Local HAPI and Custom URL";
toggleLabel.textContent = useLocalHapi ? 'Using Local HAPI' : 'Using Custom URL'; toggleLabel.textContent = useLocalHapi ? 'Using Local HAPI' : 'Using Custom URL';
fhirServerUrlInput.style.display = useLocalHapi ? 'none' : 'block'; fhirServerUrlInput.style.display = useLocalHapi ? 'none' : 'block';
fhirServerUrlInput.placeholder = "e.g., https://hapi.fhir.org/baseR4"; fhirServerUrlInput.placeholder = "e.g., https://hapi.fhir.org/baseR4";
@ -299,9 +300,10 @@ document.addEventListener('DOMContentLoaded', () => {
fetchMetadataButton.textContent = 'Fetching...'; fetchMetadataButton.textContent = 'Fetching...';
try { try {
const fetchUrl = useLocalHapi ? '/fhir/metadata' : `${customUrl}/metadata`; const fetchUrl = '/fhir/metadata';
const headers = { 'Accept': 'application/fhir+json' }; const headers = { 'Accept': 'application/fhir+json' };
if (!useLocalHapi && customUrl) { if (!useLocalHapi && customUrl) {
headers['X-Target-FHIR-Server'] = customUrl;
if (authTypeSelect && authTypeSelect.value !== 'none') { if (authTypeSelect && authTypeSelect.value !== 'none') {
const authType = authTypeSelect.value; const authType = authTypeSelect.value;
if (authType === 'bearer' && bearerTokenInput && bearerTokenInput.value) { if (authType === 'bearer' && bearerTokenInput && bearerTokenInput.value) {
@ -311,12 +313,12 @@ document.addEventListener('DOMContentLoaded', () => {
headers['Authorization'] = `Basic ${credentials}`; headers['Authorization'] = `Basic ${credentials}`;
} }
} }
console.log(`Fetching metadata directly from: ${customUrl}`); console.log(`Fetching metadata via proxy with X-Target-FHIR-Server: ${customUrl}`);
} else { } else {
console.log("Fetching metadata from local HAPI server via proxy"); console.log("Fetching metadata via proxy for local HAPI server");
} }
console.log(`Fetch URL: ${fetchUrl}`); console.log(`Proxy Fetch URL: ${fetchUrl}`);
console.log(`Request Headers sent: ${JSON.stringify(headers)}`); console.log(`Request Headers sent TO PROXY: ${JSON.stringify(headers)}`);
const response = await fetch(fetchUrl, { method: 'GET', headers: headers }); const response = await fetch(fetchUrl, { method: 'GET', headers: headers });
@ -381,30 +383,11 @@ document.addEventListener('DOMContentLoaded', () => {
return; return;
} }
const currentFhirServerUrl = useLocalHapi ? null : fhirServerUrlInput.value.trim();
if (!useLocalHapi && !currentFhirServerUrl) {
alert('Custom FHIR Server URL is required.');
fhirServerUrlInput.classList.add('is-invalid');
retrieveButton.disabled = false;
if (spinner) spinner.style.display = 'none';
if (icon) icon.style.display = 'inline-block';
return;
}
const formData = new FormData(); const formData = new FormData();
const csrfTokenInput = retrieveForm.querySelector('input[name="csrf_token"]'); const csrfTokenInput = retrieveForm.querySelector('input[name="csrf_token"]');
if (csrfTokenInput) formData.append('csrf_token', csrfTokenInput.value); if (csrfTokenInput) formData.append('csrf_token', csrfTokenInput.value);
selectedResources.forEach(res => formData.append('resources', res)); selectedResources.forEach(res => formData.append('resources', res));
// --- FIX APPLIED HERE ---
if (!useLocalHapi && currentFhirServerUrl) {
formData.append('fhir_server_url', currentFhirServerUrl);
} else {
// Explicitly use the proxy URL if local HAPI is selected
formData.append('fhir_server_url', '/fhir');
}
// --- END FIX ---
if (validateReferencesCheckbox) { if (validateReferencesCheckbox) {
formData.append('validate_references', validateReferencesCheckbox.checked ? 'true' : 'false'); formData.append('validate_references', validateReferencesCheckbox.checked ? 'true' : 'false');
} }
@ -418,6 +401,18 @@ document.addEventListener('DOMContentLoaded', () => {
formData.append('fetch_reference_bundles', 'false'); formData.append('fetch_reference_bundles', 'false');
} }
const currentFhirServerUrl = useLocalHapi ? '/fhir' : fhirServerUrlInput.value.trim();
if (!useLocalHapi && !currentFhirServerUrl) {
alert('Custom FHIR Server URL is required.');
fhirServerUrlInput.classList.add('is-invalid');
retrieveButton.disabled = false;
if (spinner) spinner.style.display = 'none';
if (icon) icon.style.display = 'inline-block';
return;
}
formData.append('fhir_server_url', currentFhirServerUrl);
// Add authentication fields for custom URL
if (!useLocalHapi && authTypeSelect) { if (!useLocalHapi && authTypeSelect) {
const authType = authTypeSelect.value; const authType = authTypeSelect.value;
formData.append('auth_type', authType); formData.append('auth_type', authType);