|
| 1 | +.. _rfc141: |
| 2 | + |
| 3 | +================================================ |
| 4 | +MS RFC 141: MapServer CONFIG MS_ONLINERESOURCE |
| 5 | +================================================ |
| 6 | + |
| 7 | +:Author: Seth Girvin |
| 8 | +:Contact: sethg@geographika.co.uk |
| 9 | +:Last Updated: 2026-02-06 |
| 10 | +:Version: MapServer 8.8 |
| 11 | +:Status: Proposed |
| 12 | + |
| 13 | +Overview |
| 14 | +-------- |
| 15 | + |
| 16 | +This RFC proposes adding a new environment variable, ``MS_ONLINERESOURCE``, to |
| 17 | +the MapServer :ref:`CONFIG file <config>`. |
| 18 | + |
| 19 | +The variable acts as a global fallback when no service-specific |
| 20 | +``*_onlineresource`` metadata (defined in the Mapfile |
| 21 | +:ref:`mapfile-web-metadata`) is provided. For background on service-specific |
| 22 | +usage, see :ref:`online_resource_wms`. |
| 23 | + |
| 24 | +The ``*_onlineresource`` settings define the public-facing URLs that MapServer |
| 25 | +advertises in GetCapabilities and related responses for accessing its OGC |
| 26 | +services (WMS, WFS, WCS, OGC Features API, etc.). These URLs are consumed by clients and must resolve correctly. |
| 27 | + |
| 28 | +Introducing a global ``MS_ONLINERESOURCE`` addresses the following issues: |
| 29 | + |
| 30 | +1. Mapfiles currently require service-specific ``*_onlineresource`` values, |
| 31 | + or an ``ows_onlineresource`` to be modified for each deployment environment |
| 32 | + (for example, local development, staging, and production). |
| 33 | + This RFC allows these environment-specific settings |
| 34 | + to be defined once in a single ``CONFIG`` file. |
| 35 | + |
| 36 | +2. When a Mapfile does not define ``*_onlineresource`` metadata, MapServer |
| 37 | + attempts to construct the service URL from request headers and server |
| 38 | + variables. This approach can produce incorrect or inconsistent URLs in more |
| 39 | + complex deployments, particularly when reverse proxies are used. As a |
| 40 | + result, explicitly defining ``*_onlineresource`` metadata is currently |
| 41 | + strongly recommended. |
| 42 | + |
| 43 | +Current Implementation |
| 44 | +---------------------- |
| 45 | + |
| 46 | +When a Mapfile does not define ``*_onlineresource`` metadata, MapServer uses |
| 47 | +the ``msBuildOnlineResource()`` function (in ``maputil.c``) to construct the |
| 48 | +base **online resource URL**. |
| 49 | + |
| 50 | +The URL is generated dynamically from CGI request data and server environment |
| 51 | +variables, and relies on CGI and proxy headers; this can produce incorrect |
| 52 | +results in some server or reverse-proxy configurations. |
| 53 | + |
| 54 | +The function determines the URL components as follows: |
| 55 | + |
| 56 | +- **Hostname** |
| 57 | + |
| 58 | + - Uses ``HTTP_X_FORWARDED_HOST`` if present |
| 59 | + - Falls back to ``SERVER_NAME`` |
| 60 | + - If multiple forwarded hosts are provided, only the first is used |
| 61 | + |
| 62 | +- **Port** |
| 63 | + |
| 64 | + - Uses ``HTTP_X_FORWARDED_PORT`` if present |
| 65 | + - Otherwise uses ``SERVER_PORT`` |
| 66 | + |
| 67 | +- **Protocol** |
| 68 | + |
| 69 | + - Defaults to ``http`` |
| 70 | + - Uses ``https`` if ``HTTPS=on`` or ``SERVER_PORT=443`` |
| 71 | + - ``HTTP_X_FORWARDED_PROTO`` overrides all other logic |
| 72 | + |
| 73 | +- **Path** |
| 74 | + |
| 75 | + - Uses ``SCRIPT_NAME`` |
| 76 | + - Appends ``PATH_INFO`` if present |
| 77 | + |
| 78 | +- **Query parameters** |
| 79 | + |
| 80 | + - If the request is a GET request and includes a ``map=`` parameter, it is |
| 81 | + appended as ``map=...&`` |
| 82 | + |
| 83 | +The port is omitted when it matches the protocol default (``80`` for HTTP, |
| 84 | +``443`` for HTTPS); otherwise it is included explicitly. |
| 85 | + |
| 86 | +The resulting URL has the general form: |
| 87 | + |
| 88 | +:: |
| 89 | + |
| 90 | + [protocol]://[hostname][:port][script][pathinfo]?[map=...&] |
| 91 | + |
| 92 | +Examples: |
| 93 | + |
| 94 | +:: |
| 95 | + |
| 96 | + https://maps.example.com/mapserv? |
| 97 | + https://maps.example.com/mapserv/ogc?map=/data/example.map& |
| 98 | + http://localhost:8080/cgi-bin/mapserv? |
| 99 | + |
| 100 | +If the hostname, port, or script name cannot be determined, the function |
| 101 | +fails with a CGI error: |
| 102 | + |
| 103 | +:: |
| 104 | + |
| 105 | + Impossible to establish server URL. |
| 106 | + |
| 107 | + |
| 108 | +Proposed Implementation |
| 109 | +----------------------- |
| 110 | + |
| 111 | +Users will be able to add the new environment variable to the ``CONFIG`` file as follows: |
| 112 | + |
| 113 | +:: |
| 114 | + |
| 115 | + CONFIG |
| 116 | + ENV |
| 117 | + MS_ONLINERESOURCE "http://localhost/test/" |
| 118 | + |
| 119 | +Notes: |
| 120 | + |
| 121 | +- Existing ``*_onlineresource`` metadata in a Mapfile will take precedence over |
| 122 | + the ``CONFIG`` setting. |
| 123 | + |
| 124 | +- If ``MS_ONLINERESOURCE`` is set to an empty string, the resulting base URL |
| 125 | + will be empty. Users are responsible for providing a valid URL for their |
| 126 | + environment. |
| 127 | + |
| 128 | +- There are no plans to support separate ``MS_ONLINERESOURCE`` values for |
| 129 | + different services. While this could be useful in some scenarios, having |
| 130 | + multiple variables such as ``MS_WMS_ONLINERESOURCE`` or |
| 131 | + ``MS_WFS_ONLINERESOURCE`` would add unnecessary complexity. |
| 132 | + |
| 133 | +Testing |
| 134 | +------- |
| 135 | + |
| 136 | +The ``msautotests`` test suite will be updated to validate various ``CONFIG`` |
| 137 | +and Mapfile setups, including: |
| 138 | + |
| 139 | +- Cases with and without a ``MS_ONLINERESOURCE`` setting |
| 140 | +- The case where ``MS_ONLINERESOURCE`` is set to an empty string |
| 141 | + |
| 142 | +Security Concerns |
| 143 | +----------------- |
| 144 | + |
| 145 | +There are no known security concerns at the moment. |
| 146 | + |
| 147 | +MapScript |
| 148 | +--------- |
| 149 | + |
| 150 | +MapScript already supports ``CONFIG`` files, so no changes are required. |
| 151 | + |
| 152 | +Example usage: |
| 153 | + |
| 154 | +:: |
| 155 | + |
| 156 | + # Create a new map object with a CONFIG file |
| 157 | + config = mapscript.configObj(r"C:\MapServer\apps\mapserver.conf") |
| 158 | + map = mapscript.mapObj(r"C:\MapServer\my.map", config) |
| 159 | + |
| 160 | + # The CONFIG file can also be passed to the fromstring helper method |
| 161 | + mapscript.fromstring("MAP NAME TEST END", r"C:/MapfileResources/", config_file) |
| 162 | + |
| 163 | + |
| 164 | +Affected files |
| 165 | +-------------- |
| 166 | + |
| 167 | ++ ``maputil.c`` |
| 168 | + |
| 169 | +Ticket Reference |
| 170 | +---------------- |
| 171 | + |
| 172 | +TODO |
| 173 | + |
| 174 | +Documentation |
| 175 | +------------- |
| 176 | + |
| 177 | +Voting History |
| 178 | +-------------- |
| 179 | + |
| 180 | +TODO |
0 commit comments