From 82fc0c7acf6586afea2dac4e7b5e22cec298b1d5 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Wed, 23 Jul 2025 18:34:21 -0700 Subject: [PATCH] Add support for 3rd-party OSM clients --- osm-web/nginx.conf | 104 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 25 deletions(-) diff --git a/osm-web/nginx.conf b/osm-web/nginx.conf index eecb36e..cbaf30e 100644 --- a/osm-web/nginx.conf +++ b/osm-web/nginx.conf @@ -11,6 +11,31 @@ upstream osm-rails-upstream { server osm-rails:3000; } +# Improve support for third-party clients by enabling workspace selection using +# a path prefix (/workspace/123/...). We strip the prefix for upstream services +# here: +# +map $request_uri $mapped_request_uri { + ~^(/workspace/\d+)?(.*)$ $2; +} + +# Improve support for third-party clients by mapping workspace IDs from the URI +# path prefix. We carry it here from a query parameter as needed: +# +map $http_x_workspace $mapped_workspace_id { + default $http_x_workspace; + "" $arg_x_workspace; +} + +# Improve support for third-party clients by mapping TDEI tokens from a request +# basic authorization header or from the user information in a URI: +# +map $http_authorization $mapped_tdei_token { + ~^Basic $remote_user; + ~^Bearer\ (.*)$ $1; + "" $remote_user; +} + server { listen 80; server_name _; @@ -20,44 +45,73 @@ server { error_page 404 /dispatch.map; + # This is effectively the maximum size of a dataset that we're willing to + # accept when creating a workspace: + # + client_max_body_size 2g; + + # Improve support for third-party clients by enabling workspace selection + # using a path prefix (/workspace/123/...). We rewrite the path to remove + # the prefix and carry the workspace ID to the next location context with + # a query parameter: + # + location ~ ^/workspace/(\d+)/ { + rewrite ^/workspace/(\d+)/(.*) /$2?x_workspace=$1 last; + } + + # If a request does not match an API endpoint implemented in CGImap, pass + # the request to the Rails implementation: + # location / { if ($request_method = GET) { - rewrite ^/api/0\.6/map(\.(json|xml))?(\?(.*))?$ /dispatch.map break; - rewrite ^/api/0\.6/(node|way|relation)/[0-9]+(\.(json|xml))?$ /dispatch.map break; - rewrite ^/api/0\.6/(node|way|relation)/[0-9]+/history.*$ /dispatch.map break; - rewrite ^/api/0\.6/(node|way|relation)/[0-9]+/[0-9]+.*$ /dispatch.map break; - rewrite ^/api/0\.6/(node|way|relation)/[0-9]+/relations$ /dispatch.map break; - rewrite ^/api/0\.6/node/[0-9]+/ways$ /dispatch.map break; - rewrite ^/api/0\.6/(way|relation)/[0-9]+/full$ /dispatch.map break; - rewrite ^/api/0\.6/changeset/[0-9]+.*$ /dispatch.map break; - rewrite ^/api/0\.6/(nodes|ways|relations)(\?(.*))?$ /dispatch.map break; - rewrite ^/api/0\.6/changeset/[0-9]+/download$ /dispatch.map break; + rewrite ^/api/0\.6/map(\.(json|xml))?$ /dispatch.map last; + rewrite ^/api/0\.6/(node|way|relation)/[0-9]+(\.(json|xml))?$ /dispatch.map last; + rewrite ^/api/0\.6/(node|way|relation)/[0-9]+/history.*$ /dispatch.map last; + rewrite ^/api/0\.6/(node|way|relation)/[0-9]+/[0-9]+.*$ /dispatch.map last; + rewrite ^/api/0\.6/(node|way|relation)/[0-9]+/relations$ /dispatch.map last; + rewrite ^/api/0\.6/node/[0-9]+/ways$ /dispatch.map last; + rewrite ^/api/0\.6/(way|relation)/[0-9]+/full$ /dispatch.map last; + rewrite ^/api/0\.6/changeset/[0-9]+.*$ /dispatch.map last; + rewrite ^/api/0\.6/(nodes|ways|relations)$ /dispatch.map last; + rewrite ^/api/0\.6/changeset/[0-9]+/download$ /dispatch.map last; } if ($request_method = POST) { - rewrite ^/api/0\.6/changeset/[0-9]+/upload.*$ /dispatch.map break; + rewrite ^/api/0\.6/changeset/[0-9]+/upload.*$ /dispatch.map last; } if ($request_method = PUT) { - rewrite ^/api/0\.6/changeset/[0-9]+/close.*$ /dispatch.map break; - rewrite ^/api/0\.6/changeset/[0-9]+$ /dispatch.map break; - rewrite ^/api/0\.6/changeset/create.*$ /dispatch.map break; + rewrite ^/api/0\.6/changeset/[0-9]+/close.*$ /dispatch.map last; + rewrite ^/api/0\.6/changeset/[0-9]+$ /dispatch.map last; + rewrite ^/api/0\.6/changeset/create.*$ /dispatch.map last; } - location ~ ^/(?!(dispatch\.map)) { - proxy_pass http://osm-rails-upstream; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Remote-User $remote_user; - } + proxy_pass http://osm-rails-upstream; + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + + proxy_set_header Authorization "Bearer $mapped_tdei_token"; + proxy_set_header X-Workspace $mapped_workspace_id; } + # Handle requests for the endpoints implemented in CGImap: + # location ~ \.map$ { fastcgi_pass osm-cgimap:8000; - include fastcgi_params; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param CONNECT_TIMEOUT 0; + + # Large dataset uploads may take a long time to process + fastcgi_read_timeout 3h; + + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param REQUEST_URI $mapped_request_uri; + + fastcgi_param HTTP_AUTHORIZATION "Bearer $mapped_tdei_token"; + fastcgi_param HTTP_X_WORKSPACE $mapped_workspace_id; } }