Esempio n. 1
0
def mapserver_wms(map_name, layer_id, client_rev):
    wrapper = instances.get_or_create(map_name, layer_id)
    if wrapper is None:
        abort(404)
    # load in request parameters
    req = mapscript.OWSRequest()
    for (k, v) in request.args.iteritems():
        if k == 'LAYERS':
            v = ','.join((t.name for t in wrapper.layers))
        req.setParameter(k, v)
    # shared stdio buffer object thing; make sure that there's nothing left over
    # from an aborted request stuck in there
    mapscript.msIO_getStdoutBufferBytes()
    try:
        wrapper.instance.OWSDispatch(req)
        headers = {'Cache-Control': 'max-age=86400, public'}
    except mapscript.MapServerError:
        # don't cache errors
        headers = {}
    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    return Response(headers=headers,
                    response=content,
                    status=200,
                    content_type=content_type)
Esempio n. 2
0
def wms(request):
    import mapscript
    image = None
    for field in ['IMAGE', 'COVERAGE', 'image', 'coverage', 'id', 'ID']:
        if field in request.GET: image = request.GET[field] 
    try:
        image = int(image)
        obj = Map.objects.get(pk=image)
        filename = obj.warped
    except:
        filename = "%s" % image 
    filename = "%s/%s" % (settings.MAP_PATH, os.path.basename(filename))    
    ows = mapscript.OWSRequest()
    for k, v in request.GET.items():
        if k.lower() in ['image', 'coverage']: continue 
        ows.setParameter(k, v)
    ows.setParameter("LAYERS", "image")
    ows.setParameter("COVERAGE", "image")
    map = mapscript.mapObj('%s/wms.map' % settings.BASE_PATH)
    raster = mapscript.layerObj(map)
    raster.name = 'image'
    raster.type = mapscript.MS_LAYER_RASTER
    raster.data = filename 
    raster.status = mapscript.MS_DEFAULT
    raster.setProjection( "+init=epsg:4326" )
    raster.dump = mapscript.MS_TRUE
    raster.metadata.set("wcs_formats", "GEOTIFF JPEG2000")
    mapscript.msIO_installStdoutToBuffer()
    contents = map.OWSDispatch(ows)
    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    return HttpResponse(content, content_type = content_type)
Esempio n. 3
0
def application(env, start_response):
    for key in MAPSERV_ENV:
        if key in env:
            os.environ[key] = env[key]
        else:
            os.unsetenv(key)

    # Using a statically assigned mapfile:
    filename = os.path.join(settings_local['base_path'], 'test_mapfile.map')
    mapfile = mapscript.mapObj(filename)

    req = mapscript.OWSRequest()
    mapscript.msIO_installStdoutToBuffer()

    req.loadParamsFromURL(env['QUERY_STRING'])
    set_default_parameters(req)

    try:
        status = mapfile.OWSDispatch(req)
    except Exception as err:
        pass

    content_type = mapscript.msIO_stripStdoutBufferContentType()
    result = mapscript.msIO_getStdoutBufferBytes()
    start_response('200 OK', [('Content-type', content_type)])
    return [result]
Esempio n. 4
0
    def testWFSPostRequest(self):
        """OWSRequestTestCase.testLoadWMSRequest: OWS can POST a WFS request"""

        self.map.web.metadata.set("ows_onlineresource", "http://dummy.org/")
        request = mapscript.OWSRequest()
        request.contenttype = "application/xml"

        post_data = """<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" service="WFS"
        version="1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <wfs:Query typeName="*:POINT" xmlns:feature="http://www.openplans.org/topp">
            <ogc:Filter>
                <ogc:PropertyIsEqualTo>
                    <ogc:PropertyName>FID</ogc:PropertyName>
                    <ogc:Literal>1</ogc:Literal>
                </ogc:PropertyIsEqualTo>
            </ogc:Filter>
        </wfs:Query>
        </wfs:GetFeature>
        """

        qs = ""  # additional parameters can be passed via the querystring
        request.loadParamsFromPost(post_data, qs)
        mapscript.msIO_installStdoutToBuffer()
        status = self.map.OWSDispatch(request)
        assert status == mapscript.MS_SUCCESS, status

        mapscript.msIO_stripStdoutBufferContentHeaders()
        result = mapscript.msIO_getStdoutBufferBytes()
        dom = xml.dom.minidom.parseString(result)
        assert len(dom.getElementsByTagName('ms:POINT')) == 1
Esempio n. 5
0
def mapserver(params,mapfile):
    """ Function implementing mapserver functionality.
    
    params: dictionary of query string of a mapserver GET request
    mapfile: path to mapfile
    
    returns: tuple with content type and response body
    """
    helper.dbg("creating map for: " + mapfile)
    request = mapscript.OWSRequest()
    #request.loadParams()
    for k in params:
        #helper.dbg( "%s : %s" % (k,params[k]))
        request.setParameter(k,params[k])
    # change the style INSPIRE:DEFAULT back to an empty string otherwise Mapserver will complain
    styles = request.getValueByName('STYLES')
    if (styles is not None and styles.count(default_style) > 0):
        styles = styles.replace(default_style, "")
        request.setParameter("STYLES", styles)
    style = request.getValueByName('STYLE')
    if style == default_style:
        request.setParameter("STYLE", "") 
            
    map = mapscript.mapObj( mapfile )
    mapscript.msIO_installStdoutToBuffer()
    map.OWSDispatch( request )
    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    operation = request.getValueByName('REQUEST')
    version = request.getValueByName('VERSION')
    if (version == '1.3.0' or version is None) and operation.upper() == 'GETCAPABILITIES':
        content = altercapabilities(content, namespace, prefix, schemaLocation, language)
    #response = 'Content-type: %s\n%s' % (content_type,content)    
    return [content_type, content]
Esempio n. 6
0
def main(map_file):

    map = mapscript.mapObj(map_file)
    map.setMetaData("ows_onlineresource", "http://dummy.org/")
    ows_req = mapscript.OWSRequest()

    ows_req.type = mapscript.MS_GET_REQUEST

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

    mapscript.msIO_installStdoutToBuffer()
    dispatch_status = map.OWSDispatch(ows_req)

    if dispatch_status != mapscript.MS_SUCCESS:
        print("An error occurred")

    content_type = mapscript.msIO_stripStdoutBufferContentType()
    mapscript.msIO_stripStdoutBufferContentHeaders()
    result = mapscript.msIO_getStdoutBufferBytes()

    # [('Content-Type', 'application/vnd.ogc.wms_xml; charset=UTF-8'), ('Content-Length', '11385')]
    response_headers = [('Content-Type', content_type),
                        ('Content-Length', str(len(result)))]

    assert int(response_headers[1][1]) > 0

    dom = xml.dom.minidom.parseString(result)
    print(dom.toprettyxml(indent="", newl=""))
Esempio n. 7
0
def main(map_file):

    map = mapscript.mapObj(map_file)
    map.web.metadata.set("ows_onlineresource", "http://dummy.org/")
    ows_req = mapscript.OWSRequest()

    ows_req.type = mapscript.MS_GET_REQUEST

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

    mapscript.msIO_installStdoutToBuffer()
    dispatch_status = map.OWSDispatch(ows_req)

    if dispatch_status != mapscript.MS_SUCCESS:
        print("An error occurred")

    content_type = mapscript.msIO_stripStdoutBufferContentType()
    mapscript.msIO_stripStdoutBufferContentHeaders()
    result = mapscript.msIO_getStdoutBufferBytes()

    # [('Content-Type', 'application/vnd.ogc.wms_xml; charset=UTF-8'), ('Content-Length', '11385')]
    response_headers = [('Content-Type', content_type),
                        ('Content-Length', str(len(result)))]

    assert int(response_headers[1][1]) > 0

    dom = xml.dom.minidom.parseString(result)
    print(dom.toprettyxml(indent="", newl=""))
Esempio n. 8
0
def get_wms_response(query_string, base_url, out_format, layers):
    group = 'raster_layers'
    layer_names = []
    for layer in layers:
        name = layer.get('name')
        if name:
            layer_names.append(name)
    req = get_wms_request(query_string=query_string, layer_names=layer_names)
    src_map = get_map(base_url=base_url,
                      out_format=out_format,
                      layers=layers,
                      group=group)
    # raise ValueError(src_map.outputformat.imagemode, mapscript.MS_IMAGEMODE_INT16)
    mapscript.msIO_installStdoutToBuffer()
    try:
        src_map.OWSDispatch(req)
        error = False
    except mapscript.MapServerError:
        error = True
    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    mapscript.msIO_resetHandlers()

    # if content_type == 'vnd.ogc.se_xml':
    #     content_type = 'text/xml'
    return content, content_type, error
def application(env, start_response):
    print "-" * 30
    for key in MAPSERV_ENV:
        if key in env:
            os.environ[key] = env[key]
            print "{0}='{1}'".format(key, env[key])
        else:
            os.unsetenv(key)
    print "-" * 30

    #mapfile = '/home/oldbay/GIS/mapserver/basemaps/build/basemaps/osm-google-fix.map'
    #mapfile = 'temp_debug.map'
    #mapfile = mapscript.mapObj(mapfile)

    mapfile = initMap()

    request = mapscript.OWSRequest()
    mapscript.msIO_installStdoutToBuffer()
    request.loadParamsFromURL(env['QUERY_STRING'])

    try:
        status = mapfile.OWSDispatch(request)
    except Exception as err:
        pass

    content_type = mapscript.msIO_stripStdoutBufferContentType()
    result = mapscript.msIO_getStdoutBufferBytes()
    start_response('200 OK', [('Content-type', content_type)])
    return [result]
Esempio n. 10
0
def wms(request):
    import mapscript
    image = None
    for field in ['IMAGE', 'COVERAGE', 'image', 'coverage', 'id', 'ID']:
        if field in request.GET: image = request.GET[field]
    try:
        image = int(image)
        obj = Map.objects.get(pk=image)
        filename = obj.warped
    except:
        filename = "%s" % image
    filename = "%s/%s" % (settings.MAP_PATH, os.path.basename(filename))
    ows = mapscript.OWSRequest()
    for k, v in request.GET.items():
        if k.lower() in ['image', 'coverage']: continue
        ows.setParameter(k, v)
    ows.setParameter("LAYERS", "image")
    ows.setParameter("COVERAGE", "image")
    map = mapscript.mapObj('%s/wms.map' % settings.BASE_PATH)
    raster = mapscript.layerObj(map)
    raster.name = 'image'
    raster.type = mapscript.MS_LAYER_RASTER
    raster.data = filename
    raster.status = mapscript.MS_DEFAULT
    raster.setProjection("+init=epsg:4326")
    raster.dump = mapscript.MS_TRUE
    mapscript.msIO_installStdoutToBuffer()
    contents = map.OWSDispatch(ows)
    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    return HttpResponse(content, content_type=content_type)
