Date: | 2006/05/10 |
---|---|
Author: | Frank Warmerdam |
Contact: | warmerdam at pobox.com |
Last Edited: | May 22, 2006 |
Status: | adopted and implemented |
Version: | MapServer 4.10 |
Id: | $Id: ms-rfc-16.txt 8278 2008-12-23 21:34:31Z hobu $ |
The general intention is that a WMS or WCS service should be able to be setup via MapScript. The web request would be turned over to a MapScript script (Python, Perl, Java, etc) which can then manipulate the request and a map as needed. Then it can invoke the low level MapServer request function (ie. GetMap, GetCapabilities), and if desired manipulate the returned information before returning to the client. This will provide a means to do customizations such as:
Add the following methods on the mapObj in mapscript/swiginc/map.i.
int OWSDispatch( OWSRequest *req );
We can’t call the lower level functions, like msWMSGetCapabilities() directly very easily because these functions require some pre-processing done by msWMSDispatch().
This object is already defined to MapScript in mapscript/swiginc/owsrequest.i but it seems to lack a means of setting it from cgi arguments or directly by parsing a provided url. I propose to add the following method on the OWSRequest:
loadParams();
loadParams( const char * url );
Currently output from functions such as msWMSGetCapabilities() is directed through the msIO services (in mapio.c), such as msIO_printf(). In order to capture this output and make it available for further processing it will be necessary to provide a means for MapScript applications to insert their own IO handlers of some sort.
Additionally, currently the msIO layer has a concept of io handlers, but they are global to the application. For non-trivial use of WxS MapScript services in Java, c# and other multithreaded environments it is desirable for it to be possible to insert per-thread IO handlers.
msIO_resetHandlers();
msIO_installStdoutToBuffer();
msIO_installStdinFromBuffer();
msIO_setStdinBuffer( unsigned char *data, int length );
gdBuffer msIO_getStdoutBufferBytes();
const char *msIO_getStdoutBufferString();
The installed “buffer” handlers will manage their own buffer and concept of current read/write position.
My objective is that folks should be able to do something like this in Python MapScript.
mapscript.msIO_installStdoutToBuffer()
if map.OWSDispatch( req ) == mapscript.MS_SUCCESS:
result = mapscript.msIO_getStdoutBufferString()
mapscript.msIO_resetHandlers()
Questions:
1) Should we be “pushing” handlers instead of installing them and losing track of the previous handler? Then we could just pop them off.
2) Should we make the whole msIOContext thing more visible to MapScript? It seems like it would be complicated.
The msIO_getStdoutBufferBytes() returns a gdBuffer since most language bindings already have a way of using this as a “array of raw bytes” buffer. It is normally used for fetched gdImage buffers. But because the msIO function returns a gdBuffer referring to an internally memory array not “owned” by the gdBuffer we need to add a owns_data flag.
typedef struct {
unsigned char *data;
int size;
int owns_data;
} gdBuffer;
Likewise, each of the language bindings needs to be modified to only call gdFree() on data if owns_data is true.
This:
%typemap(out) gdBuffer {
$result = PyString_FromStringAndSize($1.data, $1.size);
gdFree($1.data);
}
becomes this:
%typemap(out) gdBuffer {
$result = PyString_FromStringAndSize($1.data, $1.size);
if( $1.owns_data )
gdFree($1.data);
}
And similarly for the other bindings.
mapio.c
mapio.h
mapscript/mapscript.i
mapscript/swiginc/owsrequest.i
mapscript/swiginc/image.i
mapscript/swiginc/msio.i (new)
mapscript/python/pymodule.i (gdBuffer)
There are no apparent backward compatibility problems with existing MapScript scripts.
The msautotest/mspython and python unit tests will be extended with at least rudimentary testing of a few of these services.
As we have no automated tests for other MapScript languages, no automated tests will be added, but I will endevour to prepare simple scripts to test things. Currently this has been done for Python and Perl MapScript.
This shows a very simple Python MapScript script that invokes a passed in OWSRequest passed via normal cgi means, but adding a text/plain content type ahead of the regular content type so we can see the results. The script could easily have done extra manipulation on the URL parameters, and on the map object.
Example:
#!/usr/bin/env python
import sys
import mapscript
req = mapscript.OWSRequest()
req.loadParams()
mapscript.msIO_installStdoutToBuffer()
map.OWSDispatch( req )
print 'Content-type: text/plain'
print
print mapscript.msIO_getStdoutBufferString()
+1: FrankW, SteveW.
None