FHIR API
Blaze exposes a FHIR RESTful API under the default context path of /fhir. The CapabilityStatement exposed under /fhir/metadata can be used to discover the capabilities of Blaze. Everything stated there can be considered to be implemented correctly. If you find any discrepancies, please open an issue.
Interactions
Instance Level
- Read
- Versioned Read
- Update
- Delete
- Delete History Since 0.30.1
- History
Type Level
System Level
Operations
The following Operations are implemented:
- $compact Since 0.31
- $cql Since 1.5.0
- $disk-perf Since 1.11
- $graphql
- Measure $evaluate-measure
- Patient $everything Since 0.22
- Patient $purge Since 0.30.1
- CodeSystem $lookup Since 1.7.0
- CodeSystem $validate-code Since 0.32
- ValueSet $expand Since 0.32
- ValueSet $validate-code Since 0.32
Asynchronous Requests
Some requests like $evaluate-measure or complex FHIR searches with _summary=count can take longer as a typical HTTP request response cycle should be open. Typical HTTP request timeouts from client and intermediates are 30 seconds. Requests that take longer than that would require special handling. In oder to overcome that synchronous request handling, FHIR specifies Asynchronous Request Patterns.
Blaze implements the Asynchronous Interaction Request Pattern from FHIR R5.
Example FHIR Search Request
To initiate a sync request, the HTTP header Prefer has to set to respond-async:
curl -svH 'Prefer: respond-async' "http://localhost:8080/fhir/Observation?code=http://loinc.org|8310-5&_summary=count"The response will look like this:
HTTP/1.1 202 Accepted
Content-Location: http://localhost:8080/fhir/__async-status/DD7MLX6H7OGJN7SDThe status code 202 indicates that the request was accepted and will continue to be processed in the background. The Content-Location header contains an opaque URL to a status endpoint.
NOTE
Please be aware that Blaze will respond synchronously if the response is available in time or the async handling isn't implemented yet. Clients always have to be able to handle synchronous responses as well.
Polling that status endpoint:
curl -svH 'Accept: application/fhir+json' "http://localhost:8080/fhir/__async-status/DD7MLX6H7OGJN7SD"will either result in a intermediate result like this:
HTTP/1.1 202 Accepted
X-Progress: in-progressor in the final response:
HTTP/1.1 200 OK
Content-Type: application/fhir+json;charset=utf-8
Content-Length: 412The response itself will be a Bundle of type batch-response:
{
"resourceType": "Bundle",
"id": "DD7MLX6JYN54OHKZ",
"type": "batch-response",
"entry": [
{
"response": {
"status": "200"
},
"resource": {
"resourceType": "Bundle",
"id": "DD7MLX6JZHGD5YSA",
"type": "searchset",
"total": 1689,
"link": [
{
"relation": "self",
"url": "http://localhost:8080/fhir/Observation?code=http%3A%2F%2Floinc.org%7C8310-5&_summary=count&_count=50"
}
]
}
}
]
}Cancelling an Async Request
Async requests can be cancelled before they are completed:
curl -svXDELETE "http://localhost:8080/fhir/__async-status/DD7MLX6H7OGJN7SD"Paging Sessions
Interactions and operations that return a large list of resources support paging via Bundle resources. The various Bundle resources are interlinked via the next link. Type-level searches additionally provide a previous link for backwards navigation. The process of retrieving a part of or all Bundle resources (pages) of a large response forms a paging session. Paging sessions have the following properties:
Stable
Paging sessions operate on a stable database snapshot. Next and previous links point to custom paging session endpoints. Those links expire in order to constrain the usage of a paging session (see Expire). That also means that clients which have access to a paging session, will be able to access resources that were deleted or changed after the session started, for as long as their paging links stay valid.
Expire
Paging links expire because the encryption key their page ID was encrypted with is rotated out of the key set (see Encrypted). A paging link stays usable for at least three hours and is guaranteed to be unusable five hours after it was handed out.
Every page response carries freshly encrypted links, so a session that is paged continuously renews itself. Only links that are left unused expire.
For searches issued via POST, the query params are additionally kept in the page store. Its entries expire after the duration given by PAGE_STORE_EXPIRE (one hour by default) without being accessed, and every page request of the session refreshes them.
Fast
Paging sessions don't require initial setup time and show constant costs per page in most cases. In fact paging sessions don't require book keeping at server side at all. Their state is solely communicated via link URLs. For search requests with more than one parameter, page costs can vary because of internal query handling.
Encrypted
The variable part of paging URLs is encrypted to ensure confidentiality and integrity of the paging parameters. Confidentiality is important in case some of the original query parameters contain sensitive information. To mitigate the risk of exposing this data, FHIR searches are often executed via POST requests, which helps prevent sensitive information from being logged in URLs. Consequently, it is essential that paging URLs do not reveal any confidential data. Integrity is important, because it should not be possible to manipulate the paging URL in order to access a different paging session.
Encryption Key Management
- Key Rotation
- Encryption keys are rotated every hour. At most three keys are stored at any time. A new key is first added as a non-primary key, becomes the primary key used for encryption on the next rotation and is only removed three rotations after it stopped being primary. That way a page ID stays decryptable for at least three and at most five hours after it was created.
- Storage
- Currently, encryption keys are stored in plain text within the admin database. While these keys are not accessible via an API, they are also not encrypted with an external key encryption method.
- Future Improvements
- Implementing external key encryption is feasible but would require additional infrastructure. If you believe that key encryption is necessary, please open an issue for further discussion.
Backwards Navigation
Type-level search results additionally contain a previous link, allowing clients to page backwards through a result set. Because paging sessions keep no server-side state (see Fast), the previous link encodes the chain of preceding page positions. To keep paging URLs bounded in size, this chain is limited to the most recent 10 pages. When paging back further than that, the previous link is omitted; use the first link to jump to the start of the result set instead.
Absolute URLs
Blaze has to generate absolute URLs of its own in links and Location headers. By default Blaze assumes to be accessible under http://localhost:8080. The environment variable BASE_URL can be used to change this.
Besides the static BASE_URL setting, Blaze also respects the reverse proxy headers X-Forwarded-Host, X-Forwarded-Proto and Forwarded to generate its base URL dynamically.