fix(multiframe): metadata handling of NM studies and loading order (#4554)
This commit is contained in:
1 parent
6729534a1a
commit
7624ccb5e4
57 files changed
+482
-662
No files matched your search
@@ -102,18 +102,12 @@ directory:
|
||||
yarn global add http-server
|
||||
|
||||
# Change the directory to the platform/app
|
||||
cd platform/app
|
||||
|
||||
# Serve the files in our current directory
|
||||
npx serve ./dist -c ../public/serve.json
|
||||
```
|
||||
|
||||
:::caution
|
||||
In the video below notice that there is `platform/viewer` which has been renamed to `platform/app` in the latest version
|
||||
:::
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/551957266?badge=0&autopause=0&player_id=0&app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
|
||||
</div>
|
||||
|
||||
|
||||
### Automating Builds and Deployments
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Cross-Origin Information for OHIF
|
||||
@@ -7,42 +7,10 @@ sidebar_position: 7
|
||||
This document describes various security configurations, settings and environments/contexts needed to fully leverage OHIF’s capabilities. One may need some configurations while others might need ALL of them - it all depends on the environment OHIF is expected to run in.
|
||||
|
||||
In particular, three of OHIF’s features depend on these configurations:
|
||||
- [OHIF’s use of SharedArrayBuffer](#sharedarraybuffer)
|
||||
- [Embedding OHIF in an iframe](#embedding-ohif-in-an-iframe)
|
||||
- [XMLHttpRequests to fetch data from data sources](#cors-in-ohif)
|
||||
|
||||
|
||||
|
||||
## SharedArrayBuffer
|
||||
A `SharedArrayBuffer` is a JavaScript object that is similar to an `ArrayBuffer` but can be shared between web workers and the window that spawned them via the `postMessage` API. See [SharedArrayBuffer in MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) for more information.
|
||||
|
||||
:::tip
|
||||
To turn off Shared Array Buffer completely, just set `useSharedArrayBuffer` to `false` in the [OHIF configuration](../configuration/configurationFiles.md). But keep in mind that you will not get the performance boost that Shared Array Buffer offers for decoding and rendering big volumes where web workers write to the same memory space.
|
||||
:::
|
||||
|
||||
### Security Requirements
|
||||
|
||||
In order to use `SharedArrayBuffer` objects in the browser, the following security conditions must be met:
|
||||
|
||||
- The page must be served in a [secure context](#secure-context).
|
||||
- The page must have [cross-origin isolation](#cross-origin-isolation) enabled.
|
||||
|
||||
### `SharedArrayBuffer` in OHIF
|
||||
|
||||
OHIF uses `SharedArrayBuffer` in its volume loader (from Cornerstone3D). It comes with the benefit of improved performance and optimization at the cost of some configuration to use it.
|
||||
|
||||
As such, if the following popup is shown when launching OHIF then the OHIF server will have to be configured to permit the loading of volumetric images and data. Note that stack viewports are still available and functional even when this error is present.
|
||||
|
||||

|
||||
|
||||
To better determine which (if not all) of the [security requirements](#security-requirements) are lacking, have a look at the browser console.
|
||||
|
||||
Output in the console similar to the following indicates that OHIF is not running in a [secure context](#secure-context).
|
||||
|
||||

|
||||
|
||||
Absence of the above error in the console together with the presence of the Cross Origin Isolation popup warning, likely indicates that either or both of the [COOP](#coop---cross-origin-opener-policy) and/or [COEP](#coep---cross-origin-embedder-policy) headers are not set for OHIF.
|
||||
|
||||
## Embedding OHIF in an iframe
|
||||
|
||||
As described [here](./iframe.md), there are cases where OHIF will be embedded in an iframe. The following links provide more information for setting up and configuring OHIF to work in an iframe:
|
||||
@@ -64,9 +32,6 @@ URLs that are NOT local must be delivered over `https://` or `wss://` (i.e. TLS)
|
||||
|
||||
A page embedded in an iframe is considered secure if it itself and every one of its embedding ancestors are delivered securely. Otherwise it is deemed insecure.
|
||||
|
||||
### Why does OHIF require a secure context?
|
||||
|
||||
Beyond all of the inherent benefits of a secure connection, OHIF requires a secure context so that it can utilize [SharedArrayBuffer](#sharedarraybuffer) objects for volume rendering.
|
||||
|
||||
### Configuring/setting up a secure context
|
||||
|
||||
@@ -143,91 +108,8 @@ add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
```
|
||||
:::
|
||||
|
||||
## COOP - Cross-Origin Opener Policy
|
||||
|
||||
The COOP HTTP response header restricts the global, root document of the page from being referenced and accessed by another cross-origin document that might open the page in a window. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) for more information.
|
||||
|
||||
### Header Values Pertinent to OHIF (see [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy#syntax) for more information)
|
||||
|
||||
|Value|Description|
|
||||
|-----|-----------|
|
||||
|same-origin|Restricts the document to be referenced by openers of the same origin only.|
|
||||
|
||||
### COOP in OHIF
|
||||
|
||||
COOP is required for [SharedArrayBuffer](#sharedarraybuffer) usage in OHIF. See also [Troubleshooting Cross-origin Isolation in OHIF](#troubleshooting-cross-origin-isolation-in-ohif).
|
||||
|
||||
## COEP - Cross-Origin Embedder Policy
|
||||
|
||||
The COEP HTTP response header restricts cross-origin documents from being embedded into a document (e.g. in an iframe, video, image, etc). See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) for more information.
|
||||
|
||||
### Header Values Pertinent to OHIF (see [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#syntax) for more information)
|
||||
|
||||
|Value|Description|
|
||||
|-----|-----------|
|
||||
|require-corp|Permits the document to load either of the following embedded resources: <ul><li>Those from the same origin</li><li>Cross-origin resources embedded by a DOM element that has the appropriate [crossorigin attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) set</li><li>Cross-origin resources with the appropriate [CORP response header](#corp---cross-origin-resource-policy)</li></ul>
|
||||
|credentialless|See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#syntax) for more information|
|
||||
|
||||
### COEP in OHIF
|
||||
|
||||
COEP is required for [SharedArrayBuffer](#sharedarraybuffer) usage in OHIF. See also [Troubleshooting Cross-origin Isolation in OHIF](#troubleshooting-cross-origin-isolation-in-ohif).
|
||||
|
||||
## Cross-origin Isolation
|
||||
|
||||
Cross-origin isolation is [enabled](https://web.dev/cross-origin-isolation-guide/#enable-cross-origin-isolation) for a web page when the following COOP and COEP headers are set.
|
||||
- [COOP](#coop---cross-origin-opener-policy) with `same-origin`
|
||||
- [COEP](#coep---cross-origin-embedder-policy) with `require-corp` or `credentialless`
|
||||
|
||||
### iframe
|
||||
|
||||
An iframe is considered to have cross-origin isolation enabled if it itself has the appropriate COOP and COEP headers set as well as every one of its embedding ancestors.
|
||||
|
||||
### Troubleshooting Cross-origin Isolation in OHIF
|
||||
|
||||
The [SharedArrayBuffer in OHIF](#sharedarraybuffer-in-ohif) section describes how to determine if there are problems with cross-origin isolation in OHIF. If it is determined that COOP and/or COEP is indeed an issue, then the COOP and COEP headers must be set for OHIF. How to accomplish this varies per server or service that is hosting OHIF. The following are just a few examples.
|
||||
|
||||
:::tip
|
||||
In the default dev environment, the following can be set in the webpack.pwa.js file…
|
||||
|
||||
```javascript
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp"
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If deploying OHIF using Netlify, the Netlify configuration [file](https://docs.netlify.com/configure-builds/file-based-configuration/) can be used to configure the headers as such…
|
||||
|
||||
```
|
||||
[[headers]]
|
||||
# Define which paths this specific [[headers]] block will cover.
|
||||
for = "/*"
|
||||
|
||||
[headers.values]
|
||||
Cross-Origin-Opener-Policy = "same-origin"
|
||||
Cross-Origin-Embedder-Policy = "require-corp"
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If OHIF is served behind nginx, then the headers can be set in the nginx.conf file as follows. The [template nginx configuration file](https://github.com/OHIF/Viewers/blob/master/.docker/Viewer-v3.x/default.conf.template) for creating a [OHIF Docker image](./docker.md#building-the-docker-image) has an example of this too.
|
||||
```nginx
|
||||
server {
|
||||
location / {
|
||||
add_header Cross-Origin-Opener-Policy same-origin;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
## CORP - Cross-Origin Resource Policy
|
||||
|
||||
The CORP HTTP response header indicates which origins can read and use a resource. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy) for more information.
|
||||
|
||||
### Header Values (see [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy#usage) for more information)
|
||||
|
||||
@@ -239,12 +121,6 @@ The CORP HTTP response header indicates which origins can read and use a resourc
|
||||
|
||||
### OHIF and CORP
|
||||
|
||||
There are two scenarios where the CORP header is relevant to OHIF:
|
||||
|
||||
- [PDF from a Cross Origin DICOMweb Data Source](#pdf-from-a-cross-origin-dicomweb-data-source)
|
||||
- [OHIF as a Cross-origin Resource in an iframe](#ohif-as-a-cross-origin-resource-in-an-iframe)
|
||||
|
||||
Both these scenarios stem from the fact that OHIF has to be served with the [COEP](#coep---cross-origin-embedder-policy) header to support [SharedArrayBuffer](#sharedarraybuffer).
|
||||
|
||||
#### PDF from a Cross Origin DICOMweb Data Source
|
||||
|
||||
@@ -266,48 +142,3 @@ If the dcm4chee server and the OHIF server are hosted on the same site, then the
|
||||
add_header 'Cross-Origin-Resource-Policy' 'same-site' always;
|
||||
```
|
||||
:::
|
||||
|
||||
#### OHIF as a Cross-origin Resource in an iframe
|
||||
|
||||
There are cases where [OHIF is embedded in an iframe](./iframe.md) and the embedding page is from a different origin. Again due to the [security requirements for SharedArrayBuffer](#security-requirements), [both OHIF and the embedding page](#iframe) must have the appropriate COEP header. In this scenario, OHIF is the cross-origin resource and since the `<iframe>` tag does not support the `crossorigin` attribute, OHIF must be served with the appropriate CORP header.
|
||||
|
||||
:::info
|
||||
Setting the CORP header such that OHIF can be embedded in an iframe varies per server or service hosting OHIF. What follows are just a few examples. Note that whenever the embedding page is hosted on the same site as OHIF, consider using the `same-site` value instead of `cross-origin`.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
In the default dev environment, the following can be set in the webpack.pwa.js file…
|
||||
|
||||
```javascript
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Resource-Policy": "cross-origin",
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If deploying OHIF using Netlify, the Netlify configuration [file](https://docs.netlify.com/configure-builds/file-based-configuration/) can be used to configure the header as such…
|
||||
|
||||
```
|
||||
[[headers]]
|
||||
# Define which paths this specific [[headers]] block will cover.
|
||||
for = "/*"
|
||||
|
||||
[headers.values]
|
||||
Cross-Origin-Resource-Policy = "cross-origin"
|
||||
```
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If OHIF is served behind nginx, then the header can be set in the nginx.conf file as follows.
|
||||
|
||||
```nginx
|
||||
server {
|
||||
location / {
|
||||
add_header Cross-Origin-Resource-Policy cross-origin;
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
@@ -35,22 +35,13 @@ PUBLIC_URL=/my-awesome-viewer/ APP_CONFIG=config/default.js yarn build
|
||||
```
|
||||
|
||||
We can use the `npx serve` to serve the build folder. There are two things you need to consider however,
|
||||
1. You need to change the public/serve.json file to reflect the new routerBasename in the destination (see the example below)
|
||||
1. You need to change the `public/serve.json` file to reflect the new routerBasename in the destination (see the example below)
|
||||
|
||||
|
||||
```json
|
||||
// final serve.json
|
||||
{
|
||||
"rewrites": [{ "source": "*", "destination": "my-awesome-viewer/index.html" }],
|
||||
"headers": [
|
||||
{
|
||||
"source": "**/*",
|
||||
"headers": [
|
||||
{ "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" },
|
||||
{ "key": "Cross-Origin-Opener-Policy", "value": "same-origin" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -18,6 +18,14 @@ The machine on which to build and run the Docker container must have:
|
||||
3. [Docker](https://docs.docker.com/get-docker/) installed.
|
||||
|
||||
## Building the Docker Image
|
||||
|
||||
:::info
|
||||
In this tutorial, we will build the Docker image for the OHIF Viewer and OHIF server as defined in the `default.js` config. If you need a custom build, you can modify the configuration file to include your data sources and then build the Docker image. For more information on data sources, see [here](../platform/extensions/modules/data-source.md).
|
||||
|
||||
Below we show how to point the Docker image to a custom configuration file.
|
||||
:::
|
||||
|
||||
|
||||
The docker image can be built from a terminal window as such:
|
||||
1. Switch to the OHIF Viewer code root directory.
|
||||
2. Issue the following Docker command. Note that what follows `-t` flag is the `{name}:{tag}` for the Docker image and is arbitrary when creating a local Docker image.
|
||||
@@ -121,20 +129,8 @@ For SSL Docker deployments, the CORP header value is set [here](https://github.c
|
||||
We make no claims or guarantees regarding this section concerning security. If in doubt, enlist the help of an expert and conduct proper audits.
|
||||
:::
|
||||
|
||||
### Why SSL?
|
||||
As described [here](./cors.md), OHIF must be used in a [secure context](./cors.md#secure-context) in order to fully leverage all of OHIF's capabilities. Whenever OHIF is not running in a secure context and is navigated to using the OHIF's server IP address (e.g. `http://192.168.1.162:3000`) or domain name (e.g. `http://my.ohif.server`) then the following popup message will be displayed in OHIF
|
||||
|
||||

|
||||
|
||||
and the following message will appear in the browser console.
|
||||
|
||||

|
||||
|
||||
:::info
|
||||
The above indicate that OHIF is not running in a secure context. Among other things, this means information transferred to/from OHIF is not encrypted and certain capabilities such as 3D volume loading will NOT work. However, basic stack viewport functionality will continue to function.
|
||||
|
||||
Consideration must be given as to whether OHIF should be deployed in a secure context over SSL.
|
||||
:::
|
||||
If OHIF is not deployed over SSL, this means information transferred to/from OHIF is not encrypted. Consideration must be given as to whether OHIF should be deployed in a secure context over SSL.
|
||||
|
||||
### Specifying the SSL Port, Certificate and Private Key
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
sidebar_position: 7
|
||||
sidebar_label: iframe
|
||||
---
|
||||
|
||||
@@ -40,7 +40,7 @@ The PUBLIC_URL tells the application where to find the static assets and the rou
|
||||
|
||||
### Try it locally
|
||||
|
||||
Download the index.html and the build (against the /ohif/ path) from [here](https://ohif-assets.s3.us-east-2.amazonaws.com/iframe-basic/Archive.zip)
|
||||
Download the index.html and the build (against the /ohif/ path) from [here](https://ohif-assets-new.s3.us-east-1.amazonaws.com/iframe-basic/Archive.zip)
|
||||
|
||||
Then run the
|
||||
|
||||
@@ -53,119 +53,3 @@ npx http-server unzipped-folder
|
||||
You should be able to see
|
||||
|
||||

|
||||
|
||||
:::info
|
||||
Notice the Cross Origin Isolation Warning. It is present to indicate that OHIF cannot render volumes because the volume viewports
|
||||
use SharedArrayBuffer which is not allowed for non cross origin isolated apps. You can read more about Cross Origin Isolation here
|
||||
https://web.dev/coop-coep/ or follow the steps below to enable it.
|
||||
:::
|
||||
|
||||
### Fixing the Cross Origin Isolation Warning to enable volume rendering
|
||||
|
||||
For that we need a more sophisticated setup, since we need to add the Cross Origin Embedder Policy and Cross Origin Opener Policy headers
|
||||
to make the parent app cross origin isolated. For that we can use an Express server. (Note: you can use any other method
|
||||
to add the headers, this is just one of the methods)
|
||||
|
||||
Download files from [here](https://ohif-assets.s3.us-east-2.amazonaws.com/iframe-express/Archive.zip)
|
||||
|
||||
```js
|
||||
const express = require("express")
|
||||
const app = express()
|
||||
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader("Cross-Origin-Opener-Policy", "same-origin")
|
||||
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp")
|
||||
next()
|
||||
})
|
||||
|
||||
app.use(express.static("public")) // 'public' should be the folder with the static OHIF build files
|
||||
|
||||
app.listen(8080, () => console.log("Listening on port 8080!"))
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
:::tip
|
||||
if you are using webpack with react you can set
|
||||
|
||||
```js
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If you are using Angular, you should modify the `angular.json` file to add the headers
|
||||
|
||||
```js
|
||||
"serve": {
|
||||
//
|
||||
"configurations": {
|
||||
//
|
||||
"development": {
|
||||
//
|
||||
"headers": {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp"
|
||||
}
|
||||
}
|
||||
},
|
||||
//
|
||||
},
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
|
||||
## Development Server
|
||||
|
||||
If you are not using the static build, you can use the iframe to load the viewer from the local development server. For example, if you are running the viewer locally on port 3000, you can use the following iframe element to load the viewer:
|
||||
|
||||
```html
|
||||
// e.g., app running on 3001 and iframe loading the viewer from 3000
|
||||
<iframe src="http://localhost:3000" style="width: 100%; height: 500px; border: none"/>
|
||||
```
|
||||
|
||||
Notice that not including the static build removes the need for
|
||||
the PUBLIC_URL and the routerBasename. However, the Cross Origin Resource Policy (CORP)
|
||||
headers must be set because the viewer will be loaded from a different port. You can read
|
||||
more about CORP [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy).
|
||||
Basically in the development server that is serving the viewer, add the following headers:
|
||||
|
||||
```js
|
||||
// use this if the embedding app is running on the same site as OHIF
|
||||
// (e.g. parent/embedding app is http://localhost:3001 and OHIF is http://localhost:3000)
|
||||
"Cross-Origin-Resource-Policy": "same-site"
|
||||
or
|
||||
|
||||
// use this if the embedding app is a completely different origin than OHIF (e.g.
|
||||
// parent/embedding app is http://192.168.1.2 and OHIF is http://localhost:3000)
|
||||
"Cross-Origin-Resource-Policy": "cross-origin"
|
||||
```
|
||||
|
||||
:::info
|
||||
You can't set the `Cross-Origin-Resource-Policy` to `same-origin` since the viewer is loaded from a different port.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
If you are using webpack to serve the viewer it would be
|
||||
|
||||
```js
|
||||
devServer: {
|
||||
headers: {
|
||||
"Cross-Origin-Resource-Policy": "same-site" // cross-origin is also valid
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
Take a look at how other people have integrated OHIF in their react app
|
||||
|
||||
example1: https://github.com/OHIF/Viewers/issues/3371#issuecomment-1630405255
|
||||
:::
|
||||
Reference in new issue
Block a user