Esempio n. 11
0
    def render(self):
        """ Render this map object

            This will inspect the OWS request type, and render the correct image
            for the request.

            Known supported OWS REQUEST values:

            * GetLegendGraphic: Will render the legend for the OWS request
            * GetMap: Will render the map tile for the OWS request
        """

        log = logging.getLogger(__name__)

        content = None          # the bytes of the rendered image
        content_type = None     # the image mimetype
        retval = None           # the OWS return value, useful for debugging

        with self.__class__.MAPSCRIPT_RLOCK:
            try:
                ows_request_type = self.ows_request.getValueByName('REQUEST')

                if (ows_request_type == 'GetLegendGraphic'):
                    # Draw the legend for the map
                    retval = self.loadOWSParameters(self.ows_request)
                    image = self.drawLegend()
                    content = image.getBytes()
                    content_type = image.format.mimetype
                elif (ows_request_type == 'GetMap'):
                    # Draw the map (tiles)
                    retval = self.loadOWSParameters(self.ows_request)
                    image = self.draw()
                    content = image.getBytes()
                    content_type = image.format.mimetype
                else:
                    # Unexpected OWS request. Do our best to support it by
                    # falling back to using the OWS Dispatch

                    # Tell mapscript to start capturing the stdout in a buffer
                    mapscript.msIO_installStdoutToBuffer()
                    # dispatch the OWS request
                    retval = self.OWSDispatch(self.ows_request)
                    # Get the content type of the return value
                    content_type = mapscript.msIO_stripStdoutBufferContentType()
                    # Get the content of the resulting image
                    content = mapscript.msIO_getStdoutBufferBytes()

                if retval != mapscript.MS_SUCCESS:
                    # Failed to render the desired image
                    raise RuntimeError("Failed to render map OWS request")

            except:
                log.error("Error while trying to render map: %s", sys.exc_info()[0])
                raise
            finally:
                # Reset the mapscript I/O pointers back to where they should be
                mapscript.msIO_resetHandlers()

        return content, content_type, retval
    def application(self, env, start_response):
        q_str = {
            my.split("=")[0].upper(): my.split("=")[1]
            for my in env['QUERY_STRING'].split('&') if "=" in my
        }
        serv_ver = [q_str.get('SERVICE', False), q_str.get('VERSION', False)]

        print "-" * 30
        for key in self.MAPSERV_ENV:
            if key in env:
                os.environ[key] = env[key]
                print "{0}='{1}'".format(key, env[key])
            else:
                os.unsetenv(key)
        print "QUERY_STRING=("
        for key in q_str:
            print "    {0}={1},".format(key, q_str[key])
        print ")"
        print "-" * 30

        request = mapscript.OWSRequest()
        mapscript.msIO_installStdoutToBuffer()
        request.loadParamsFromURL(env['QUERY_STRING'])
        rec_obj = self.mapscript_obj.clone()

        try:
            status_id = rec_obj.OWSDispatch(request)
        except Exception as err:
            print "OWSDispatch Error: {}".format(err)
            err_def = unicode(err).split(':')[0]
            status_id = None

        content_type = mapscript.msIO_stripStdoutBufferContentType()
        result = mapscript.msIO_getStdoutBufferBytes()
        mapscript.msIO_resetHandlers()

        # status:
        if status_id == mapscript.MS_SUCCESS:
            status = '200 OK'
        elif status_id == mapscript.MS_FAILURE:
            status = '400 Bad request'
            if serv_ver == ['WFS', '2.0.0']:
                result = '\n'.join(result.split('\n')[2:])
        elif status_id is None:
            if serv_ver[0] == "WMS" and err_def == "msPostGISLayerGetExtent()":
                status = '200 OK'
            elif serv_ver == ['WFS', '1.0.0'
                              ] and err_def == "msWFSGetFeature()":
                status = '400 Bad request'
            else:
                status = '500 Server Error'

        start_response(status, [('Content-type', str(content_type))])
        return [result]
Esempio n. 13
0
 def request_mapscript(self, env, mapdata, que=None):
     """
     render on mapserver mapscript request
     """
     q_str = {
         my.split("=")[0].upper(): my.split("=")[1]
         for my 
         in env['QUERY_STRING'].split('&')
         if "=" in my
     }
     serv_ver = [q_str.get('SERVICE', False), q_str.get('VERSION', False)]
     request = mapscript.OWSRequest()
     mapscript.msIO_installStdoutToBuffer()
     request.loadParamsFromURL(env['QUERY_STRING'])
     rec_obj = mapdata.clone()
 
     try:
         status_id = rec_obj.OWSDispatch(request)
     except Exception as err:
         print "OWSDispatch Error: {}".format(err)
         err_def = unicode(err).split(':')[0]
         status_id = None
 
     content_type = mapscript.msIO_stripStdoutBufferContentType()
     content = mapscript.msIO_getStdoutBufferBytes()
     mapscript.msIO_resetHandlers()
     
     # status:
     if status_id == mapscript.MS_SUCCESS:
         status = 200
     elif status_id == mapscript.MS_FAILURE:
         status = 400
         if serv_ver == ['WFS', '2.0.0']:
             content = '\n'.join(content.split('\n')[2:])
     elif status_id is None:
         if serv_ver[0] == "WMS" and err_def == "msPostGISLayerGetExtent()":
             status = 200
         elif serv_ver == ['WFS', '1.0.0'] and err_def == "msWFSGetFeature()":
             status = 400
         else:
             status = 500
     else:
         status = 500
     
     out_response = (
         status, 
         content_type, 
         content
     )
     if que is None:
         return out_response
     else:
         que.put(out_response)
Esempio n. 14
0
def mapserver_wms(map_name, layer_id, client_rev):
    wrapper = instances.get_or_create(map_name, layer_id)
    if wrapper is None:
        abort(404)
    # load in request parameters
    req = mapscript.OWSRequest()
    for (k, v) in request.args.iteritems():
        if k == 'LAYERS':
            v = ','.join((t.name for t in wrapper.layers))
        req.setParameter(k, v)
    # shared stdio buffer object thing; make sure that there's nothing left over
    # from an aborted request stuck in there
    mapscript.msIO_getStdoutBufferBytes()
    try:
        wrapper.instance.OWSDispatch(req)
        headers = {'Cache-Control' : 'max-age=86400, public'}
    except mapscript.MapServerError:
        # don't cache errors
        headers = {}
    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    return Response(headers=headers, response=content, status=200, content_type=content_type)
Esempio n. 15
0
    def ows_req(self):
        # http://mapserver.org/ogc/mapscript.html#python-examples
        ows_req = mapscript.OWSRequest()
        ows_req.loadParams()
        req_str = ows_req.getValueByName("REQUEST")
        styles = ows_req.getValueByName("STYLES")

        do_heatmap = styles and styles.startswith("heat")

        # Filter out "graphic" WMS requests
        if req_str == "GetMap" and do_heatmap:
            self.wms_getheatmap_req(ows_req)
            return
        elif req_str == "GetLegendGraphic":
            # GetLegendGraphic may have a optional STYLE parameter
            # if this indicates a heatmap style defer to our own implementation
            # to return heatmap gradient image as style for now.
            style = ows_req.getValueByName("STYLE")
            if style and style.startswith("heat"):
                self.wms_getheatmaplegend_req(ows_req)
                return

        # All other OWS (WFS/WMS-non-graphic) are XML-based
        # and can be dispatched/returned directly
        ows_req.setParameter("STYLES", "")
        mapscript.msIO_installStdoutToBuffer()
        self.map.OWSDispatch(ows_req)

        if req_str == "GetMap":
            content = mapscript.msIO_getStdoutBufferBytes()
        else:
            content_type = mapscript.msIO_stripStdoutBufferContentType()
            content = mapscript.msIO_getStdoutBufferString()

            if (
                content_type == "vnd.ogc.se_xml"
                or content_type == "application/vnd.ogc.wms_xml"
                or content_type == "application/vnd.ogc.gml"
            ):
                content_type = "text/xml"

            print("Content-type: " + content_type)
            print

        print(content)
def wxs():
    import mapscript
    import os
    path_map = os.path.join(request.folder, 'private', request.args(0))
    if not request.vars:
        return ''
    req = mapscript.OWSRequest()
    for v in request.vars:
        req.setParameter(v, request.vars[v])

    map = mapscript.mapObj(path_map)
    mapscript.msIO_installStdoutToBuffer()
    map.OWSDispatch(req)

    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    response.header = "Content-Type","%s; charset=utf-8"%content_type
    return content
def wxs():
    import mapscript
    import os
    path_map = os.path.join(request.folder, 'private', request.args(0))
    if not request.vars:
        return ''
    req = mapscript.OWSRequest()
    for v in request.vars:
        req.setParameter(v, request.vars[v])

    map = mapscript.mapObj(path_map)
    mapscript.msIO_installStdoutToBuffer()
    map.OWSDispatch(req)

    content_type = mapscript.msIO_stripStdoutBufferContentType()
    content = mapscript.msIO_getStdoutBufferBytes()
    response.header = "Content-Type", "%s; charset=utf-8" % content_type
    return content
Esempio n. 18
0
    def request_mapscript(self, env, mapdata, que=None):
        """
        render on mapserver mapscript request
        """
        request = mapscript.OWSRequest()
        mapscript.msIO_installStdoutToBuffer()
        request.loadParamsFromURL(env['QUERY_STRING'])

        try:
            status = mapdata.OWSDispatch(request)
        except Exception as err:
            pass

        content_type = mapscript.msIO_stripStdoutBufferContentType()
        result = mapscript.msIO_getStdoutBufferBytes()
        out_req = (content_type, result)
        if que is None:
            return out_req
        else:
            que.put(out_req)
Esempio n. 19
0
def application(environ, start_response):
    try:
        req = mapscript.OWSRequest()
        req.loadParamsFromURL(environ.get('QUERY_STRING'))

        map = mapscript.mapObj(args.map_file)

        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'

        start_response('200 Ok', [('Content-type', content_type)])
        return [content]

    except:
        start_response('500 Ooops', [('Content-type', 'text/plain')])
        return ['An error occured\n' + mapscript.msIO_getStdoutBufferString()]
