[mapserver-users] Designing a wrapper around mapserv which can be used with fcgi

Andy Colson andy at squeakycode.net
Wed Nov 4 09:38:52 EST 2009


> 
> Andy Colson wrote:
>>> Andy Colson wrote:
>>>> Adrian Popa wrote:
>>>>> Hello everyone,
>>>>>
>>>>> I am currently using a wrapper around mapserv which receives the 
>>>>> URL parameters, builds the map file (actually I only need to set 
>>>>> some filters in the map file, but the filters need to be built 
>>>>> after running some SQL queries with the passed in parameters). 
>>>>> After the map file is built, mapserv is called (as a shell script), 
>>>>> and the map gets sent to the user. Currently this wrapper is 
>>>>> written in perl - so it's not terribly fast as a cgi process.
>>>>>
>>>>> While this approach works, it is terribly inefficient. I would like 
>>>>> to use mapserv as a fcgi process (or something faster than plain 
>>>>> cgi). My question is - how can I /should I build a wrapper around 
>>>>> mapserv that can "customize" the MAP file on the fly and run as a 
>>>>> fcgi process?
>>>>>
>>>>> Any ideas on where I should start? An example of such a wrapper?
>>>>>
>>>>> Also, I suspect I can send parameters to mapserver and use some 
>>>>> sort of variables in the map file to set up my filters - but I 
>>>>> haven't seen an example. Can someone point me to such a documentation?
>>>>>
>>>>> Thanks,
>>>>> Adrian
>>>>
>>>> Have you seen mapscript?  You can use mapserver directly from perl.  
>>>> And perl can do fast-cgi.  Here is a little, ad-hoc, non-tested, 
>>>> perl fcgi:
>>>>
>>>>
>>>> #!/usr/bin/perl
>>>>
>>>> use strict;
>>>> use mapscript;
>>>> use FCGI;
>>>>
>>>>
>>>> my $request = FCGI::Request( );
>>>> while($request->Accept() >= 0)
>>>> {
>>>>         my($req, $x, $at, $xmap, $xpin, $sid, $y, $q);
>>>>
>>>>         $req = new mapscript::OWSRequest();
>>>>         $req->loadParams();
>>>>
>>>>         $xmap = $req->getValueByName('map');
>>>>         $xpin = $req->getValueByName('pin');
>>>>
>>>>         my $map = new mapscript::mapObj( "/maps/$xmap.map" );
>>>>         if (! $map)
>>>>         {
>>>>                 #print STDERR "----- Error loading map: $xmap.map\n";
>>>>                 print("Content-type: text/text\r\n\r\n");
>>>>                 print "cant load $xmap.map";
>>>>                 $request->Finish();
>>>>                 next;
>>>>         }
>>>>
>>>>         mapscript::msIO_installStdoutToBuffer();
>>>>
>>>>         $x = $map->OWSDispatch( $req );
>>>>         if ($x)
>>>>         {
>>>>                 print STDERR "OWSDispatch: $x\n";
>>>>                 my $errObj = new mapscript::errorObj();
>>>>                 while ($errObj) {
>>>>                         print STDERR "ERROR: 
>>>> $errObj->{code}:$errObj->{message}:$errObj->{routine} \n";
>>>>                         $errObj = $errObj->next();
>>>>                 }
>>>>         }
>>>>
>>>>         my $content_type = 
>>>> mapscript::msIO_stripStdoutBufferContentType();
>>>>
>>>>         $x = mapscript::msIO_getStdoutBufferBytes();
>>>>
>>>>
>>>>         print("Content-type: $content_type\r\n\r\n");
>>>>         if (mapscript::msGetVersionInt() >= 50500)
>>>>         {
>>>>                 print $$x;
>>>>         } else {
>>>>                 print $x;
>>>>         }
>>>>
>>>>         mapscript::msIO_resetHandlers();
>>>>         $request->Finish();
>>>> }
>>>>
>>>>
>>>>
>>>> I'd recommend using mapserver 5.6.0.
>>>>
>>>> -Andy
>>>>
>>>
>>
>> Adrian Popa wrote:
>> > Thank you,
>> >
>> > I will look into it. I guess through mapscript I can redefine the
>> > parameters that get sent to mapserver? Or do I rewrite the whole map?
>> >
>>
>>
>> You can load a map into memory (I assume you were already doing that). 
>> You said "..perl.. receives the URL parameters ...and... builds the 
>> map file".
>>
>>
>> I assume your perl does: use mapscript?
>>
>> and at some point: my $map = new mapscript::mapObj( "/maps/$xmap.map" );
>>
>> You kind of imbed mapserver into your perl script, and can call its 
>> functions and what not.  After you load the map you can do things to 
>> it, in memory.
>>
>> In my example above, I'm using the WMS features ($map->OWSDispatch), 
>> but you can also generate an image:
>>
>> my $img = $map->draw();
>> $img->save('x.jpg', $mapscript::MS_JPG);
>>
>> -Andy
>>
> 
> 

Adrian Popa wrote:
 > Thank you Andy for explaining.
 >
 > Actually my wrapper is very hard-core, meaning I don't use mapscript
 > (because I had to build it quickly and didn't have time to research
 > which was the best approach). Now I have more time and I'd like to tune
 > things up, so I will definitely start studying mapscript (If you have a
 > link to a good tutorial/function reference for it I am in your debt).
 >
 > My wrapper just copied over a template map file, edited it (rewrites
 > some filters) and then it set
 > $ENV{'QUERY_STRING'} = $ENV{'QUERY_STRING'}."&map=$file";
 >
 > ...and then called
 >
 > print `/var/www/cgi-bin/mapserv`;
 >
 >
 > It's barbaric, I know, but it worked for me. :)
 > It will take a bit of rewrite to add fcgi support and mapscript, but in
 > the long run it will be more mantainable... :)
 >
 > Thanks again,
 > Adrian

So are you using the template html stuff?  Humm... I've never used that 
stuff, not sure how it'll all translate.

For documentation, I used the mapscript reference:
http://mapserver.org/mapscript/mapscript.html

I found a few example perl scripts that helped with the syntax (my $c = 
new mapscript::colorObj(), $c->{blue} = 255;, etc...).  Other than that, 
I had more problems comming up with nice looking colors for my map, than 
actually writing the perl code.

-Andy


More information about the mapserver-users mailing list