Personal tools
You are here: Home Documentation How-tos MapScript wrappers for WxS Services

MapScript wrappers for WxS Services

Document Actions
Describes how mapscript can be used to wrap MapServer WxS services such as WMS, WFS and WCS.

MapScript Wrappers for WxS Services

1   Introduction

With the implementation of MapServer RFC 16 in MapServer 4.9, MapScript now has the ability to invoke MapServer's ability to execute OGC Web Service requests such as WMS, WCS, and WFS as well as capturing the results of processing the requests.

This makes it possible to dynamically configure a map object based on information in the original request, and to capture the output of processing requests for further post-processing.

2   Python Examples

The following trivial example, in Python, demonstrates a script that internally provides the map name, but otherwise uses normal mapserver processing.

import mapscript

req = mapscript.OWSRequest()
req.loadParams()

map = mapscript.mapObj( '/u/www/maps/ukpoly/ukpoly.map' )
map.OWSDispatch( req )

The OWSRequest object is used to manage a parsed list of OWS processing options. In the above example they are loaded from the environment using the loadParams() call which fetches and parses them from QUERY_STRING in the same way the mapserv executable would.

Then we load a map, and invoke OWSDispatch with the given arguments on that map. By default the results of the dispatched request are written to stdout which returns them back to the client.

The following example ignores all passed in arguments, and manually constructs a request argument by argument. It is likely more useful for testing purposes than for deploying WxS services, but demonstrates direct manipulation of the request object.

import mapscript

req = mapscript.OWSRequest()
req.setParameter( 'SERVICE', 'WMS' )
req.setParameter( 'VERSION', '1.1.0' )
req.setParameter( 'REQUEST', 'GetCapabilities' )

map = mapscript.mapObj( '/u/www/maps/ukpoly/ukpoly.map' )
map.OWSDispatch( req )

The previous example have all let results be returned directly to the client. But in some cases we want to be able to capture, and perhaps modify the results of our requests in some custom way. In the following example we force the hated OGC required mime type for errors to simple text/xml (warning - non-standard!)

import mapscript

req = mapscript.OWSRequest()
req.loadParams()

map = mapscript.mapObj( '/u/www/maps/ukpoly/ukpoly.map' )

mapscript.msIO_installStdoutToBuffer()
map.OWSDispatch( req )

content_type = mapscript.msIO_stripStdoutBufferContentType()
content = mapscript.msIO_getStdoutBufferBytes()

if content_type == 'vnd.ogc.se_xml':
  content_type = 'text/xml'

print 'Content-type: ' + content_type
print
print content

This example demonstrates capture capturing output of OWSRequest to a buffer, capturing the "Content-type:" header value, and capturing the actual content as binary data. The msIO_getStdoutBufferBytes() function returns the stdout buffer as a byte array. If the result was known to be text, the msIO_getStdoutBufferString() function could have been used to fetch it as a string instead, for easier text manipulation.

3   Perl Example

Most of the same capabilities are accessable in all SWIG based mapscript languages. In perl, we could script creation of a request like this:

#!/usr/bin/perl

use mapscript;

$req = new mapscript::OWSRequest();
$req->setParameter( "SERVICE", "WMS" );
$req->setParameter( "VERSION", "1.1.0" );
$req->setParameter( "REQUEST", "GetCapabilities" );

$map = new mapscript::mapObj( "/u/www/maps/ukpoly/ukpoly.map" );

mapscript::msIO_installStdoutToBuffer();

$dispatch_out = $map->OWSDispatch( $req );

printf "%s\n", mapscript::msIO_getStdoutBufferString();

One issue in perl is that there is currently no wrapping for binary buffers so you cannot call msIO_getStdoutBufferBytes(), and so cannot manipulate binary results.

4   Java Example

One benefit of redirection of output to a buffer is that it is thread-safe. Several threads in the same process can be actively processing requests and writing their results to distinct output buffers. This Java example, used to test multi-threaded access demonstrates that.

import edu.umn.gis.mapscript.mapObj;
import edu.umn.gis.mapscript.OWSRequest;
import edu.umn.gis.mapscript.mapscript;

class WxSTest_thread extends Thread {

  public String       mapName;
  public byte[]       resultBytes;

  public void run() {
      mapObj map = new mapObj(mapName);

      map.setMetaData( "ows_onlineresource", "http://dummy.org/" );

      OWSRequest req = new OWSRequest();

      req.setParameter( "SERVICE", "WMS" );
      req.setParameter( "VERSION", "1.1.0" );
      req.setParameter( "REQUEST", "GetCapabilities" );

      mapscript.msIO_installStdoutToBuffer();

      int owsResult = map.OWSDispatch( req );

      if( owsResult != 0 )
          System.out.println( "OWSDispatch Result (expect 0): " + owsResult );

      resultBytes = mapscript.msIO_getStdoutBufferBytes();
  }
}

