OHIF / Viewers

OHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages
https://docs.ohif.org/
MIT License
3.35k stars 3.36k forks source link

Viewer + orthanc + docker compose = CORS #1462

Closed trypag closed 4 years ago

trypag commented 4 years ago

Hello,

I am trying to setup a basic infra based only on docker images. I took inspiration from this repo so far https://github.com/mjstealey/ohif-orthanc-dimse-docker/ it was working as expected. I am now in the process of upgrading most of the images and I am stuck with a CORS error.

This problem emerged after I did the upgrade from the viewer v1 to viewer v3. I did my best to find a solution for 2 days now, getting help from other examples, but I can't understand what's wrong with my nginx configuration.

Code is ready to be tested here https://github.com/trypag/ohif-orthanc-postgres-docker

Hopefully it can serve others once it's fully upgraded. I would really appreciate someone's experience on this, thanks :smile:

trypag commented 4 years ago

Screenshot from 2020-02-25 13-25-46

dannyrb commented 4 years ago

Hmm... Your config has you proxying requests to orthanc. That means requests should hit localhost:8080/orthanc, not orthanc:8042

Your docker-compose stands up orthanc, but makes sure it's not accessible outside of the container's internal network (this is good and as intended) :+1:

It gives the orthanc container, a name of "orthanc", which is how nginx is able to resolve its api address when proxy passing

I'm pretty sure these fields are your issue: https://github.com/trypag/ohif-orthanc-postgres-docker/blob/master/config/viewer.js#L9-L11

servers: {
    dicomWeb: [
      {
        name: 'Orthanc',
        wadoUriRoot: 'http://orthanc:8042/wado',
        qidoRoot: 'http://orthanc:8042/dicom-web',
        wadoRoot: 'http://orthanc:8042/dicom-web',
        qidoSupportsIncludeField: false,
        imageRendering: 'wadors',
        thumbnailRendering: 'wadors',
      },
    ],
  },

Should probably be:

servers: {
    dicomWeb: [
      {
        name: 'Orthanc',
        wadoUriRoot: 'http://localhost:8080/orthanc/wado',
        qidoRoot: 'http://localhost:8080/orthanc/dicom-web',
        wadoRoot: 'http://localhost:8080/orthanc/dicom-web',
        qidoSupportsIncludeField: false,
        imageRendering: 'wadors',
        thumbnailRendering: 'wadors',
      },
    ],
  },
trypag commented 4 years ago

Thanks, I finally understand how to configure the viewer servers, I also understand why requesting orthanc:8042 was not possible. :+1:

So I made a few modifications (basically used your implementation), I managed to remove the extra nginx and use only the one from the viewer's image to proxy. I still have CORS issue, but now I think I am just missing the correct headers in nginx.

Code is updated https://github.com/trypag/ohif-orthanc-postgres-docker

trypag commented 4 years ago

I think I should use the same as here right ?

Should I just replace the proxy related code by the root and index ?

Otherwise I might have misunderstood how to allow other domains to be queried :(

trypag commented 4 years ago

Screenshot from 2020-02-25 14-58-31

I think the viewer's servers are now correctly defined, I am just missing the correct definitions of the headers.

I tried to define those :

location / {
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            #
            # Custom headers and headers various browsers *should* be OK with but aren't
            #
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            #
            # Tell client that this pre-flight info is valid for 20 days
            #
            add_header 'Access-Control-Allow-Headers' 'Authorization';
            add_header 'Access-Control-Allow-Credentials' true;
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Length' 0;
            return 204;
        }
        if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
        }
        if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
            add_header 'Access-Control-Allow-Headers' 'Authorization';
            add_header 'Access-Control-Allow-Credentials' true;
        }

        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
        add_header Cache-Control "no-store, no-cache, must-revalidate";

        # proxy_http_version 1.1;

        # proxy_set_header Host               $host;
        # proxy_set_header X-Real-IP          $remote_addr;
        # proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        # proxy_set_header X-Forwarded-Proto  $scheme;

        # proxy_pass http://orthanc:8042;
    }

Clearly, it's still a failure ^^

trypag commented 4 years ago

It's working ! I had my viewer's config wrong again (orthanc instead of localhost, which made no sense).

I am still interested in how to setup CORS though :)

trypag commented 4 years ago

I can define a simple use case to illustrate the workings :

My current thinking is that nginx (hosted locally at :80) should proxy requests to x.x.x.x:8042 and allow cross domain in the location \ section right ?

Though I can't understand how the viewer's content can be delivered :

location / {
          alias  /var/www/html/;
          index index.html;
          try_files $uri $uri/ /index.html;
          add_header Cache-Control "no-store, no-cache, must-revalidate";
        }

AND at the same time proxied like in here

Not sure if I am clear ?

dannyrb commented 4 years ago

You generally don't want to expose orthanc to the open web. See: https://book.orthanc-server.com/faq/security.html

If Orthanc is put on a server that can be contacted from Internet, put Orthanc behind a reverse proxy, and let this reverse proxy take care of the HTTPS encryption.

This is our nginx "proxy pass" configuration. nginx is handling the web requests, https, etc.

If you have orthanc behind a web server like nginx on a different domain/origin/port, then you can explicitly set CORS headers in the responses nginx returns using the nginx config:

https://enable-cors.org/server_nginx.html

trypag commented 4 years ago

Ok I think I got it :smile: Still not perfect without a proper use case to implement, but I can go further now. Thank you so much for your help, it was clear and really helpful.

Sorry for all the incoming issues I will be opening during the following weeks, as I try to get a deeper understanding of the viewer. Thanks @dannyrb :hand:

supermansrf commented 4 years ago

@trypag where are you at with this? Do you feel comfortable that I could recreate your docker setup and deploy my own version? It seems that what you have come up with is exactly what I'm trying to do. It would be nice to not have to recreate the wheel. I'm hoping for a local instance of OHIF and Orthanc deployed on one machine but I know just enough to make my life miserable about this whole process. I'm trying to help out a friend who needs a reliable way to host and recall US images. We like Orthanc but it's not as user friendly as I want.

trypag commented 4 years ago

Hello @supermansrf , I managed to make a proper docker config, everything is up at https://github.com/trypag/ohif-orthanc-postgres-docker

You should be able to run it easily on your side. Let me know if there is any issue.

supermansrf commented 4 years ago

Thanks for the quick reply. I’ll start messing with it.

supermansrf commented 4 years ago

hey @dannyrb can you have a look at our discussion over here:

https://github.com/trypag/ohif-orthanc-postgres-docker/issues/1

And see if you can shed any light on this issue?