Esempio n. 20
0
def test_msIO_getAndStripStdoutBufferMimeHeaders():

    if 'INPUT=GDAL' not in mapscript.msGetVersion():
        return 'skip'
    if 'SUPPORTS=WMS' not in mapscript.msGetVersion():
        return 'skip'

    map = mapscript.mapObj('test_mapio.map')
    request = mapscript.OWSRequest()
    mapscript.msIO_installStdoutToBuffer()
    request.loadParamsFromURL(
        'service=WMS&version=1.1.1&request=GetMap&layers=grey&srs=EPSG:4326&bbox=-180,-90,180,90&format=image/png&width=80&height=40'
    )
    status = map.OWSDispatch(request)
    if status != 0:
        pmstestlib.post_reason('wrong OWSDispatch status')
        return 'fail'
    headers = mapscript.msIO_getAndStripStdoutBufferMimeHeaders()
    if headers is None:
        pmstestlib.post_reason('headers is None')
        return 'fail'
    if 'Content-Type' not in headers or headers['Content-Type'] != 'image/png':
        pmstestlib.post_reason('wrong Content-Type')
        print(headers)
        return 'fail'
    if 'Cache-Control' not in headers or headers[
            'Cache-Control'] != 'max-age=86400':
        pmstestlib.post_reason('wrong Cache-Control')
        print(headers)
        return 'fail'

    result = mapscript.msIO_getStdoutBufferBytes()
    if result is None or result[1:4] != b'PNG':
        pmstestlib.post_reason('wrong data')
        return 'fail'

    return 'success'
Esempio n. 21
0
    def application(self, env, start_response):
        print "-" * 30
        for key in self.MAPSERV_ENV:
            if key in env:
                os.environ[key] = env[key]
                print "{0}='{1}'".format(key, env[key])
            else:
                os.unsetenv(key)
        print "-" * 30

        mapfile = self.get_mapobj()
        request = mapscript.OWSRequest()
        mapscript.msIO_installStdoutToBuffer()
        request.loadParamsFromURL(env['QUERY_STRING'])

        try:
            status = mapfile.OWSDispatch(request)
        except Exception as err:
            pass

        content_type = mapscript.msIO_stripStdoutBufferContentType()
        result = mapscript.msIO_getStdoutBufferBytes()
        start_response('200 OK', [('Content-type', content_type)])
        return [result]
Esempio n. 22
0
def process_request(django_request, map_obj):
    """Offload the processing of the OWS request to MapServer.

    :arg django_request: the request parameters
    :type django_request: HttpRequest
    :arg map_obj: the in-memory mapfile to use
    :type map_obj: mapscript.mapObj
    :return: the mapserver buffer with the output from processing the request
    """

    if django_request.method == 'GET':
        params = django_request.GET
    elif django_request.method == 'POST':
        # get the params from the XML body of the request
        raise Exception
    # build the WMS request
    wms_req = mapscript.OWSRequest()
    for k, v in params.items():
        wms_req.setParameter(k, v)

    # install a mapserver IO handler directing future stdout to a memory buffer
    output_buffer = mapscript.msIO_installStdoutToBuffer()

    # dispatch the request to mapserver
    map_obj.OWSDispatch(wms_req)

    # get back mapserver's response
    # ms_headers = mapscript.msIO_stripStdoutBufferContentHeaders()
    ms_content_type = mapscript.msIO_stripStdoutBufferContentType()
    ms_content = mapscript.msIO_getStdoutBufferBytes()
    if ms_content == 'application/vnd.ogc.se_xml':
        ms_content = 'Content-Type: text/xml\n\n{}'.format(ms_content)

    # reset the stdin/stdout handlers
    mapscript.msIO_resetHandlers()
    return ms_content, ms_content_type
Esempio n. 23
0
    def render(self):
        """ Render this map object

            This will inspect the OWS request type, and render the correct image
            for the request.

            Known supported OWS REQUEST values:

            * GetLegendGraphic: Will render the legend for the OWS request
            * GetMap: Will render the map tile for the OWS request
        """

        log = logging.getLogger(__name__)

        content = None  # the bytes of the rendered image
        content_type = None  # the image mimetype
        retval = None  # the OWS return value, useful for debugging

        # TODO: do I need alock here?
        # with LockFile(self.data_file_path + '.lock'):
        if True:
            try:
                ows_request_type = self.ows_request.getValueByName('REQUEST')

                if (ows_request_type == 'GetLegendGraphic'):
                    # Draw the legend for the map
                    retval = self.loadOWSParameters(self.ows_request)
                    image = self.drawLegend()
                    content = image.getBytes()
                    content_type = image.format.mimetype
                elif (ows_request_type == 'GetMap'):
                    # Draw the map (tiles)
                    retval = self.loadOWSParameters(self.ows_request)
                    image = self.draw()
                    content = image.getBytes()
                    content_type = image.format.mimetype
                else:
                    # Unexpected OWS request. Do our best to support it by
                    # falling back to using the OWS Dispatch

                    # Tell mapscript to start capturing the stdout in a buffer
                    mapscript.msIO_installStdoutToBuffer()
                    # dispatch the OWS request
                    retval = self.OWSDispatch(self.ows_request)
                    # Get the content type of the return value
                    content_type = mapscript.msIO_stripStdoutBufferContentType(
                    )
                    # Get the content of the resulting image
                    content = mapscript.msIO_getStdoutBufferBytes()

                if retval != mapscript.MS_SUCCESS:
                    # Failed to render the desired image
                    raise RuntimeError("Failed to render map OWS request")

            except:
                log.error("Error while trying to render map: %s",
                          sys.exc_info()[0])
                raise
            finally:
                # Reset the mapscript I/O pointers back to where they should be
                mapscript.msIO_resetHandlers()

        return content, content_type, retval
