MS RFC 16:MapScript WXS服务

日期

2006/05/10

作者

弗兰克·沃默丹

联系

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、露比、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()

臭虫识别码

https://github.com/MapServer/MapServer/issues/1788

投票历史

+1:弗兰克,史蒂文。

开放性问题

没有