PATH_INFO is not correctly handled with IIS + CGI mapcache
PATH_INFO on IIS is a bit different than we would expect. It's defined here: http://msdn2.microsoft.com/en-us/library/ms524602.aspx
Note that we could set a property (AllowPathInfoForScriptMappings) on the server to make it compatible with the canonically expected value, but that would have the side effect of breaking things like ASP (again, mentioned in the link above). The issue is that, where the CGI spec would expect something like:
PATH_INFO = /msj/rev/012a04065db5
IIS actually gives something like:
PATH_INFO = /list.py/msj/rev/012a04065db5
Although there is a server side variable AllowPathInfoForScriptMappings, but it has side effects. It is more sufficient to handle this issue in mapcache, something like:
scriptName = getenv("SCRIPT_NAME"); if (pathInfo && scriptName) { /* if PATH_INFO contains SCRIPT_NAME trim that from the left (IIS issue) _/ while (_pathInfo != '/' && *scriptName == '/') ++scriptName; if (!strncmp(pathInfo, scriptName, strlen(scriptName))) pathInfo += strlen(scriptName); }
I'd rather this was checked/fixed only for IIS, as there's a potential for backwards incompatibility if people have been using a deployment SCRIPT_NAME that matches a mapcache service name (i.e. mapcache deployed to http://server/tms, serving url such as http://server/tms/tms/1.0.0/etc...)
Possible approach to a fix at https://forums.iis.net/post/1943141.aspx ?
/* Hack for IIS that sets incorrect PATH_INFO */
char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE")-1 TSRMLS_CC);
if (env_server_software &&
env_script_name &&
env_path_info &&
strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 &&
strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0
) {
env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC);
env_path_info += strlen(env_script_name);
if (*env_path_info == 0) {
env_path_info = NULL;
}
env_path_info = _sapi_cgibin_putenv("PATH_INFO", env_path_info TSRMLS_CC);
}
Seems like we might also need this in MapServer as part of OGC API support - which does need PATH_INFO.
As of IIS7 (released in 2007) the same PATH_INFO can be used as other servers by setting the [allowPathInfo] (https://docs.microsoft.com/en-us/iis/configuration/system.webserver/handlers/add#attributes) attribute.
This doesn't have the same issue as the older (IIS6) AllowPathInfoForScriptMappings, although there is an issue apparently with the less used PATH_TRANSLATED.
There is a good summary at https://docs.python.org/3/library/wsgiref.html#wsgiref.handlers.IISCGIHandler:
A specialized alternative to CGIHandler, for use when deploying on Microsoft’s IIS web server, without having set the config allowPathInfo option (IIS>=7) or metabase allowPathInfoForScriptMappings (IIS<7).
By default, IIS gives a PATH_INFO that duplicates the SCRIPT_NAME at the front, causing problems for WSGI applications that wish to implement routing. This handler strips any such duplicated path.
IIS can be configured to pass the correct PATH_INFO, but this causes another bug where PATH_TRANSLATED is wrong. Luckily this variable is rarely used and is not guaranteed by WSGI. On IIS<7, though, the setting can only be made on a vhost level, affecting all other script mappings, many of which break when exposed to the PATH_TRANSLATED bug. For this reason IIS<7 is almost never deployed with the fix (Even IIS7 rarely uses it because there is still no UI for it.).
For reference the following server variables
- getenv("SERVER_SOFTWARE") -
Microsoft-IIS/10.0 - getenv("ORIG_PATH_INFO") - seems to always be null
- getenv("SCRIPT_TRANSLATED") - path of the IIS app e.g.
C:\Inetpub\wwwroot\mapserver\mapserv.exe