Esempio n. 24
0
    def get(self, request, *args, **kwargs):
        """
        Html GET method of WmsView. This view renders WMS requests into
        corresponding responses using the attached WmsMap class.
        Responses are mainly images and xml files.
        """
        # Create response
        response = HttpResponse()

        # Setup wms request object
        ows_request = mapscript.OWSRequest()

        # If tile kwargs were provided, add tile parameters to request
        tileparams = self.tilemode()

        if tileparams:
            # Get image format from url
            format = {
                '.png': 'image/png',
                '.jpg': 'image/jpeg'
            }[self.kwargs.get('format')]

            # Return empty image if tile cant be found
            if not self.tile_exists(*tileparams):
                # Get image type and size
                imagetype = 'PNG' if format == 'image/png' else 'JPEG'
                imagesize = 256, 256
                response['Content-Type'] = format

                # Create image and save it to response
                im = Image.new("RGBA", imagesize, (0, 0, 0, 0))
                im.save(response, imagetype)

                return response
            else:
                tilebounds = self.get_tile_bounds(*tileparams)

                # Get layer name
                layers = self.kwargs.get('layers')

                # Setup wms parameter object
                request_data = {
                    'SERVICE': 'WMS',
                    'REQUEST': 'GetMap',
                    'VERSION': '1.1.1',
                    'TRANSPARENT': 'true',
                    'HEIGHT': '256',
                    'WIDTH': '256',
                    'SRS': 'EPSG:3857',
                    'FORMAT': format,
                    'LAYERS': layers,
                    'BBOX': tilebounds,
                }

                request.GET = dict(request.GET.items() + request_data.items())

        # Set ows parameters from request data
        for param, value in request.GET.items():
            ows_request.setParameter(param, value)

        # Instantiate WmsMap class
        self.wmsmap = self.map_class(request, **kwargs)

        # Dynamically use host for declaring service endpoint
        onlineresource = request.build_absolute_uri().split('?')[0] + '?'
        self.wmsmap.map_object.setMetaData('wms_onlineresource',
                                           onlineresource)

        # Dispatch map rendering
        self.wmsmap.map_object.OWSDispatch(ows_request)

        # Strip buffer from headers
        mapscript.msIO_stripStdoutBufferContentHeaders()

        # Store contenttype
        contenttype = mapscript.msIO_stripStdoutBufferContentType()

        # Write data to response
        response.write(mapscript.msIO_getStdoutBufferBytes())

        # Set contenttype
        response['Content-Type'] = contenttype

        return response
    def test_get_productlayer(self):
        #import StringIO
        import mapscript
        # getparams = web.input()

        #getparams = {'STYLES': u'', 'productcode': u'vgt-ndvi', 'legendid': u'7', 'SERVICE': u'WMS', 'subproductcode': u'ndv', 'CRS': u'EPSG:4326', 'FORMAT': u'image/png', 'REQUEST': u'GetMap', 'HEIGHT': u'1010', 'WIDTH': u'998', 'VERSION': u'1.3.0', 'productversion': u'sv2-pv2.1', 'date': u'20130221', 'mapsetcode': u'SPOTV-Africa-1km', 'TRANSPARENT': u'false', 'BBOX': u'-16.17,16.17,-15.47,16.87'}
        getparams = {'STYLES': u'',
                     'productcode': u'vgt-fapar',
                     'legendid': u'99',
                     'SERVICE': u'WMS',
                     'subproductcode': u'fapar',
                     'CRS': u'EPSG:4326',
                     'FORMAT': u'image/png',
                     'REQUEST': u'GetMap',
                     'HEIGHT': u'1010',
                     'WIDTH': u'998',
                     'VERSION': u'1.3.0',
                     'productversion': u'V1.4',
                     'date': u'20130221',
                     'mapsetcode': u'SPOTV-Africa-1km',
                     'TRANSPARENT': u'false',
                     'BBOX': u'15.46875, -17.578125, 16.171875, -16.875'}

        #getparams = {'STYLES': u'', 'productcode': u'vgt-ndvi', 'legendid': u'7', 'SERVICE': u'WMS', 'subproductcode': u'ndv', 'CRS': u'EPSG:4326', 'FORMAT': u'image/png', 'REQUEST': u'GetMap', 'HEIGHT': u'1091', 'WIDTH': u'998', 'VERSION': u'1.3.0', 'productversion': u'sv2-pv2.1', 'date': u'20130221', 'mapsetcode': u'SPOTV-Africa-1km', 'TRANSPARENT': u'false', 'BBOX': u'-25.70957541665903,9.276714800828785,-13.723491432284028,20.021343707078785'}
        # getparams = [
        #     SERVICE:'WMS',
        #     VERSION='1.3.0',
        #     REQUEST='GetMap',
        #     FORMAT='image/png',
        #     TRANSPARENT='false',
        #     productcode='vgt-ndvi',
        #     productversion='sv2-pv2.1',
        #     subproductcode='ndv',
        #     mapsetcode='SPOTV-Africa-1km',
        #     legendid='7',
        #     date='20130221',
        #     CRS='EPSG:4326'',
        #     STYLES=''
        #     WIDTH='998',
        #     HEIGHT='1010',
        #     BBOX='-26,-35,60,38'
        # ]
        p = Product(product_code=getparams['productcode'], version=getparams['productversion'])
        dataset = p.get_dataset(mapset=getparams['mapsetcode'], sub_product_code=getparams['subproductcode'])
        # print dataset.fullpath

        if hasattr(getparams, "date"):
            filedate = getparams['date']
        else:
            dataset.get_filenames()
            lastdate = dataset.get_dates()[-1].strftime("%Y%m%d")
            filedate = lastdate

        if dataset.no_year():
            filedate=dataset.strip_year(filedate)
        # lastdate = lastdate.replace("-", "")
        # mydate=lastdate.strftime("%Y%m%d")

        filename = functions.set_path_filename(filedate,
                                               getparams['productcode'],
                                               getparams['subproductcode'],
                                               getparams['mapsetcode'],
                                               getparams['productversion'],
                                               '.tif')
        productfile = dataset.fullpath + filename
        # print productfile

        #web.header('Content-type', 'image/png')
        #web.header('Content-transfer-encoding', 'binary')
        #buf = StringIO.StringIO()
        #mapscript.msIO_installStdoutToBuffer()
        #map = mapserver.getmap()
        ##map.save to a file fname.png
        ##web.header('Content-Disposition', 'attachment; filename="fname.png"')
        #contents = buf.getvalue()
        #return contents

        #logger.debug("MapServer: Installing stdout to buffer.")
        mapscript.msIO_installStdoutToBuffer()

        # projlib = "/usr/share/proj/"
        projlib = es_constants.proj4_lib_dir
        # errorfile = es_constants.apps_dir+"/analysis/ms_tmp/ms_errors.log"
        errorfile = es_constants.log_dir+"/mapserver_error.log"
        # imagepath = es_constants.apps_dir+"/analysis/ms_tmp/"

        owsrequest = mapscript.OWSRequest()

        inputparams = getparams # web.input()
        for k, v in inputparams.iteritems():
            print k + ':' + v
            owsrequest.setParameter(k.upper(), v)

        # print owsrequest

        filenamenoextention = functions.set_path_filename(filedate,
                                               getparams['productcode'],
                                               getparams['subproductcode'],
                                               getparams['mapsetcode'],
                                               getparams['productversion'],
                                               '')
        owsrequest.setParameter("LAYERS", filenamenoextention)

        productmap = mapscript.mapObj(es_constants.template_mapfile)
        productmap.setConfigOption("PROJ_LIB", projlib)
        productmap.setConfigOption("MS_ERRORFILE", errorfile)
        productmap.maxsize = 4096

        outputformat_png = mapscript.outputFormatObj('GD/PNG', 'png')
        outputformat_png.setOption("INTERLACE", "OFF")
        productmap.appendOutputFormat(outputformat_png)
        #outputformat_gd = mapscript.outputFormatObj('GD/GIF', 'gif')
        #productmap.appendOutputFormat(outputformat_gd)
        productmap.selectOutputFormat('png')
        productmap.debug = mapscript.MS_TRUE
        productmap.status = mapscript.MS_ON
        productmap.units = mapscript.MS_DD

        coords = map(float, inputparams['BBOX'].split(","))
        print coords
        llx = coords[0]
        lly = coords[1]
        urx = coords[2]
        ury = coords[3]
        print llx, lly, urx, ury

        productmap.setExtent(llx, lly, urx, ury)   # -26, -35, 60, 38
        # productmap.setExtent(-26, -35, 60, 38)

        # epsg must be in lowercase because in unix/linux systems the proj filenames are lowercase!
        # epsg = "+init=epsg:3857"
        # epsg = "+init=" + inputparams.CRS.lower()   # CRS = "EPSG:4326"
        epsg = inputparams['CRS'].lower()   # CRS = "EPSG:4326"
        productmap.setProjection(epsg)

        w = int(inputparams['WIDTH'])
        h = int(inputparams['HEIGHT'])
        productmap.setSize(w, h)

        # General web service information
        productmap.setMetaData("WMS_TITLE", "Product description")
        productmap.setMetaData("WMS_SRS", inputparams['CRS'].lower())
        # productmap.setMetaData("WMS_SRS", "epsg:3857")
        productmap.setMetaData("WMS_ABSTRACT", "A Web Map Service returning eStation2 raster layers.")
        productmap.setMetaData("WMS_ENABLE_REQUEST", "*")   # necessary!!

        product_info = querydb.get_product_out_info(productcode=inputparams['productcode'],
                                                    subproductcode=inputparams['subproductcode'],
                                                    version=inputparams['productversion'])
        if hasattr(product_info, "__len__") and product_info.__len__() > 0:
            for row in product_info:
                scale_factor = row.scale_factor
                scale_offset = row.scale_offset
                nodata = row.nodata

        legend_info = querydb.get_legend_info(legendid=inputparams['legendid'])
        if hasattr(legend_info, "__len__") and legend_info.__len__() > 0:
            for row in legend_info:
                minstep = int((row.min_value - scale_offset)/scale_factor)    #int(row.min_value*scale_factor+scale_offset)
                maxstep = int((row.max_value - scale_offset)/scale_factor)    # int(row.max_value*scale_factor+scale_offset)
                realminstep = int((row.realminstep - scale_offset)/scale_factor)
                realmaxstep = int((row.realmaxstep - scale_offset)/scale_factor)
                minstepwidth = int((row.minstepwidth - scale_offset)/scale_factor)
                maxstepwidth = int((row.maxstepwidth - scale_offset)/scale_factor)
                totwidth = int((row.totwidth - scale_offset)/scale_factor)
                totsteps = row.totsteps

            # maxstep = 255
            processing_scale = 'SCALE='+str(minstep)+','+str(maxstep)  # min(legend_step.from_step) max(legend_step.to_step) example: 'SCALE=-7000,10000'

            minbuckets = 256
            maxbuckets = 10000
            num_buckets = maxbuckets
            if minstepwidth > 0:
                num_buckets = round(totwidth / minstepwidth, 0)

            if num_buckets < minbuckets:
                num_buckets = minbuckets
            elif num_buckets > maxbuckets:
                num_buckets = 0

            # num_buckets = 10000
            if num_buckets > 0:
                processing_buckets = 'SCALE_BUCKETS='+str(num_buckets)

            # nodata = -32768     # get this value from the table products.product
            processing_novalue = ''
            if nodata is not None and minstep <= nodata < maxstep:
                processing_novalue = 'NODATA='+str(nodata)

            layer = mapscript.layerObj(productmap)
            layer.name = filenamenoextention
            layer.type = mapscript.MS_LAYER_RASTER
            layer.status = mapscript.MS_ON     # MS_DEFAULT
            layer.data = productfile
            # layer.setProjection("+init=epsg:4326")
            layer.setProjection("epsg:4326")
            layer.dump = mapscript.MS_TRUE

            # scale & buckets
            if num_buckets > 0:
                layer.setProcessing(processing_scale)
                layer.setProcessing(processing_buckets)

            if processing_novalue != '':
                layer.setProcessing(processing_novalue)

            legend_steps = querydb.get_legend_steps(legendid=inputparams['legendid'])
            if hasattr(legend_steps, "__len__") and legend_steps.__len__() > 0:
                stepcount = 0
                for step in legend_steps:
                    stepcount += 1
                    min_step = int((step.from_step - scale_offset)/scale_factor)
                    max_step = int((step.to_step - scale_offset)/scale_factor)
                    colors = map(int, (color.strip() for color in step.color_rgb.split(" ") if color.strip()))

                    if stepcount == legend_steps.__len__():    # For the last step use <= max_step
                        expression_string = '([pixel] >= '+str(min_step)+' and [pixel] <= '+str(max_step)+')'
                    else:
                        expression_string = '([pixel] >= '+str(min_step)+' and [pixel] < '+str(max_step)+')'
                    # define class object and style
                    layerclass = mapscript.classObj(layer)
                    layerclass.name = layer.name+'_'+str(stepcount)
                    layerclass.setExpression(expression_string)
                    style = mapscript.styleObj(layerclass)
                    style.color.setRGB(colors[0], colors[1], colors[2])

        result_map_file = es_constants.apps_dir+'/analysis/MAP_result.map'
        # if os.path.isfile(result_map_file):
        #     os.remove(result_map_file)
        productmap.save(result_map_file)
        image = productmap.draw()
        image.save(es_constants.apps_dir+'/analysis/'+filenamenoextention+'.png')

        contents = productmap.OWSDispatch(owsrequest)
        content_type = mapscript.msIO_stripStdoutBufferContentType()
        content = mapscript.msIO_getStdoutBufferBytes()
        #web.header = "Content-Type","%s; charset=utf-8"%content_type
        # web.header('Content-type', 'image/png')
        #web.header('Content-transfer-encoding', 'binary')
        # return content

        self.assertEquals(True, True)
Esempio n. 26
0
map = mapscript.mapObj('../../tests/test.map')
map.setMetaData( "ows_onlineresource", "http://dummy.org/" )
ows_req = mapscript.OWSRequest()

ows_req.type = mapscript.MS_GET_REQUEST

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

mapscript.msIO_installStdoutToBuffer()
dispatch_status = map.OWSDispatch(ows_req)
if dispatch_status:
    status = '200 OK'
else:
    status = '500 Internal Server Error'
content_type = mapscript.msIO_stripStdoutBufferContentType()
mapscript.msIO_stripStdoutBufferContentHeaders()
result = mapscript.msIO_getStdoutBufferBytes()

try:
    # MapServer 6.0:
    mapscript.msCleanup()
except:
    # MapServer 6.1:
    mapscript.msCleanup(1)

response_headers = [('Content-Type', content_type),
                    ('Content-Length', str(len(result)))]
