changeset 269:76e517d2e300

Handling of the HTTP header "Forwarded" for WADO-RS
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 10 May 2019 12:23:49 +0200
parents 0488d41376b3
children f5abf0b4211a
files NEWS Plugin/Configuration.cpp Resources/Samples/Proxy/NOTES.txt Resources/Samples/Proxy/nginx.local.conf
diffstat 4 files changed, 111 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Apr 18 14:37:17 2019 +0200
+++ b/NEWS	Fri May 10 12:23:49 2019 +0200
@@ -1,6 +1,8 @@
 Pending changes in the mainline
 ===============================
 
+* Handling of the HTTP header "Forwarded" for WADO-RS
+
 
 Version 0.6 (2019-02-27)
 ========================
--- a/Plugin/Configuration.cpp	Thu Apr 18 14:37:17 2019 +0200
+++ b/Plugin/Configuration.cpp	Fri May 10 12:23:49 2019 +0200
@@ -395,11 +395,69 @@
     }
 
 
-    std::string  GetBaseUrl(const OrthancPluginHttpRequest* request)
+    static bool IsHttpsProto(const std::string& proto,
+                             bool defaultValue)
+    {
+      if (proto == "http")
+      {
+        return false;
+      }
+      else if (proto == "https")
+      {
+        return true;
+      }
+      else
+      {
+        return defaultValue;
+      }
+    }
+
+
+    std::string GetBaseUrl(const OrthancPluginHttpRequest* request)
     {
       assert(configuration_.get() != NULL);
       std::string host = configuration_->GetStringValue("Host", "");
-      bool ssl = configuration_->GetBooleanValue("Ssl", false);
+      bool https = configuration_->GetBooleanValue("Ssl", false);
+
+      std::string forwarded;
+      if (host.empty() &&
+          LookupHttpHeader(forwarded, request, "forwarded"))
+      {
+        // There is a "Forwarded" HTTP header in the query
+        // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded
+        
+        std::vector<std::string> forwarders;
+        Orthanc::Toolbox::TokenizeString(forwarders, forwarded, ',');
+
+        // Only consider the first forwarder, if any
+        if (!forwarders.empty())
+        {
+          std::vector<std::string> tokens;
+          Orthanc::Toolbox::TokenizeString(tokens, forwarders[0], ';');
+
+          for (size_t j = 0; j < tokens.size(); j++)
+          {
+            std::vector<std::string> args;
+            Orthanc::Toolbox::TokenizeString(args, tokens[j], '=');
+            
+            if (args.size() == 2)
+            {
+              std::string key = Orthanc::Toolbox::StripSpaces(args[0]);
+              std::string value = Orthanc::Toolbox::StripSpaces(args[1]);
+
+              Orthanc::Toolbox::ToLowerCase(key);
+              if (key == "host")
+              {
+                host = value;
+              }
+              else if (key == "proto")
+              {
+                https = IsHttpsProto(value, https);
+              }
+            }
+          }
+        }
+      }
 
       if (host.empty() &&
           !LookupHttpHeader(host, request, "host"))
@@ -409,7 +467,7 @@
         host = "localhost:8042";
       }
 
-      return (ssl ? "https://" : "http://") + host + GetRoot();
+      return (https ? "https://" : "http://") + host + GetRoot();
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/Proxy/NOTES.txt	Fri May 10 12:23:49 2019 +0200
@@ -0,0 +1,9 @@
+This is a sample configuration file for nginx to test the DICOMweb
+plugin behind a HTTP proxy. To start the proxy as a regular user:
+
+$ nginx -c ./nginx.local.conf -p $PWD
+
+
+References about "Forwarded" header in nginx:
+https://onefeed.xyz/posts/x-forwarded-for-vs-x-real-ip.html
+https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/Proxy/nginx.local.conf	Fri May 10 12:23:49 2019 +0200
@@ -0,0 +1,39 @@
+worker_processes 1;
+error_log stderr;
+daemon off;
+pid nginx.pid;
+
+# `events` section is mandatory
+events {
+  worker_connections 1024; # Default: 1024
+}
+
+http {
+  # prevent nginx sync issues on OSX
+  proxy_buffering off;
+  access_log off;
+
+  server {
+    listen 9977 default_server;
+    client_max_body_size 4G;
+    
+    # location may have to be adjusted depending on your OS and nginx install
+    include /etc/nginx/mime.types;
+
+    # if not in your system mime.types, add this line to support WASM:
+    # types {
+    #    application/wasm                      wasm; 
+    # }
+
+    # reverse proxy orthanc
+	location /orthanc/ {
+		rewrite /orthanc(.*) $1 break;
+		proxy_pass http://127.0.0.1:8042;
+		proxy_set_header Host $http_host;
+		proxy_set_header my-auth-header good-token;
+		#proxy_request_buffering off;
+		#proxy_max_temp_file_size 0;
+		#client_max_body_size 0;
+	}
+  } 
+}