public class WxSTest {
  public static void main(String[] args)  {
      try {
          WxSTest_thread tt[] = new WxSTest_thread[100];
          int i;
          int expectedLength=0, success = 0, failure=0;

          for( i = 0; i < tt.length; i++ )
          {
              tt[i] = new WxSTest_thread();
              tt[i].mapName = args[0];
          }
          
          for( i = 0; i < tt.length; i++ )
              tt[i].start();

          for( i = 0; i < tt.length; i++ )
          {
              tt[i].join();
              if( i == 0 )
              {
                  expectedLength = tt[i].resultBytes.length;
                  System.out.println( "Document Length: " + expectedLength + ", expecting somewhere around 10000 or more." );
              }
              else if( expectedLength != tt[i].resultBytes.length )
              {
                  System.out.println( "Document Length:" + tt[i].resultBytes.length + " Expected:" + expectedLength );
                  failure++;
              }
              else
                  success++;
          }

          System.out.println( "Successes: " + success );
          System.out.println( "Failures: " + failure );

      } catch( Exception e ) {
          e.printStackTrace();
      }
  }
}

5   PHP Example

Most of the same capabilities are accessable in php mapscript. Here is an example displaying a wms capabilities.

Example1 : get the capabilities
This is for example what a url could look like :
http://.../php/ows.php?service=WMS&version=1.1.1&Request=GetCapabilities  


<?php

dl("php_mapscript_4.10.0.dll");

$request = ms_newowsrequestobj();

$request->loadparams();

/*exampple on how to modify the parameters :
 forcing the version from 1.1.1 to 1.1.0 */
$request->setParameter("VeRsIoN","1.1.0");

ms_ioinstallstdouttobuffer();

$oMap = ms_newMapobj("../../service/wms.map");

$oMap->owsdispatch($request);

$contenttype = ms_iostripstdoutbuffercontenttype();

$buffer = ms_iogetstdoutbufferstring();

header('Content-type: application/xml');
echo $buffer;

ms_ioresethandlers();

?>


Example2 : get the map
This is for example what a url could look like :
 
http://.../php/ows.php?SERVICE=WMS&VeRsIoN=1.1.1&Request=GetMap&
LAYERS=WorldGen_Outline  


<?php

dl("php_mapscript_4.10.0.dll");

$request = ms_newowsrequestobj();

$request->loadparams();

ms_ioinstallstdouttobuffer();

$oMap = ms_newMapobj("../../service/wms.map");

$oMap->owsdispatch($request);

$contenttype = ms_iostripstdoutbuffercontenttype();

if ($contenttype == 'image/png')
   header('Content-type: image/png');

ms_iogetStdoutBufferBytes();

ms_ioresethandlers();

?> 

6   Use in Non-CGI Environments (mod_php, etc)

The loadParams() call establish parses the cgi environment varabiables (QUERY_STRING, and REQUEST_METHOD) into parameters in the OWSRequest object. In non-cgi environments, such as when php, python and perl are used as "loaded modules" in Apache, or Java with Tomcat, the loadParams() call will not work - in fact in 4.10.x it will terminate the web server instance.

It is necessary in these circumstances for the calling script/application to parse the request url into keyword/value pairs and assign to the OWSRequest object by other means, as shown in some of the above examples explicitly setting the request parameters.

7   Post Processing Capabilities

In the following python example, we process any incoming WxS request, but if it is a GetCapabilities request we replace the Service section in the capabilities with a section read from a file, that is carefully tailored the way we want.

#!/usr/bin/env python

import sys
import elementtree.ElementTree as ET

import mapscript

req = mapscript.OWSRequest()
req.loadParams()

map = mapscript.mapObj( '/u/www/maps/ukpoly/ukpoly.map' )

#
# Handle anything but a GetCapabilities call normally. 
#
if req.getValueByName('REQUEST') <> 'GetCapabilities':

  map.OWSDispatch( req )

#
# Do special processing for GetCapabilities 
#
else:
  mapscript.msIO_installStdoutToBuffer()

  map.OWSDispatch( req )

  ct = mapscript.msIO_stripStdoutBufferContentType()
  content = mapscript.msIO_getStdoutBufferString()
  mapscript.msIO_resetHandlers()

  # Parse the capabilities.
  
  tree = ET.fromstring(content)

  # Strip out ordinary Service section, and replace from custom file.
  
  tree.remove(tree.find('Service'))
  tree.insert(0,ET.parse('./Service.xml').getroot())

  # Stream out adjusted capabilities.
  
  print 'Content-type: ' + ct
  print
  print ET.tostring(tree)

This How-to applies to: MapServer 4.10

by Frank Warmerdam last modified 2006-11-28 10:55
Contributors: Frank Warmerdam

PHP, $request->loadparams() problem

Posted by Jorge de Jesus at 2007-04-05 07:02
I run the PHP script to get a WCS service and the only reply was an empty file whose name was identical to the PHP script, and no error, so I googled and found the solution:

[UMN_MAPSERVER-USERS] PHP Mapscript OwsRequestObj & loadparams()

Armin Burger
Thu, 16 Nov 2006 13:40:47 -0800

Hi


the OWSRequest object for PHP Mapscript has a slight problem at least under Linux. As already mentioned by another user some weeks ago, the definition as described in the how-to

$request = ms_newOwsRequestObj();
$request->loadparams();


is also not working for me (Linux Debian and Ubuntu). There is no error in PHP neither Apache, just the page returned is completely empty as soon as the 'loadparams()' is applied.

For the ones interested in a fast workaround to use the really nice and flexible Mapscript OWS interface via PHP I used the following

$request = ms_newOwsRequestObj();

foreach ($_GET as $k=>$v) {
$request->setParameter($k, $v);
}


This worked fine for me and the WMS service could be accessed by all clients I tested (all seem to use the GET request).

Armin

I am using Linux suse 10.0 and my mapserv is chrooted
 

Powered by Plone