Esempio n. 27
0
def airspace_image(cache_key, as_id):
    if not mapscript_available:
        abort(404)

    # get information from cache...
    infringements = current_app.cache.get('upload_airspace_infringements_' + cache_key)
    flight_path = current_app.cache.get('upload_airspace_flight_path_' + cache_key)

    # abort if invalid cache key
    if not infringements \
       or not flight_path:
        abort(404)

    # Convert the coordinate into a list of tuples
    coordinates = [(c.location['longitude'], c.location['latitude']) for c in flight_path]
    # Create a shapely LineString object from the coordinates
    linestring = LineString(coordinates)
    # Save the new path as WKB
    locations = from_shape(linestring, srid=4326)

    highlight_locations = []
    extent_epsg4326 = [180, 85.05112878, -180, -85.05112878]

    for period in infringements[as_id]:
        # Convert the coordinate into a list of tuples
        coordinates = [(c['location']['longitude'], c['location']['latitude']) for c in period]

        # Create a shapely LineString object from the coordinates
        if len(coordinates) == 1:
            # a LineString must contain at least two points...
            linestring = LineString([coordinates[0], coordinates[0]])
        else:
            linestring = LineString(coordinates)

        highlight_locations.append(linestring)

        # gather extent
        (minx, miny, maxx, maxy) = linestring.bounds

        extent_epsg4326[0] = min(extent_epsg4326[0], minx)
        extent_epsg4326[1] = min(extent_epsg4326[1], miny)
        extent_epsg4326[2] = max(extent_epsg4326[2], maxx)
        extent_epsg4326[3] = max(extent_epsg4326[3], maxy)

    # Save the new path as WKB
    highlight_multilinestring = from_shape(MultiLineString(highlight_locations), srid=4326)

    # increase extent by factor 1.05
    width = abs(extent_epsg4326[0] - extent_epsg4326[2])
    height = abs(extent_epsg4326[1] - extent_epsg4326[3])

    center_x = (extent_epsg4326[0] + extent_epsg4326[2]) / 2
    center_y = (extent_epsg4326[1] + extent_epsg4326[3]) / 2

    extent_epsg4326[0] = center_x - width / 2 * 1.05
    extent_epsg4326[1] = center_y - height / 2 * 1.05
    extent_epsg4326[2] = center_x + width / 2 * 1.05
    extent_epsg4326[3] = center_y + height / 2 * 1.05

    # minimum extent should be 0.3 deg
    width = abs(extent_epsg4326[0] - extent_epsg4326[2])
    height = abs(extent_epsg4326[1] - extent_epsg4326[3])

    if width < 0.3:
        extent_epsg4326[0] = center_x - 0.15
        extent_epsg4326[2] = center_x + 0.15

    if height < 0.3:
        extent_epsg4326[1] = center_y - 0.15
        extent_epsg4326[3] = center_y + 0.15

    # convert extent from EPSG4326 to EPSG3857
    epsg4326 = pyproj.Proj(init='epsg:4326')
    epsg3857 = pyproj.Proj(init='epsg:3857')

    x1, y1 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[0], extent_epsg4326[1])
    x2, y2 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[2], extent_epsg4326[3])

    extent_epsg3857 = [x1, y1, x2, y2]

    # load basemap and set size + extent
    basemap_path = os.path.join(current_app.config.get('SKYLINES_MAPSERVER_PATH'), 'basemap.map')
    map_object = mapscript.mapObj(basemap_path)
    map_object.setSize(400, 400)
    map_object.setExtent(extent_epsg3857[0], extent_epsg3857[1], extent_epsg3857[2], extent_epsg3857[3])

    # enable airspace and airports layers
    num_layers = map_object.numlayers
    for i in range(num_layers):
        layer = map_object.getLayer(i)

        if layer.group == 'Airports':
            layer.status = mapscript.MS_ON

        if layer.group == 'Airspace':
            layer.status = mapscript.MS_ON

    # get flights layer
    flights_layer = map_object.getLayerByName('Flights')
    highlight_layer = map_object.getLayerByName('Flights_Highlight')

    # set sql query for blue flight
    one = literal_column('1 as flight_id')
    flight_query = db.session.query(locations.label('flight_geometry'), one)

    flights_layer.data = 'flight_geometry FROM (' + query_to_sql(flight_query) + ')' + \
                         ' AS foo USING UNIQUE flight_id USING SRID=4326'

    # set sql query for highlighted linestrings
    highlighted_query = db.session.query(highlight_multilinestring.label('flight_geometry'), one)

    highlight_layer.data = 'flight_geometry FROM (' + query_to_sql(highlighted_query) + ')' + \
                           ' AS foo USING UNIQUE flight_id USING SRID=4326'

    highlight_layer.status = mapscript.MS_ON

    # get osm layer and set WMS url
    osm_layer = map_object.getLayerByName('OSM')
    osm_layer.connection = current_app.config.get('SKYLINES_MAP_TILE_URL') + \
        '/service?'

    # draw map
    map_image = map_object.draw()

    # get image
    mapscript.msIO_installStdoutToBuffer()
    map_image.write()
    content = mapscript.msIO_getStdoutBufferBytes()

    # return to client
    resp = make_response(content)
    resp.headers['Content-type'] = map_image.format.mimetype
    return resp
Esempio n. 28
0
    def wfs(self):
        """This is a WFS endpoint.

        It uses mapserver mapscript to process a WFS request.

        This endpoint requires an additional WFS parameter
        DATA_URL. The DATA_URL, should point to a downloadable file
        which can be used as raster data input for mapserver.
        """
        LOG.debug("Processing ows request")

        data_url = None
        try:
            data_url = self.request.GET.getone("DATA_URL")
        except:
            LOG.warn("No data_url provided")
            data_url = None

        # get location of local data file
        # FIXME: May not be required if data is from DB
        if data_url:
            loc = fetch_file(self.request, data_url)

        # get map
        map = self._get_map()

        # Check that appropriate files are already exist.
        datadir, filename = os.path.split(loc)
        # fname, fext = os.path.splitext(filename)
        # if fext == '.zip':
        # Check if shape file exists.
        # if os.path.isfile(os.path.join(datadir, fname + ".shp")):
        #    dbFilename = os.path.join(datadir, fname + ".shp")
        # elif os.path.isdir(os.path.join(datadir, fname)) and fname.endswith(".gdb"):
        #    dbFilename = os.path.join(datadir, fname)
        # else:
        #    msg = "Invalid zip file '{}' -- is not in shape/gdb format.".format(filename)
        #    raise HTTPNotImplemented(msg)
        # else:
        #    raise HTTPNotImplemented("Invalid zip file '{}'".format(filename))

        # if DB server is configured, get layer data from DB server. Otherwise get data from db file.
        # FIXME: filename shall be gdb/shape filename
        layer = ShapeLayer(self.request, filename)

        # add the shape layer into map
        idx = layer.add_layer_obj(map)

        # set map projection and extent from layer data
        lx = map.getLayer(idx).getExtent()
        map.extent = mapscript.rectObj(lx.minx, lx.miny, lx.maxx, lx.maxy)
        map.setProjecntion = "init={}".format(layer._data["crs"])

        # prepare an ows request object by copying request params
        ows_req = mapscript.OWSRequest()
        ows_req.loadParamsFromURL(self.request.query_string)

        # here is probably some room for optimisation
        # e.g. let mapscript write directly to output?
        #      write tile to file system and serve tile via some other means?
        #      cache tile or at least mapobj?
        wfs_req = self.request.params["REQUEST"]
        wfs_ver = self.request.params.get("VERSION", "1.1.0")

        # now do something based on REQUEST:
        mapscript.msIO_installStdoutToBuffer()
        res = map.OWSDispatch(ows_req)  # if != 0 then error
        content_type = mapscript.msIO_stripStdoutBufferContentType()
        content = mapscript.msIO_getStdoutBufferBytes()
        return Response(content, content_type=content_type)
Esempio n. 29
0
    def wms(self):
        """This is a WMS endpoint.

        It uses mapserver mapscript to process a WMS request.

        This endpoint requires an additional WMS parameter
        DATA_URL. The DATA_URL, should point to a downloadable file
        which can be used as raster data input for mapserver.
        """
        LOG.debug('Processing ows request')

        data_url = None
        try:
            data_url = self.request.GET.getone('DATA_URL')
        except:
            LOG.warn('No data_url provided')
            data_url = None
            # FIXME: should return an error here)

        # get location of local data file
        loc = fetch_file(self.request, data_url)
        # get map
        map = self._get_map()
        # setup layer
        # TODO: improve selection of Layer generator
        # TODO: use python-magic for a more reliable mime type detection
        mimetype, encoding = mimetypes.guess_type(loc)
        if mimetype == 'image/tiff':
            layer = TiffLayer(self.request, loc)
        elif mimetype == 'text/csv':
            layer = CSVLayer(self.request, loc)
        elif mimetype == 'application/zip':
            datadir, filename = os.path.split(loc)
            # fname, fext = os.path.splitext(filename)

            # Check if shape/gdb file exists.
            # if os.path.isfile(os.path.join(datadir, fname + ".shp")):
            #    dbFilename = os.path.join(datadir, fname + ".shp")
            # elif os.path.isdir(os.path.join(datadir, fname)) and fname.endswith(".gdb"):
            #    dbFilename = os.path.join(datadir, fname)
            # else:
            #    msg = "Invalid zip file '{}' -- is not in shape/gdb format.".format(filename)
            #    raise HTTPNotImplemented(msg)

            # FIXME: filename shall be gdb/shape filename
            layer = ShapeLayer(self.request, filename)
        else:
            msg = "Unknown file type '{}'.".format(mimetype)
            # HTTPBadRequest(msg)
            raise HTTPNotImplemented(msg)

        # add layer into map
        idx = layer.add_layer_obj(map)
        # set map projection and extent from layer data
        lx = map.getLayer(idx).getExtent()
        map.extent = mapscript.rectObj(lx.minx, lx.miny, lx.maxx, lx.maxy)
        map.setProjection = "init={}".format(layer._data['crs'])

        # prepare an ows request object
        # do some map processing here
        ows_req = mapscript.OWSRequest()
        # our layer.add_layer_obj applies SLD and SLD_BODY
        # copy request params into ows request except not these two
        for k, v in ((k, v) for (k, v) in self.request.params.items()
                     if k.lower() not in ('sld', 'sld_body', 'data_url')):
            ows_req.setParameter(k, v)
        # req.setParameter('SERVICE', 'WMS')
        # req.setParameter('VERSION', '1.3.0')
        # req.setParameter('REQUEST', 'GetCapablities')

        # here is probably some room for optimisation
        # e.g. let mapscript write directly to output?
        #      write tile to file system and serve tile via some other means?
        #      cache tile or at least mapobj?
        wms_req = self.request.params['REQUEST']
        wms_ver = self.request.params.get('VERSION', '1.3.0')
        # now do something based on REQUEST:
        if wms_req == u'GetMap':
            res = map.loadOWSParameters(ows_req, wms_ver)  # if != 0 then error
            img = map.draw()
            return Response(img.getBytes(), content_type=img.format.mimetype)
        elif wms_req == u'GetCapabilities':
            mapscript.msIO_installStdoutToBuffer()
            res = map.OWSDispatch(ows_req)  # if != 0 then error
            content_type = mapscript.msIO_stripStdoutBufferContentType()
            content = mapscript.msIO_getStdoutBufferBytes()
            return Response(content, content_type=content_type)
        elif wms_req == u'GetFeatureInfo':
            res = map.loadOWSParameters(ows_req, wms_ver)  # if != 0 then error
            mapscript.msIO_installStdoutToBuffer()
            res = map.OWSDispatch(ows_req)  # if != 0 then error
            content_type = mapscript.msIO_stripStdoutBufferContentType()
            content = mapscript.msIO_getStdoutBufferBytes()
            return Response(content, content_type=content_type)

        # We shouldn't end up here.....
        # let's raise an Error
        # FIXME: I am sure there are better pyramid ways to return errors
        raise Exception('request was not handled correctly')
