diff --git a/workshop/content/docs/assets/images/mapserver-index-page.png b/workshop/content/docs/assets/images/mapserver-index-page.png new file mode 100644 index 0000000..ceb1f12 Binary files /dev/null and b/workshop/content/docs/assets/images/mapserver-index-page.png differ diff --git a/workshop/content/docs/mapfile/config.md b/workshop/content/docs/mapfile/config.md index aaa5ea4..c8ab113 100644 --- a/workshop/content/docs/mapfile/config.md +++ b/workshop/content/docs/mapfile/config.md @@ -1,16 +1,147 @@ # MapServer Configuration File +MapServer 8.0 introduced support for a global [CONFIG](https://mapserver.org/mapfile/config.html) file. +This allows settings to be defined once and applied to all Mapfiles in a MapServer deployment, +reducing duplication and simplifying configuration. + +This tutorial provides an introduction to the `CONFIG` file, and highlights the [Index Page](https://mapserver.org/output/index-page.html) +functionality that it enables. + +![MapServer Index Page](../assets/images/mapserver-index-page.png) + ## Overview +The configuration file used for the workshop can be found at `workshop/exercises/mapfiles/mapserver.conf`. +It uses a structure similar to a Mapfile, with configuration organized into blocks that are terminated with `END`. + +```scala +CONFIG + ENV + ... + END + MAPS + ... + END + PLUGINS + # not currently used in the workshop, this block can be used + # to add plugins for Oracle and Microsoft SQL Server drivers + ... + END +END +``` + +!!! important + + If you make changes in the `CONFIG` file you need to restart the web server. + The configuration file is read only when the web server (Apache in this workshop) starts. + The easiest way to do this in the workshop is to restart the `mapserver` container: + + ```bash + docker restart mapserver + ``` + +## `ENV` Settings + +The `ENV` (Environment) block is used to store +[Environment Variables](https://mapserver.org/optimization/environment_variables.html) used by MapServer. +Placing them in the configuration file means they do not have to be duplicated in every Mapfile. +Settings defined in the configuration file can be overridden by settings in individual Mapfiles. +When both are present, the Mapfile value takes precedence. + +In the workshop configuration file, the following variables are set: + +- `MS_ONLINERESOURCE ""` the `ONLINERESOURCE` is used by various services, such as WMS, and WFS, to generate + links, for example in `GetCapabilities` requests. An option to set this globally in the `CONFIG` file + was added in MapServer 8.8 (see [RFC 141](https://mapserver.org/development/rfc/ms-rfc-141.html)) to avoid having to set + `ows_onlineresource` for different servers (for example in development and production) in every Mapfile. + In this workshop it is set to an empty string, allowing MapServer to automatically generate URLs based + on the incoming request host and path. +- `OGCAPI_HTML_TEMPLATE_DIRECTORY "/usr/local/share/mapserver/ogcapi/templates/html-bootstrap/"` + this setting points MapServer to the folder containing the Bootstrap HTML templates used when generating + the OGC API interface, for example at . +- `MS_INDEX_TEMPLATE_DIRECTORY "/usr/local/share/mapserver/ogcapi/templates/html-index-bootstrap/"` + a similar setting, but used to point to the Bootstrap templates used when generating the MapServer + [Index Pages](https://mapserver.org/output/index-page.html). +- `MS_MAP_PATTERN "^/etc/mapserver/"` - This is a required setting used to restrict Mapfiles + to specific filesystem locations. This prevents users from requesting arbitrary Mapfiles, + reducing the risk of unauthorised data access. In the workshop Mapfiles are restricted + to `/etc/mapserver` and subdirectories. + +!!! tip + + There are several other settings commented out in the configuration file, to show the different + environment variables available. + + These can be set globally in the `CONFIG` file, and then overridden in individual Mapfiles, + using the syntax `CONFIG "VARIABLE_NAME" "VARIABLE_VALUE"`, for example `CONFIG "MS_ERRORFILE" "stderr"`. + +## `MAPS` Settings + +The `MAPS` block contains a list of all Mapfiles available on the server, in the form of +`key "path"`: + +```scala +MAPS + # the paths used here, are the paths + # within the MapServer Docker container + CLUSTERS "/etc/mapserver/clusters.map" + CONTOURS "/etc/mapserver/contours.map" + # additional mapfiles... +END +``` + +The keys allow us to access the Mapfile using the URL in the form `http://server/KEY/`. + +!!! note + + Mapfiles explicitly registered in the `MAPS` section are considered trusted and are not + subject to `MS_MAP_PATTERN` validation because they are defined server-side rather than + provided by client requests. + + `MS_MAP_PATTERN` is only applied when a Mapfile path is supplied by a client + request, for example: + + `?map=/etc/mapserver/lines.map` + +If we have set the `MS_INDEX_TEMPLATE_DIRECTORY` path in the `ENV` section above, then MapServer +will return an "Index Page", listing all these maps at the root of the MapServer URL: . + +Clicking on one of these links takes you to an individual Mapfile Landing Page, which lists the +services available for that Mapfile, such as WMS, WFS, WCS, and OGC APIs. For example . + +## Code + +!!! example + + - MapServer Index Page request: + - MapServer Mapfile Landing Page example: + +??? Config file "mapserver.conf" + + ``` scala + --8<-- "mapserver.conf" + ``` + +??? Example Mapfile file "config.map" -Set this in the config file - MS_ONLINERESOURCE "/" + ``` scala + --8<-- "config.map" + ``` +## Exercises - Include the one used by the workshop +- Add the Mapfile `./workshop/exercises/mapfiles/config.map` to the configuration file + `./workshop/exercises/mapfiles/mapserver.conf`. Check it appears in the MapServer Index page + at . You will need to restart the MapServer container to see this change. +- Enable the CGI functionality in the Mapfile by changing `"ms_enable_modes" "!*"` + to `"*"` (or comment-out the whole line). This should create a new "OpenLayers Viewer" + link at . +- Comment and uncomment the various `enable_request` `METADATA` items, and see how they affect + the available services for the Mapfile at . -Any changes in the CONFIG file you need to restart the web server: +!!! tip -```bash -docker restart mapserver -``` \ No newline at end of file + When editing a Mapfile, changes are instantly reflected in the HTML Index Pages + (when you refresh the browser). You only need to restart the MapServer Docker container + if you edit the `mapserver.conf` file, as this is read once when the Apache web server + starts. diff --git a/workshop/content/zensical.toml b/workshop/content/zensical.toml index 207efa4..7527b99 100644 --- a/workshop/content/zensical.toml +++ b/workshop/content/zensical.toml @@ -29,7 +29,8 @@ nav = [ { "Lines" = "mapfile/lines.md" }, { "Points" = "mapfile/points.md" }, { "Labels" = "mapfile/labels.md" }, - { "Polygons" = "mapfile/polygons.md" } + { "Polygons" = "mapfile/polygons.md" }, + { "Configuration File" = "mapfile/config.md" } ]}, { "Inputs" = [ { "Raster Data" = "inputs/raster.md" }, diff --git a/workshop/exercises/mapfiles/config.map b/workshop/exercises/mapfiles/config.map new file mode 100644 index 0000000..584e543 --- /dev/null +++ b/workshop/exercises/mapfiles/config.map @@ -0,0 +1,34 @@ +MAP + NAME "CONFIG_MAP" + SIZE 800 400 + PROJECTION + "epsg:4326" + END + IMAGECOLOR "#37929E" + WEB + IMAGEPATH "/etc/mapserver/tmp/" + METADATA + #"ms_enable_modes" "!*" # !* disables all CGI requests + # "wms_enable_request" "*" + # "wcs_enable_request" "*" + # "wfs_enable_request" "*" + # "ows_enable_request" "*" + END + END + EXTENT -180 -90 180 90 + LAYER + NAME "countries" + TYPE POLYGON + STATUS DEFAULT + CONNECTIONTYPE FLATGEOBUF + DATA "data/naturalearth/ne_110m_admin_0_countries.fgb" + + CLASS + STYLE + COLOR "#C7CAB0" + OUTLINECOLOR 255 255 255 + WIDTH 0.1 + END + END + END +END \ No newline at end of file diff --git a/workshop/exercises/mapfiles/countries.map b/workshop/exercises/mapfiles/countries.map index 693b9f9..20bbcea 100644 --- a/workshop/exercises/mapfiles/countries.map +++ b/workshop/exercises/mapfiles/countries.map @@ -1,7 +1,7 @@ # Comment can be added using a hash (#) at the start of a line # All Mapfiles begin with a MAP block, and finish with a closing END MAP - NAME "mymap" + NAME "Countries" # the default size used for image output SIZE 800 400 diff --git a/workshop/exercises/mapfiles/mapserver.conf b/workshop/exercises/mapfiles/mapserver.conf index 4bf0c8a..fed942a 100644 --- a/workshop/exercises/mapfiles/mapserver.conf +++ b/workshop/exercises/mapfiles/mapserver.conf @@ -1,5 +1,6 @@ # # MapServer Config File +# (used by the workshop) # CONFIG @@ -11,10 +12,22 @@ CONFIG MS_ONLINERESOURCE "" # - # Limit Mapfile Access + # OGC API + # + OGCAPI_HTML_TEMPLATE_DIRECTORY "/usr/local/share/mapserver/ogcapi/templates/html-bootstrap/" + + # + # Landing page # + MS_INDEX_TEMPLATE_DIRECTORY "/usr/local/share/mapserver/ogcapi/templates/html-index-bootstrap/" + + # + # Limit Mapfile Access + # required - Mapfiles can only be loaded if they match this regex + MS_MAP_PATTERN "^/etc/mapserver/" + # MS_MAP_NO_PATH "1" - # MS_MAP_PATTERN "^/opt/mapserver" ## required + # MS_MAP_PATTERN "^/opt/mapserver" # # Global Log/Debug Setup @@ -28,9 +41,9 @@ CONFIG # MS_MAPFILE "/opt/mapserver/test/test.map" # - # Proj Library + # Proj (path to proj.db) # - # PROJ_LIB "" + # PROJ_DATA "" # # Request Control @@ -48,17 +61,8 @@ CONFIG # MS_XMLMAPFILE_XSLT # MS_MODE # MS_OPENLAYERS_JS_URL - # MS_TEMPPATH - # MS_MAX_OPEN_FILES - - # - # OGC API - # - OGCAPI_HTML_TEMPLATE_DIRECTORY "/usr/local/share/mapserver/ogcapi/templates/html-bootstrap/" - MS_INDEX_TEMPLATE_DIRECTORY "/usr/local/share/mapserver/ogcapi/templates/html-index-bootstrap/" - MS_MAP_PATTERN "." - # MS_TEMPPATH "/etc/mapserver/tmp" + # MS_MAX_OPEN_FILES END # @@ -90,6 +94,9 @@ CONFIG VECTOR-TILES "/etc/mapserver/vector-tiles.map" WCS "/etc/mapserver/wcs.map" WFS "/etc/mapserver/wfs.map" + + # Example for ./workshop/content/docs/mapfile/config.md + # CONFIG_MAP "/etc/mapserver/config.map" END END diff --git a/workshop/exercises/scripts/map_configs.py b/workshop/exercises/scripts/map_configs.py new file mode 100644 index 0000000..896eb75 --- /dev/null +++ b/workshop/exercises/scripts/map_configs.py @@ -0,0 +1,25 @@ +r""" +C:\VirtualEnvs\mappyfile3\Scripts\Activate.ps1 +cd D:\GitHub\getting-started-with-mapserver +python ./workshop/exercises/scripts/map_configs.py +""" + +import mappyfile +import json +from pathlib import Path + +fn = r"./workshop/exercises/mapfiles/mapserver.conf" +d = mappyfile.open(fn, include_comments=True) + +maps = {} # d["maps"] + +# get .MAP files + +map_files = [p for p in Path("./workshop/exercises/mapfiles").glob("*.map")] + +for mf in sorted(map_files): + maps[mf.stem.upper()] = f"/etc/mapserver/{mf.name}" + +d["maps"] = maps + +print(mappyfile.dumps(d, indent=4))