Services
Services are the core building blocks of Harmony's data pipeline architecture. They define how data enters Harmony (via Endpoints) and how Harmony communicates with external systems (via Backends).
Endpoints
Endpoints define protocol entry points into the Harmony pipeline. Each endpoint is associated with a service that handles protocol-specific data conversion to/from the internal Envelope format.
Architecture
Endpoints work with Protocol Adapters to process requests:
The endpoint configuration specifies:
- Which service type to use (e.g.,
http,fhir,jmix,dicomweb,dicom) - Service-specific options (e.g.,
path_prefixfor HTTP endpoints,local_aetfor DICOM) - How the service should construct request/response envelopes
HTTP (Passthru)
A basic HTTP endpoint for generic HTTP traffic with automatic multi-format support.
Service behavior:
- Accepts an HTTP request and converts it into a
RequestEnvelope - Takes a
ResponseEnvelopeand converts it into an HTTP response - Preserves headers, query parameters, and body
- Automatically parses multiple content types
Supported Content Types:
-
JSON (
application/json,application/fhir+json,application/dicom+json)- Direct pass-through to normalized data
- Default when Content-Type missing
-
XML (
application/xml,text/xml,application/soap+xml)- Converted to JSON structure
- Attributes prefixed with
@ - XXE attack prevention enabled
-
CSV (
text/csv)- Parsed into array of row objects
- First row treated as header
- Formula injection prevention (fields starting with
=,+,-,@are escaped)
-
Form URL-Encoded (
application/x-www-form-urlencoded)- Converted to flat JSON object
- Array notation supported with
[]
-
Multipart Form Data (
multipart/form-data)- Fields and files separated in normalized structure
- File metadata captured (filename, content_type, size, checksum)
- Files NOT saved to disk automatically
-
Binary Content (
image/*,video/*,audio/*,application/pdf,application/octet-stream)- Binary data preserved in envelope
- Metadata extracted (content_type, size, checksum)
Configuration:
[endpoints.api_passthrough]
service = "http"
[endpoints.api_passthrough.options]
path_prefix = "/api"
Content Limits:
[proxy.content_limits]
max_body_size = 10485760 # 10MB (default)
max_csv_rows = 10000 # Maximum CSV rows
max_xml_depth = 100 # Maximum XML nesting
max_multipart_files = 10 # Maximum files per upload
max_form_fields = 1000 # Maximum form fields
FHIR
Extends the HTTP endpoint with FHIR-specific handling for healthcare interoperability.
Service behavior:
- Accepts an HTTP request and converts it into a
RequestEnvelope - Provides FHIR-aware request/response handling
- Takes a
ResponseEnvelopeand converts it into a FHIR-compliant HTTP response
Configuration:
[endpoints.fhir_server]
service = "fhir"
[endpoints.fhir_server.options]
path_prefix = "/fhir"
JMIX
JMIX endpoint registers a strict, fixed set of routes for the JMIX healthcare data exchange format.
Service behavior:
- Registers fixed routes under the configured
path_prefix - Handles JMIX data package operations
Supported routes (under configured path_prefix):
GET {prefix}/api/jmix/{id}- Retrieve JMIX packageGET {prefix}/api/jmix/{id}/manifest- Retrieve package manifestGET {prefix}/api/jmix?studyInstanceUid=...- Query by Study Instance UIDPOST {prefix}/api/jmix- Create JMIX package
Configuration:
[endpoints.jmix_exchange]
service = "jmix"
[endpoints.jmix_exchange.options]
path_prefix = "/data"
DICOMweb
Provides DICOMweb QIDO-RS (Query) and WADO-RS (Retrieve) endpoints for medical imaging.
Service behavior:
- Accepts DICOMweb requests and converts them into
RequestEnvelope - Supports QIDO-RS queries and WADO-RS retrieval operations
- Currently returns 501 Not Implemented for all endpoints (skeleton implementation)
Supported routes:
GET /dicomweb/studies- Query for studies (QIDO-RS)GET /dicomweb/studies/{study_uid}/series- Query for series (QIDO-RS)GET /dicomweb/studies/{study_uid}/series/{series_uid}/instances- Query for instances (QIDO-RS)GET /dicomweb/studies/{study_uid}/metadata- Retrieve study metadata (WADO-RS)GET /dicomweb/studies/{study_uid}/series/{series_uid}/metadata- Retrieve series metadata (WADO-RS)GET /dicomweb/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}/metadata- Retrieve instance metadata (WADO-RS)GET /dicomweb/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}- Retrieve instance (WADO-RS)GET /dicomweb/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}/frames/{frame_numbers}- Retrieve frames (WADO-RS)GET /dicomweb/bulkdata/{bulk_data_uri}- Bulk data retrieval (WADO-RS)
Configuration:
[endpoints.dicomweb_pacs]
service = "dicomweb"
[endpoints.dicomweb_pacs.options]
path_prefix = "/pacs"
DICOM SCP (Service Class Provider)
Provides DICOM DIMSE SCP endpoint for receiving incoming DICOM requests via TCP/IP.
Service behavior:
- Accepts incoming DIMSE connections (C-FIND, C-MOVE, C-GET, C-ECHO)
- Converts DIMSE operations to
RequestEnvelopevia protocol adapter - Routes requests through the pipeline system
- Returns DIMSE responses to the calling SCU
Supported operations:
C-ECHO- Connectivity test (enabled by default)C-FIND- Query for studies/series/imagesC-MOVE- Request dataset transfer to destination AETC-GET- Direct dataset retrievalC-STORE- Store incoming datasets (planned)
Configuration:
[endpoints.dicom_qr_scp]
service = "dicom_scp"
[endpoints.dicom_qr_scp.options]
local_aet = "QR_SCP" # Local Application Entity Title (required)
bind_addr = "0.0.0.0" # Bind address (default: 0.0.0.0)
port = 11112 # Listen port (default: 11112)
enable_echo = true # Enable C-ECHO (default: true)
enable_find = true # Enable C-FIND (default: false)
enable_move = true # Enable C-MOVE (default: false)
enable_get = true # Enable C-GET (default: false)
storage_dir = "./data/dicom" # Storage directory (optional)
Note: The DICOM SCP endpoint uses the DimseAdapter protocol adapter, not HTTP. It listens on the configured port for incoming DIMSE associations.
Backends
Backends enable the pipeline to communicate with external systems (targets). Backends operate within the unified PipelineExecutor and handle the "backend invocation" step of the pipeline.
Architecture
Backend responsibilities:
- Convert
RequestEnvelopeto protocol-specific requests - Communicate with external targets (HTTP endpoints, DICOM PACS, databases, etc.)
- Convert responses back to
ResponseEnvelope - Handle target selection when multiple targets are configured
Note: Backends run inside the PipelineExecutor, not in protocol adapters. All protocols use the same backend implementations.
HTTP (Passthru)
A basic HTTP backend for connecting to HTTP/HTTPS targets.
Service behavior:
- Accepts a
RequestEnvelopeand converts it to an HTTP request - Sends request to configured target
- Converts HTTP response back to
ResponseEnvelope - Preserves headers, status codes, and body
Configuration:
[backends.external_api]
service = "http"
[backends.external_api.options]
base_url = "https://external-api.example.com/v1"
FHIR
Extends the HTTP backend for FHIR resource servers.
Service behavior:
- FHIR-aware request/response handling
- Supports FHIR search parameters and operations
- Validates FHIR content types
Configuration:
[backends.fhir_server]
service = "fhir"
[backends.fhir_server.options]
base_url = "https://hapi.fhir.org/baseR4"
DICOMweb
Extends the HTTP backend for DICOMweb QIDO-RS/WADO-RS/STOW-RS targets.
Service behavior:
- DICOMweb-compliant request formatting
- Multipart handling for STOW-RS
- QIDO-RS query parameter construction
Configuration:
[backends.pacs_dicomweb]
service = "dicomweb"
[backends.pacs_dicomweb.options]
base_url = "https://pacs.example.com/dicomweb"
DICOM SCU (Service Class User)
A DICOM DIMSE backend for connecting to remote DICOM PACS via C-ECHO/C-FIND/C-MOVE/C-GET operations.
Service behavior:
- Converts
RequestEnvelopeto DICOM DIMSE operations (SCU - outgoing requests) - Communicates with remote DICOM nodes using AE titles
- Converts DICOM responses back to
ResponseEnvelope - Supports C-ECHO, C-FIND, C-MOVE, C-GET operations
Supported operations:
C-ECHO- Test connectivityC-FIND- Query for studies/series/imagesC-MOVE- Request dataset transferC-GET- Retrieve datasets
Configuration options:
aet(string, required): Remote Application Entity Titlehost(string, required): PACS hostname or IP addressport(integer, required): PACS port numberlocal_aet(string, optional): Local AE title (default: "HARMONY_SCU")dimse_retrieve_mode(string, optional): DICOM retrieval mode (default: "get")"get"(C-GET): Direct image retrieval, works without PACS-side AE configuration"move"(C-MOVE): Requires PACS to know SCU's AE title and network address
use_tls(boolean, optional): Enable TLS encryption (default: false)incoming_store_port(integer, optional): Port for C-STORE SCP when using C-MOVEpersistent_store_scp(boolean, optional): Keep persistent C-STORE SCP listening
Configuration:
[backends.orthanc_pacs]
service = "dicom_scu"
[backends.orthanc_pacs.options]
aet = "ORTHANC"
host = "localhost"
port = 4242
local_aet = "HARMONY_SCU"
dimse_retrieve_mode = "get"
incoming_store_port = 11112
persistent_store_scp = true
use_tls = false
Prerequisites: Requires DCMTK installed for DICOM operations.
Echo (Test)
A simple echo backend that reflects the request back as the response.
Service behavior:
- Returns the request envelope as the response
- Useful for testing and debugging pipelines
- No external communication
Configuration:
[backends.test_echo]
service = "echo"
Target Selection
Backends can have multiple targets configured. The backend service decides which target to use based on:
- Load balancing strategy
- Health checks
- Request routing rules
Example with multiple targets:
[backends.load_balanced_api]
service = "http"
targets = ["api1", "api2"]
[targets.api1]
url = "https://api1.example.com"
[targets.api2]
url = "https://api2.example.com"
Related Documentation
- Configuration - Complete configuration guide
- Middleware - Request/response transformation
- Authentication - Security and auth setup