Esempio n. 30
0
def application(env, start_response):
    """WSGI application for WMS/WCS"""
    for key in MAPSERV_ENV:
        if key in env:
            os.environ[key] = env[key]
        else:
            os.unsetenv(key)

    layer = None
    mapfile_ = None

    request = mapscript.OWSRequest()
    request.loadParams()

    lang_ = request.getValueByName('LANG')
    service_ = request.getValueByName('SERVICE')
    request_ = request.getValueByName('REQUEST')
    layers_ = request.getValueByName('LAYERS')
    layer_ = request.getValueByName('LAYER')
    coverageid_ = request.getValueByName('COVERAGEID')
    format_ = request.getValueByName('FORMAT')

    if lang_ is not None and lang_ in ['f', 'fr', 'fra']:
        lang = 'fr'
    else:
        lang = 'en'
    if layers_ is not None:
        layer = layers_
    elif layer_ is not None:
        layer = layer_
    elif coverageid_ is not None:
        layer = coverageid_
    else:
        layer = None
    if service_ is None:
        service_ = 'WMS'

    if layer is not None and len(layer) == 0:
        layer = None

    LOGGER.debug('service: {}'.format(service_))
    LOGGER.debug('language: {}'.format(lang))

    if layer is not None and ',' not in layer:
        mapfile_ = '{}/mapfile/geomet-climate-{}-{}-{}.map'.format(
            BASEDIR, service_, layer, lang)
    if mapfile_ is None or not os.path.exists(mapfile_):
        mapfile_ = '{}/mapfile/geomet-climate-{}-{}.map'.format(
            BASEDIR, service_, lang)
    if not os.path.exists(mapfile_):
        start_response('400 Bad Request',
                       [('Content-Type', 'application/xml')])
        msg = 'Unsupported service'
        return [SERVICE_EXCEPTION.format(msg)]

    # if requesting GetCapabilities for entire service, return cache
    if request_ == 'GetCapabilities' and layer is None:
        if service_ == 'WMS':
            filename = 'geomet-climate-WMS-1.3.0-capabilities-{}.xml'.format(
                lang)
            cached_caps = os.path.join(BASEDIR, 'mapfile', filename)
        elif service_ == 'WCS':
            filename = 'geomet-climate-WCS-2.0.1-capabilities-{}.xml'.format(
                lang)
            cached_caps = os.path.join(BASEDIR, 'mapfile', filename)

        if os.path.isfile(cached_caps):
            start_response('200 OK', [('Content-Type', 'application/xml')])
            with io.open(cached_caps, 'rb') as fh:
                return [fh.read()]

    LOGGER.debug('Loading mapfile: {}'.format(mapfile_))
    mapfile = mapscript.mapObj(mapfile_)

    mapscript.msIO_installStdoutToBuffer()
    request.loadParamsFromURL(env['QUERY_STRING'])

    try:
        LOGGER.debug('Dispatching OWS request')
        mapfile.OWSDispatch(request)
    except (mapscript.MapServerError, IOError) as err:
        # let error propagate to service exception
        LOGGER.error(err)
        pass

    headers = mapscript.msIO_getAndStripStdoutBufferMimeHeaders()

    headers_ = [
        ('Content-Type', headers['Content-Type']),
    ]

    # for WCS requests, generate useful filename for response
    if service_ == 'WCS' and request_ == 'GetCoverage':
        filename = 'geomet-climate-{}.{}'.format(layer, WCS_FORMATS[format_])
        headers_.append(('Content-Disposition',
                         'attachment; filename="{}"'.format(filename)))

    content = mapscript.msIO_getStdoutBufferBytes()

    start_response('200 OK', headers_)

    return [content]
Esempio n. 31
0
def airspace_image(cache_key, airspace_id):
    if not mapscript_available:
        abort(404)

    # get information from cache...
    infringements = cache.get('upload_airspace_infringements_' + cache_key)
    flight_path = cache.get('upload_airspace_flight_path_' + cache_key)

    # abort if invalid cache key
    if not infringements \
       or not flight_path:
        abort(404)

    # Convert the coordinate into a list of tuples
    coordinates = [(c.location['longitude'], c.location['latitude'])
                   for c in flight_path]
    # Create a shapely LineString object from the coordinates
    linestring = LineString(coordinates)
    # Save the new path as WKB
    locations = from_shape(linestring, srid=4326)

    highlight_locations = []
    extent_epsg4326 = [180, 85.05112878, -180, -85.05112878]

    for period in infringements[airspace_id]:
        # Convert the coordinate into a list of tuples
        coordinates = [(c['location']['longitude'], c['location']['latitude'])
                       for c in period]

        # Create a shapely LineString object from the coordinates
        if len(coordinates) == 1:
            # a LineString must contain at least two points...
            linestring = LineString([coordinates[0], coordinates[0]])
        else:
            linestring = LineString(coordinates)

        highlight_locations.append(linestring)

        # gather extent
        (minx, miny, maxx, maxy) = linestring.bounds

        extent_epsg4326[0] = min(extent_epsg4326[0], minx)
        extent_epsg4326[1] = min(extent_epsg4326[1], miny)
        extent_epsg4326[2] = max(extent_epsg4326[2], maxx)
        extent_epsg4326[3] = max(extent_epsg4326[3], maxy)

    # Save the new path as WKB
    highlight_multilinestring = from_shape(
        MultiLineString(highlight_locations), srid=4326)

    # increase extent by factor 1.05
    width = abs(extent_epsg4326[0] - extent_epsg4326[2])
    height = abs(extent_epsg4326[1] - extent_epsg4326[3])

    center_x = (extent_epsg4326[0] + extent_epsg4326[2]) / 2
    center_y = (extent_epsg4326[1] + extent_epsg4326[3]) / 2

    extent_epsg4326[0] = center_x - width / 2 * 1.05
    extent_epsg4326[1] = center_y - height / 2 * 1.05
    extent_epsg4326[2] = center_x + width / 2 * 1.05
    extent_epsg4326[3] = center_y + height / 2 * 1.05

    # minimum extent should be 0.3 deg
    width = abs(extent_epsg4326[0] - extent_epsg4326[2])
    height = abs(extent_epsg4326[1] - extent_epsg4326[3])

    if width < 0.3:
        extent_epsg4326[0] = center_x - 0.15
        extent_epsg4326[2] = center_x + 0.15

    if height < 0.3:
        extent_epsg4326[1] = center_y - 0.15
        extent_epsg4326[3] = center_y + 0.15

    # convert extent from EPSG4326 to EPSG3857
    epsg4326 = pyproj.Proj(init='epsg:4326')
    epsg3857 = pyproj.Proj(init='epsg:3857')

    x1, y1 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[0],
                              extent_epsg4326[1])
    x2, y2 = pyproj.transform(epsg4326, epsg3857, extent_epsg4326[2],
                              extent_epsg4326[3])

    extent_epsg3857 = [x1, y1, x2, y2]

    # load basemap and set size + extent
    basemap_path = os.path.join(
        current_app.config.get('SKYLINES_MAPSERVER_PATH'), 'basemap.map')
    map_object = mapscript.mapObj(basemap_path)
    map_object.setSize(400, 400)
    map_object.setExtent(extent_epsg3857[0], extent_epsg3857[1],
                         extent_epsg3857[2], extent_epsg3857[3])

    # enable airspace and airports layers
    num_layers = map_object.numlayers
    for i in range(num_layers):
        layer = map_object.getLayer(i)

        if layer.group == 'Airports':
            layer.status = mapscript.MS_ON

        if layer.group == 'Airspace':
            layer.status = mapscript.MS_ON

    # get flights layer
    flights_layer = map_object.getLayerByName('Flights')
    highlight_layer = map_object.getLayerByName('Flights_Highlight')

    # set sql query for blue flight
    one = literal_column('1 as flight_id')
    flight_query = db.session.query(locations.label('flight_geometry'), one)

    flights_layer.data = 'flight_geometry FROM (' + query_to_sql(flight_query) + ')' + \
                         ' AS foo USING UNIQUE flight_id USING SRID=4326'

    # set sql query for highlighted linestrings
    highlighted_query = db.session.query(
        highlight_multilinestring.label('flight_geometry'), one)

    highlight_layer.data = 'flight_geometry FROM (' + query_to_sql(highlighted_query) + ')' + \
                           ' AS foo USING UNIQUE flight_id USING SRID=4326'

    highlight_layer.status = mapscript.MS_ON

    # get osm layer and set WMS url
    osm_layer = map_object.getLayerByName('OSM')
    osm_layer.connection = current_app.config.get('SKYLINES_MAP_TILE_URL') + \
        '/service?'

    # draw map
    map_image = map_object.draw()

    # get image
    mapscript.msIO_installStdoutToBuffer()
    map_image.write()
    content = mapscript.msIO_getStdoutBufferBytes()

    # return to client
    resp = make_response(content)
    resp.headers['Content-type'] = map_image.format.mimetype
    return resp
Esempio n. 32
0
map = mapscript.mapObj('../../tests/test.map')
map.setMetaData("ows_onlineresource", "http://dummy.org/")
ows_req = mapscript.OWSRequest()

ows_req.type = mapscript.MS_GET_REQUEST

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

mapscript.msIO_installStdoutToBuffer()
dispatch_status = map.OWSDispatch(ows_req)
if dispatch_status:
    status = '200 OK'
else:
    status = '500 Internal Server Error'
content_type = mapscript.msIO_stripStdoutBufferContentType()
mapscript.msIO_stripStdoutBufferContentHeaders()
result = mapscript.msIO_getStdoutBufferBytes()

