MS RFC 16:MapScript WXS服务¶
- 日期
2006/05/10
- 作者
Frank Warmerdam
- 联系方式
Pobox.com上可了解有关Warmerdam的更多信息
- 最后编辑
2006年5月22日
- 状态
通过并实施
- 版本
MAPServer 4.10
目的¶
一般来说,wms或wcs服务应该能够通过mapscript进行设置。Web请求将被转换为MyScript脚本(Python、Perl、Java等),然后可以根据需要操作请求和映射。然后它可以调用低级mapserver请求函数(即getmap、getcapabilities),如果需要,在返回到客户机之前操作返回的信息。这将提供进行自定义的方法,例如:
实施安全策略。
使用从数据库等动态创建的地图。
扩充功能文档,带有不能通过.map元数据标记设置的辅助信息。
调整错误行为。
技术解决方案¶
getcapabilities、getfeatureinfo和getmap调用可从mapscript调用的WMS,并捕获结果进行处理。
getcapabilities、describeCoverage和getcoverge从mapscript调用wcs,并捕获结果进行处理。
getCapabilities、describeFeatureType和getFeature调用可从mapscript调用的WFS,并捕获结果进行处理。
通过owsdispatch(如sos)发送的任何其他OWS服务也可以从mapscript访问。
通过mapio.c服务完成从mapserver服务捕获各种输出的IO挂钩,与用于捕获fastcgi服务的输出相同。
所有基于SWIG的MaScript语言都将得到支持(Perl、Python、Ruby、Cype、Java)。如果php-mapscript维护人员执行类似的实现,则可能支持php(非swig)。
将编写一个mapscript wxs howto,包括定制服务的简单示例。
WXS函数¶
在mapscript/swiginc/map.i中的mapobj上添加以下方法。
int OWSDispatch( OWSRequest *req );
我们不能很容易地直接调用较低级别的函数,如mswmsgetCapabilities(),因为这些函数需要由mswmsdispatch()进行一些预处理。
请注意,owsdispatch()重新配置调用它的映射以匹配请求。
请注意,owsrequest的结果仍然是通过正常的stdout流处理写出的,因此需要单独的msio挂钩来捕获结果。
OWSRequest¶
这个对象已经在mapscript/swiginc/owsrequest.i中定义为mapscript,但是它似乎缺乏从CGI参数或直接通过解析提供的URL来设置它的方法。我建议在owsrequest中添加以下方法:
loadParams();
从普通源(查询字符串env)加载参数。例如变量)。
loadParams( const char * url );
从给定的URL部分加载参数,如果获取请求方法,则会显示在查询字符串中。
IO挂钩¶
当前,mswmsgetCapabilities()等函数的输出是通过msio服务(在mapio.c中)定向的,例如msio_printf()。为了捕获这个输出并使其可用于进一步的处理,需要为mapscript应用程序提供一种方法来插入它们自己的某种类型的IO处理程序。
此外,当前的msio层有一个IO处理程序的概念,但它们对应用程序是全局的。对于Java、C等多线程环境中WXS MASPcript服务的非平凡使用,希望能够插入每个线程IO处理程序。
至少需要使当前的_stdin/stdout/stderr_上下文变量成为本地线程。可能使用与maperror.c相同的方法。为此需要一个新的互斥体。
是否考虑将线程安全输出到所有线程的共享stdin/stdout/stderr句柄?也就是说,用静音保护。
我们需要提供一种方便的方法来安装“to buffer”和“from buffer”IO处理程序。
我们需要始终使用msio重定向。目前在不使用fastcgi的默认情况下,在mapio.h和msio_printf()中没有定义use_mapio,类似的函数实际上只是定义为printf()。但是,如果我们希望能够一直为mapscript捕获输出,我们实际上总是需要msio层。因此,必须始终定义“使用地图”。
msIO_resetHandlers();
将msio处理程序重置为默认值(使用stdin、stdout、stderr)。
如果安装了缓冲处理程序,则清除缓冲区数据。
msIO_installStdoutToBuffer();
安装处理程序以将stdout发送到缓冲区,清除缓冲区。
msIO_installStdinFromBuffer();
安装处理程序以从缓冲区获取stdin,清除缓冲区。
msIO_setStdinBuffer( unsigned char *data, int length );
设置stdin缓冲区的数据。
gdBuffer msIO_getStdoutBufferBytes();
获取stdout缓冲区指针和长度。
gdbuffer已经提供了特定于语言的绑定来获取字节数据。
const char *msIO_getStdoutBufferString();
以字符串形式提取stdout缓冲区。例如,适用于XML和HTML结果。
安装的“缓冲区”处理程序将管理自己的缓冲区和当前读/写位置的概念。
我的目标是人们应该能够在python mapscript中做类似的事情。
mapscript.msIO_installStdoutToBuffer()
if map.OWSDispatch( req ) == mapscript.MS_SUCCESS:
result = mapscript.msIO_getStdoutBufferString()
mapscript.msIO_resetHandlers()
问题:
1)我们是否应该“推动”处理程序,而不是安装它们并丢失对前一个处理程序的跟踪?然后我们就可以把它们弹下来。
2)我们应该让整个msioContext对mapscript更可见吗?这似乎很复杂。
gd缓冲区¶
msio_getstdobufferbytes()返回gdbuffer,因为大多数语言绑定已经有一种方法将其用作“原始字节数组”缓冲区。它通常用于获取GDImage缓冲区。但是,由于msio函数返回的gdbuffer引用的是内部内存数组,而不是gdbuffer“拥有”的,因此我们需要添加一个owner_数据标志。
typedef struct {
unsigned char *data;
int size;
int owns_data;
} gdBuffer;
同样,如果owners_data为true,则每个语言绑定都需要修改为只对数据调用gdfree()。
此:
%typemap(out) gdBuffer {
$result = PyString_FromStringAndSize($1.data, $1.size);
gdFree($1.data);
}
变成这样:
%typemap(out) gdBuffer {
$result = PyString_FromStringAndSize($1.data, $1.size);
if( $1.owns_data )
gdFree($1.data);
}
其他绑定也是如此。
受影响的文件和对象¶
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)
向后兼容性问题¶
现有的mapscript脚本没有明显的向后兼容性问题。
实施问题¶
gdbuffer的内容可能应该是广义的。
一些mapscript语言缺少gdbuffer类型映射(即perl)。
应进行一些性能测试,以验证使用_Mapio不会显著降低正常操作的速度。当mapio.c静态实际上作为线程本地处理时,这是一个特殊的问题,因为每个msio调用都需要搜索适当的线程本地上下文。
msio“buffer”方法是基于将输出结果流式传输到内存缓冲区的情况进行预测的。对于非常大的返回结果,这可能会使用不合理的内存量。例如,带有250MB响应文档的WFS请求。但无论如何,这种结果在Web服务上下文中并不一定合理。
这组函数需要在PHP绑定中单独公开。
测试套件¶
msautotest/mspython和python单元测试将至少通过对其中一些服务的基本测试进行扩展。
因为我们没有其他mapscript语言的自动化测试,所以不会添加自动化测试,但是我将努力准备简单的脚本来测试东西。目前已经为python和perl-mapscript完成了这项工作。
例子¶
这显示了一个非常简单的python mapscript脚本,它调用通过普通CGI传递的传入owsrequest,但是在常规内容类型前面添加了一个文本/纯内容类型,这样我们就可以看到结果。脚本可以很容易地对URL参数和映射对象进行额外的操作。
例子::
#!/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:弗兰克,史蒂文。
开放性问题¶
没有