try:
    # MapServer 6.0:
    mapscript.msCleanup()
except:
    # MapServer 6.1:
    mapscript.msCleanup(1)

response_headers = [('Content-Type', content_type),
                    ('Content-Length', str(len(result)))]
Esempio n. 33
0
    def get(self, request, *args, **kwargs):
        """
        Html GET method of WmsView. This view renders WMS requests into
        corresponding responses using the attached WmsMap class.
        Responses are mainly images and xml files.
        """
        # Create response
        response = HttpResponse()

        # Setup wms request object
        ows_request = mapscript.OWSRequest()

        # If tile kwargs were provided, add tile parameters to request
        tileparams = self.tilemode()

        if tileparams:
            # Get image format from url
            format = {'.png': 'image/png',
                      '.jpg': 'image/jpeg'}[self.kwargs.get('format')]

            # Return empty image if tile cant be found
            if not self.tile_exists(*tileparams):
                # Get image type and size
                imagetype = 'PNG' if format == 'image/png' else 'JPEG'
                imagesize = 256, 256
                response['Content-Type'] = format

                # Create image and save it to response
                im = Image.new("RGBA", imagesize, (0, 0, 0, 0))
                im.save(response, imagetype)

                return response
            else:
                tilebounds = self.get_tile_bounds(*tileparams)

                # Get layer name
                layers = self.kwargs.get('layers')

                # Setup wms parameter object
                request_data = {
                    'SERVICE': 'WMS',
                    'REQUEST': 'GetMap',
                    'VERSION': '1.1.1',
                    'TRANSPARENT': 'true',
                    'HEIGHT': '256',
                    'WIDTH': '256',
                    'SRS': 'EPSG:3857',
                    'FORMAT': format,
                    'LAYERS': layers,
                    'BBOX': tilebounds,
                }

                request.GET = dict(request.GET.items() + request_data.items())

        # Set ows parameters from request data
        for param, value in request.GET.items():
            ows_request.setParameter(param, value)

        # Instantiate WmsMap class
        self.wmsmap = self.map_class(request, **kwargs)

        # Dynamically use host for declaring service endpoint
        onlineresource = request.build_absolute_uri().split('?')[0] + '?'
        self.wmsmap.map_object.setMetaData('wms_onlineresource',
                                           onlineresource)

        # Dispatch map rendering
        self.wmsmap.map_object.OWSDispatch(ows_request)

        # Strip buffer from headers
        mapscript.msIO_stripStdoutBufferContentHeaders()

        # Store contenttype
        contenttype = mapscript.msIO_stripStdoutBufferContentType()

        # Write data to response
        response.write(mapscript.msIO_getStdoutBufferBytes())

        # Set contenttype
        response['Content-Type'] = contenttype

        return response
Esempio n. 34
0
    def wms_getheatmap_req(self, wms_req):
        # http://mapserver.org/ogc/mapscript.html#python-examples
        # test url
        # http://mapglow.org/wms/?service=WMS&request=GetMap&bbox=4.95,52,5.6,52.3&version=1.1.0&layers=tracepoints&srs=EPSG:4326&format=image/png&width=400&height=400
        #    print("Content-type: text/plain\n\n")

        bbox = wms_req.getValueByName("BBOX")
        layer = wms_req.getValueByName("LAYERS")
        srs = wms_req.getValueByName("SRS")
        width = float(wms_req.getValueByName("WIDTH"))
        height = float(wms_req.getValueByName("HEIGHT"))

        # CREATE WKT STRING OF POINT COORDS
        bbox_arr = bbox.split(",")
        wktLL = "POINT(%s %s)" % (bbox_arr[0], bbox_arr[1])
        wktUR = "POINT(%s %s)" % (bbox_arr[2], bbox_arr[3])

        # CREATE PROJECTION OBJECTS
        google = osr.SpatialReference()
        google.ImportFromEPSG(900913)
        wgs84 = osr.SpatialReference()
        wgs84.ImportFromEPSG(4326)

        # CREATE OGR POINT OBJECT, ASSIGN PROJECTION, REPROJECT
        pointLL = ogr.CreateGeometryFromWkt(wktLL)
        pointLL.AssignSpatialReference(google)
        pointLL.TransformTo(wgs84)
        pointUR = ogr.CreateGeometryFromWkt(wktUR)
        pointUR.AssignSpatialReference(google)
        pointUR.TransformTo(wgs84)

        bbox = "%f,%f,%f,%f" % (pointLL.GetX(), pointLL.GetY(), pointUR.GetX(), pointUR.GetY())
        bboxLL = "%f,%f,%f,%f" % (pointLL.GetY(), pointLL.GetX(), pointUR.GetY(), pointUR.GetX())

        # Do not use internal WFS (too slow)
        # points = self.get_layer_points_wfs(layer, bbox, max_features)

        # Get points from the layer (direct layer query)

        layerObj = self.map.getLayerByName(layer)
        points = []
        if layerObj:
            # see if layer has configured feature density
            # this determines max number of features for Layer query
            feature_density = float(layerObj.metadata.get("mapglow_feat_density", "0.002"))

            # calculate max features for Layer query
            max_features = int(round(feature_density * width * height))

            # get array of Point objects from Layer
            printtime("START - get points from layer max_features=" + str(max_features))
            points = self.get_layer_points(layerObj, bbox, max_features)
            printtime("Got " + str(len(points)) + " points from layer")

        # No points: generate transparent overlay image using standard MS dispatch
        if len(points) <= 0:
            mapscript.msIO_installStdoutToBuffer()

            # MS does not like the heatmap-style STYLES
            wms_req.setParameter("STYLES", "")

            self.map.OWSDispatch(wms_req)
            print(mapscript.msIO_getStdoutBufferBytes())
            return

        # Get heatmap algoritm+parms
        # Now 1 type in STYLES, e.g. 'heat/seth/red-yellow-green/12/0.5'
        # TODO: parameters are heatmap-type specific
        (heat, heatmap_type, gradient, radius, decay) = wms_req.getValueByName("STYLES").split("/")

        # Just to protect ourselves from blowing up
        if int(radius) > 20:
            radius = "20"

        # check how gradient is specified: either a gradient file or a range of doubles (stop, R, G, B, A)
        gradient_path = self.root_dir + "config/gradients/gradient-" + gradient + ".png"
        if os.path.exists(gradient_path):
            # Gradient as file
            gradient_option_name = "--gradient"
            gradient_option_value = gradient_path
        else:
            # Gradient as range of doubles (stop, R, G, B, A), (stop, R, G, B, A),...
            # each of value double between 0..1
            # e.g. 0,1,1,0,1, 0.75,1,0,0,1, 0.9,1,1,0
            gradient_option_name = "--gradient_color_srgba"
            gradient_option_value = gradient

        # Assemble arguments
        args = [
            "--web",
            "--points_arr",
            "--radius",
            radius,
            "--decay",
            decay,
            "--width",
            wms_req.getValueByName("WIDTH"),
            "--height",
            wms_req.getValueByName("HEIGHT"),
            gradient_option_name,
            gradient_option_value,
            "--extent",
            bboxLL,
        ]

        # Creates and sends the heatmap
        main(args, points)
Esempio n. 35
0
    def wfs(self):
        """This is a WFS endpoint.

        It uses mapserver mapscript to process a WFS request.

        This endpoint requires an additional WFS parameter
        DATA_URL. The DATA_URL, should point to a downloadable file
        which can be used as raster data input for mapserver.
        """
        LOG.debug('Processing ows request')

        data_url = None
        try:
            data_url = self.request.GET.getone('DATA_URL')
        except:
            LOG.warn('No data_url provided')
            data_url = None

        # get location of local data file
        # FIXME: May not be required if data is from DB
        if data_url:
            loc = fetch_file(self.request, data_url)

        # get map
        map = self._get_map()

        # Check that appropriate files are already exist.
        datadir, filename = os.path.split(loc)
        #fname, fext = os.path.splitext(filename)
        #if fext == '.zip':
        # Check if shape file exists.
        #if os.path.isfile(os.path.join(datadir, fname + ".shp")):
        #    dbFilename = os.path.join(datadir, fname + ".shp")
        #elif os.path.isdir(os.path.join(datadir, fname)) and fname.endswith(".gdb"):
        #    dbFilename = os.path.join(datadir, fname)
        #else:
        #    msg = "Invalid zip file '{}' -- is not in shape/gdb format.".format(filename)
        #    raise HTTPNotImplemented(msg)
        #else:
        #    raise HTTPNotImplemented("Invalid zip file '{}'".format(filename))

        # if DB server is configured, get layer data from DB server. Otherwise get data from db file.
        # FIXME: filename shall be gdb/shape filename
        layer = ShapeLayer(self.request, filename)

        # add the shape layer into map
        idx = layer.add_layer_obj(map)

        # set map projection and extent from layer data
        lx = map.getLayer(idx).getExtent()
        map.extent = mapscript.rectObj(lx.minx, lx.miny, lx.maxx, lx.maxy)
        map.setProjecntion = "init={}".format(layer._data['crs'])

        # prepare an ows request object by copying request params
        ows_req = mapscript.OWSRequest()
        ows_req.loadParamsFromURL(self.request.query_string)

        # here is probably some room for optimisation
        # e.g. let mapscript write directly to output?
        #      write tile to file system and serve tile via some other means?
        #      cache tile or at least mapobj?
        wfs_req = self.request.params['REQUEST']
        wfs_ver = self.request.params.get('VERSION', '1.1.0')

        # now do something based on REQUEST:
        mapscript.msIO_installStdoutToBuffer()
        res = map.OWSDispatch(ows_req)  # if != 0 then error
        content_type = mapscript.msIO_stripStdoutBufferContentType()
        content = mapscript.msIO_getStdoutBufferBytes()
        return Response(content, content_type=content_type)
Esempio n. 36
0
def application(env, start_response):
    """WSGI application for WMS/WCS"""

    for key in MAPSERV_ENV:
        if key in env:
            os.environ[key] = env[key]
        else:
            os.unsetenv(key)

    layer = None
    mapfile_ = None

    request = mapscript.OWSRequest()
    request.loadParams()

    lang_ = request.getValueByName('LANG')
    service_ = request.getValueByName('SERVICE')
    request_ = request.getValueByName('REQUEST')
    layers_ = request.getValueByName('LAYERS')
    layer_ = request.getValueByName('LAYER')
    coverageid_ = request.getValueByName('COVERAGEID')

    if lang_ is not None and lang_ in ['f', 'fr', 'fra']:
        lang = 'fr'
    else:
        lang = 'en'
    if layers_ is not None:
        layer = layers_
    elif layer_ is not None:
        layer = layer_
    elif coverageid_ is not None:
        layer = coverageid_
    else:
        layer = None
    if service_ is None:
        service_ = 'WMS'

    if layer is not None and len(layer) == 0:
        layer = None

    time_error = None

    LOGGER.debug('service: {}'.format(service_))
    LOGGER.debug('language: {}'.format(lang))

    if layer == 'GODS':
        banner = os.path.join(BASEDIR, 'geomet_mapfile/resources',
                              'other/banner.txt')
        with open(banner) as fh:
            start_response('200 OK', [('Content-Type', 'text/plain')])
            msg = fh.read()
            return ['{}'.format(msg).encode()]

    # fetch mapfile from store or from disk
    if MAPFILE_STORAGE == 'file':
        # if a single layer is specified in LAYER param fetch mapfile from disk
        if layer is not None and ',' not in layer:
            mapfile_ = '{}/mapfile/geomet-weather-{}.map'.format(
                BASEDIR, layer)
        # if mapfile_ is None or its path does not exist
        if mapfile_ is None or not os.path.exists(mapfile_):
            mapfile_ = '{}/mapfile/geomet-weather.map'.format(BASEDIR)
        # if mapfile_ path does not exist set mapfile_ to None
        if not os.path.exists(mapfile_):
            mapfile_ = None
    elif MAPFILE_STORAGE == 'store':
        st = load_plugin('store', {'type': STORE_TYPE, 'url': STORE_URL})
        if layer is not None and ',' not in layer:
            mapfile_ = st.get_key('{}_mapfile'.format(layer))
        if mapfile_ is None:
            mapfile_ = st.get_key('geomet-weather_mapfile')

    # if no mapfile at all is found return a Unsupported service exception
    if not mapfile_:
        start_response('400 Bad Request',
                       [('Content-Type', 'application/xml')])
        msg = 'Unsupported service'
        return [SERVICE_EXCEPTION.format(msg).encode()]

    # if requesting GetCapabilities for entire service, return cache
    if request_ == 'GetCapabilities' and layer is None:
        LOGGER.debug('Requesting global mapfile')
        if service_ == 'WMS':
            filename = 'geomet-weather-ogc-wms-1.3.0-capabilities-{}.xml'.format(
                lang)  # noqa
            cached_caps = os.path.join(BASEDIR, 'mapfile', filename)

        if os.path.isfile(cached_caps):
            start_response('200 OK', [('Content-Type', 'application/xml')])
            with io.open(cached_caps, 'rb') as fh:
                return [fh.read()]
    else:
        LOGGER.debug('Requesting layer mapfile')
        if os.path.exists(mapfile_):
            # read mapfile from filepath
            LOGGER.debug('Loading mapfile {} from disk'.format(mapfile_))
            mapfile = mapscript.mapObj(mapfile_)
        else:
            # read mapfile from string returned from store
            LOGGER.debug('Loading {}_mapfile from store'.format(
                layer if layer else 'geomet-mapfile'))
            mapfile = mapscript.fromstring(mapfile_)

        layerobj = mapfile.getLayerByName(layer)
        time = request.getValueByName('TIME')
        ref_time = request.getValueByName('DIM_REFERENCE_TIME')

        if any(time_param == '' for time_param in [time, ref_time]):
            time_error = "Valeur manquante pour la date ou l'heure / Missing value for date or time"  # noqa
            start_response('200 OK', [('Content-type', 'text/xml')])
            return [SERVICE_EXCEPTION.format(time_error).encode()]

        if time is None:
            time = layerobj.getMetaData('wms_timedefault')
        if ref_time is None:
            ref_time = layerobj.getMetaData('wms_reference_time_default')

        try:
            filepath, url = get_data_path(layer, time, ref_time)
        except TileNotFoundError as err:
            LOGGER.error(err)
            time_error = (
                'NoMatch: Date et heure invalides / Invalid date and time')
            start_response('200 OK', [('Content-type', 'text/xml')])
            return [SERVICE_EXCEPTION.format(time_error).encode()]

        try:
            if request_ in ['GetMap', 'GetFeatureInfo']:
                if all([
                        filepath.startswith(os.sep),
                        not os.path.isfile(filepath)
                ]):
                    LOGGER.debug('File is not on disk: {}'.format(filepath))
                    if not ALLOW_LAYER_DATA_DOWNLOAD:
                        LOGGER.error('layer data downloading not allowed')
                        _error = 'data not found'
                        start_response('500 Internal Server Error',
                                       [('Content-type', 'text/xml')])
                        return [SERVICE_EXCEPTION.format(_error).encode()]

                    if not os.path.exists(os.path.dirname(filepath)):
                        LOGGER.debug('Creating the filepath')
                        os.makedirs(os.path.dirname(filepath))
                    LOGGER.debug('Downloading url: {}'.format(url))
                    with urlopen(url) as r:
                        with open(filepath, 'wb') as fh:
                            fh.write(r.read())

            layerobj.data = filepath

        except ValueError as err:
            LOGGER.error(err)
            _error = (
                'NoApplicableCode: Donnée non disponible / Data not available')
            start_response('500 Internal Server Error',
                           [('Content-type', 'text/xml')])
            return [SERVICE_EXCEPTION.format(_error).encode()]

        if request_ == 'GetCapabilities' and lang == 'fr':
            metadata_lang(mapfile, layer.split(','), lang)

    mapscript.msIO_installStdoutToBuffer()

    # giving we don't use properly use tileindex due to performance issues
    # we need to remove the time parameter from the request for uvraster layer
    if 'time' in env['QUERY_STRING'].lower():
        query_string = env['QUERY_STRING'].split('&')
        query_string = [x for x in query_string if 'time' not in x.lower()]
        request.loadParamsFromURL('&'.join(query_string))
    else:
        request.loadParamsFromURL(env['QUERY_STRING'])

    try:
        LOGGER.debug('Dispatching OWS request')
        mapfile.OWSDispatch(request)
    except (mapscript.MapServerError, IOError) as err:
        # let error propagate to service exception
        LOGGER.error(err)
        pass

    headers = mapscript.msIO_getAndStripStdoutBufferMimeHeaders()

    headers_ = [
        ('Content-Type', headers['Content-Type']),
    ]

    content = mapscript.msIO_getStdoutBufferBytes()

    start_response('200 OK', headers_)

    return [content]
Esempio n. 37
0
    def wms(self):
        """This is a WMS endpoint.

        It uses mapserver mapscript to process a WMS request.

        This endpoint requires an additional WMS parameter
        DATA_URL. The DATA_URL, should point to a downloadable file
        which can be used as raster data input for mapserver.
        """
        LOG.debug('Processing ows request')

        data_url = None
        try:
            data_url = self.request.GET.getone('DATA_URL')
        except:
            LOG.warn('No data_url provided')
            data_url = None
            # FIXME: should return an error here)

        # get location of local data file
        loc = fetch_file(self.request, data_url)
        # get map
        map = self._get_map()
        # setup layer
        # TODO: improve selection of Layer generator
        # TODO: use python-magic for a more reliable mime type detection
        mimetype, encoding = mimetypes.guess_type(loc)
        if mimetype == 'image/tiff':
            layer = TiffLayer(self.request, loc)
        elif mimetype == 'text/csv':
            layer = CSVLayer(self.request, loc)
        elif mimetype == 'application/zip':
            datadir, filename = os.path.split(loc)
            # fname, fext = os.path.splitext(filename)

            # Check if shape/gdb file exists.
            # if os.path.isfile(os.path.join(datadir, fname + ".shp")):
            #    dbFilename = os.path.join(datadir, fname + ".shp")
            # elif os.path.isdir(os.path.join(datadir, fname)) and fname.endswith(".gdb"):
            #    dbFilename = os.path.join(datadir, fname)
            # else:
            #    msg = "Invalid zip file '{}' -- is not in shape/gdb format.".format(filename)
            #    raise HTTPNotImplemented(msg)

            # FIXME: filename shall be gdb/shape filename
            layer = ShapeLayer(self.request, filename)
        else:
            msg = "Unknown file type '{}'.".format(mimetype)
            # HTTPBadRequest(msg)
            raise HTTPNotImplemented(msg)

        # add layer into map
        idx = layer.add_layer_obj(map)
        # set map projection and extent from layer data
        lx = map.getLayer(idx).getExtent()
        map.extent = mapscript.rectObj(lx.minx, lx.miny, lx.maxx, lx.maxy)
        map.setProjection = "init={}".format(layer._data['crs'])

        # prepare an ows request object
        # do some map processing here
        ows_req = mapscript.OWSRequest()
        # our layer.add_layer_obj applies SLD and SLD_BODY
        # copy request params into ows request except not these two
        for k, v in ((k, v)for (k, v) in self.request.params.items() if k.lower() not in ('sld', 'sld_body', 'data_url')):
            ows_req.setParameter(k, v)
        # req.setParameter('SERVICE', 'WMS')
        # req.setParameter('VERSION', '1.3.0')
        # req.setParameter('REQUEST', 'GetCapablities')

        # here is probably some room for optimisation
        # e.g. let mapscript write directly to output?
        #      write tile to file system and serve tile via some other means?
        #      cache tile or at least mapobj?
        wms_req = self.request.params['REQUEST']
        wms_ver = self.request.params.get('VERSION', '1.3.0')
        # now do something based on REQUEST:
        if wms_req == u'GetMap':
            res = map.loadOWSParameters(ows_req, wms_ver)  # if != 0 then error
            img = map.draw()
            return Response(img.getBytes(), content_type=img.format.mimetype)
        elif wms_req == u'GetCapabilities':
            mapscript.msIO_installStdoutToBuffer()
            res = map.OWSDispatch(ows_req)  # if != 0 then error
            content_type = mapscript.msIO_stripStdoutBufferContentType()
            content = mapscript.msIO_getStdoutBufferBytes()
            return Response(content, content_type=content_type)
        elif wms_req == u'GetFeatureInfo':
            res = map.loadOWSParameters(ows_req, wms_ver)  # if != 0 then error
            mapscript.msIO_installStdoutToBuffer()
            res = map.OWSDispatch(ows_req)  # if != 0 then error
            content_type = mapscript.msIO_stripStdoutBufferContentType()
            content = mapscript.msIO_getStdoutBufferBytes()
            return Response(content, content_type=content_type)

        # We shouldn't end up here.....
        # let's raise an Error
        # FIXME: I am sure there are better pyramid ways to return errors
        raise Exception('request was not handled correctly')