Пример #1
0
    def proxy(self) -> Response:
        if self.user is not None:
            # We have a user logged in. We need to set group_id and
            # possible layer_name in the params. We set layer_name
            # when either QUERY_PARAMS or LAYERS is set in the
            # WMS params, i.e. for GetMap and GetFeatureInfo
            # requests. For GetLegendGraphic requests we do not
            # send layer_name, but MapServer should not use the DATA
            # string for GetLegendGraphic.

            roles = self.user.roles
            if len(roles):
                if self.ogc_server.auth == main.OGCSERVER_AUTH_STANDARD:
                    self.params["role_ids"] = \
                        "-1" if len(roles) == 0 else ",".join([str(r.id) for r in roles])

                    # In some application we want to display the features owned by a user
                    # than we need his id.
                    self.params["user_id"] = self.user.id  # pragma: no cover
            else:  # pragma nocover
                log.warning("The user '%s' has no role", self.user.username)

        # do not allows direct variable substitution
        for k in list(self.params.keys()):
            if k[:2].capitalize() == "S_":
                log.warning(
                    "Direct substitution not allowed ({0!s}={1!s}).".format(
                        k, self.params[k]))
                del self.params[k]

        # add functionalities params
        self.params.update(get_mapserver_substitution_params(self.request))

        # get method
        method = self.request.method

        # we want the browser to cache GetLegendGraphic and
        # DescribeFeatureType requests
        use_cache = False

        if method == "GET":
            # For GET requests, params are added only if the self.request
            # parameter is actually provided.
            if "request" not in self.lower_params:
                self.params = {}  # pragma: no cover
            else:
                if self.ogc_server.type != main.OGCSERVER_TYPE_QGISSERVER or \
                        "user_id" not in self.params:

                    use_cache = self.lower_params["request"] in (
                        "getlegendgraphic", )

                    # no user_id and role_id or cached queries
                    if use_cache and "user_id" in self.params:
                        del self.params["user_id"]
                    if use_cache and "role_ids" in self.params:
                        del self.params["role_ids"]

            if "service" in self.lower_params and self.lower_params[
                    "service"] == "wfs":
                _url = self._get_wfs_url()
            else:
                _url = self._get_wms_url()
        else:
            # POST means WFS
            _url = self._get_wfs_url()

        cache_control = PRIVATE_CACHE
        if method == "GET" and \
                "service" in self.lower_params and \
                self.lower_params["service"] == "wms":
            if self.lower_params["request"] in ("getmap", "getfeatureinfo"):
                cache_control = NO_CACHE
            elif self.lower_params["request"] == "getlegendgraphic":
                cache_control = PUBLIC_CACHE
        elif method == "GET" and \
                "service" in self.lower_params and \
                self.lower_params["service"] == "wfs":
            if self.lower_params["request"] == "getfeature":
                cache_control = NO_CACHE
        elif method != "GET":
            cache_control = NO_CACHE

        headers = self._get_headers()
        # Add headers for Geoserver
        if self.ogc_server.auth == main.OGCSERVER_AUTH_GEOSERVER and \
                self.user is not None:
            headers["sec-username"] = self.user.username
            headers["sec-roles"] = ";".join([r.name for r in roles])

        response = self._proxy_callback(self.user,
                                        cache_control,
                                        url=_url,
                                        params=self.params,
                                        cache=use_cache,
                                        headers=headers,
                                        body=self.request.body)

        if self.lower_params.get("request") == "getmap" and \
                not response.content_type.startswith('image/') and \
                response.status_code < 400:
            response.status_code = 400

        return response
Пример #2
0
    async def _wms_getcap_cached(
        self, ogc_server: main.OGCServer
    ) -> Tuple[Optional[Url], Optional[bytes], Set[str]]:
        errors: Set[str] = set()
        url = get_url2(f"The OGC server '{ogc_server.name}'", ogc_server.url, self.request, errors)
        if errors or url is None:
            return url, None, errors

        # Add functionality params
        if (
            ogc_server.auth == main.OGCSERVER_AUTH_STANDARD
            and ogc_server.type == main.OGCSERVER_TYPE_MAPSERVER
        ):
            url.add_query(get_mapserver_substitution_params(self.request))

        url.add_query(
            {
                "SERVICE": "WMS",
                "VERSION": "1.1.1",
                "REQUEST": "GetCapabilities",
                "ROLE_IDS": "0",
                "USER_ID": "0",
            },
        )

        LOG.debug("Get WMS GetCapabilities for URL: %s", url)

        # Forward request to target (without Host Header)
        headers = dict(self.request.headers)

        # Add headers for Geoserver
        if ogc_server.auth == main.OGCSERVER_AUTH_GEOSERVER:
            headers["sec-username"] = "******"
            headers["sec-roles"] = "root"

        if url.hostname != "localhost" and "Host" in headers:
            headers.pop("Host")

        headers = restrict_headers(headers, self.headers_whitelist, self.headers_blacklist)

        try:
            content, content_type = await asyncio.get_event_loop().run_in_executor(
                None, get_http_cached, self.http_options, url, headers
            )
        except Exception:
            error = f"Unable to GetCapabilities from URL {url}"
            errors.add(error)
            LOG.error(error, exc_info=True)
            return url, None, errors

        # With wms 1.3 it returns text/xml also in case of error :-(
        if content_type.split(";")[0].strip() not in [
            "application/vnd.ogc.wms_xml",
            "text/xml",
        ]:
            error = (
                f"GetCapabilities from URL '{url}' returns a wrong Content-Type: {content_type}\n"
                f"{content.decode()}"
            )
            errors.add(error)
            LOG.error(error)
            return url, None, errors

        return url, content, errors
Пример #3
0
    async def _wms_getcap_cached(self, ogc_server, _):
        """ _ is just for cache on the role id """

        errors: Set[str] = set()
        url = get_url2("The OGC server '{}'".format(ogc_server.name),
                       ogc_server.url, self.request, errors)
        if errors or url is None:  # pragma: no cover
            return url, None, errors

        # Add functionality params
        sparams = get_mapserver_substitution_params(self.request)
        url = add_url_params(url, sparams)

        url = add_url_params(
            url,
            {
                "SERVICE": "WMS",
                "VERSION": "1.1.1",
                "REQUEST": "GetCapabilities",
                "ROLE_ID": "0",
                "USER_ID": "0",
            },
        )

        LOG.debug("Get WMS GetCapabilities for url: %s", url)

        # Forward request to target (without Host Header)
        headers = dict(self.request.headers)

        # Add headers for Geoserver
        if ogc_server.auth == main.OGCSERVER_AUTH_GEOSERVER:
            headers["sec-username"] = "******"
            headers["sec-roles"] = "root"

        if urllib.parse.urlsplit(
                url
        ).hostname != "localhost" and "Host" in headers:  # pragma: no cover
            headers.pop("Host")

        try:
            response = await asyncio.get_event_loop().run_in_executor(
                None, get_http_cached, self.http_options, url, headers)
        except Exception:  # pragma: no cover
            error = "Unable to GetCapabilities from URL {}".format(url)
            errors.add(error)
            LOG.error(error, exc_info=True)
            return url, None, errors

        if not response.ok:  # pragma: no cover
            error = "GetCapabilities from URL {} return the error: {:d} {}".format(
                url, response.status_code, response.reason)
            errors.add(error)
            LOG.error(error)
            return url, None, errors

        # With wms 1.3 it returns text/xml also in case of error :-(
        if response.headers.get("Content-Type",
                                "").split(";")[0].strip() not in [
                                    "application/vnd.ogc.wms_xml",
                                    "text/xml",
                                ]:
            error = "GetCapabilities from URL {} returns a wrong Content-Type: {}\n{}".format(
                url, response.headers.get("Content-Type", ""), response.text)
            errors.add(error)
            LOG.error(error)
            return url, None, errors

        return url, response.content, errors
Пример #4
0
    def proxy(self) -> Response:

        if self.user is None and "authentication_required" in self.request.params:
            LOG.debug("proxy() detected authentication_required")
            raise HTTPUnauthorized(headers={"WWW-Authenticate": 'Basic realm="Access to restricted layers"'})

        # We have a user logged in. We need to set group_id and possible layer_name in the params. We set
        # layer_name when either QUERY_PARAMS or LAYERS is set in the WMS params, i.e. for GetMap and
        # GetFeatureInfo requests. For GetLegendGraphic requests we do not send layer_name, but MapServer
        # should not use the DATA string for GetLegendGraphic.

        if self.ogc_server.auth == main.OGCSERVER_AUTH_STANDARD:
            self.params["role_ids"] = ",".join([str(e) for e in get_roles_id(self.request)])

            # In some application we want to display the features owned by a user than we need his id.
            self.params["user_id"] = self.user.id if self.user is not None else "-1"  # pragma: no cover

        # Do not allows direct variable substitution
        for k in list(self.params.keys()):
            if k[:2].capitalize() == "S_":
                LOG.warning("Direct substitution not allowed (%s=%s).", k, self.params[k])
                del self.params[k]

        # add functionalities params
        self.params.update(get_mapserver_substitution_params(self.request))

        # get method
        method = self.request.method

        # we want the browser to cache GetLegendGraphic and
        # DescribeFeatureType requests
        use_cache = False

        if method == "GET":
            # For GET requests, params are added only if the self.request
            # parameter is actually provided.
            if "request" not in self.lower_params:
                self.params = {}  # pragma: no cover
            else:
                if self.ogc_server.type != main.OGCSERVER_TYPE_QGISSERVER or "user_id" not in self.params:

                    use_cache = self.lower_params["request"] in ("getlegendgraphic",)

                    # no user_id and role_id or cached queries
                    if use_cache and "user_id" in self.params:
                        del self.params["user_id"]
                    if use_cache and "role_ids" in self.params:
                        del self.params["role_ids"]

            if "service" in self.lower_params and self.lower_params["service"] == "wfs":
                _url = self._get_wfs_url()
            else:
                _url = self._get_wms_url()
        else:
            # POST means WFS
            _url = self._get_wfs_url()

        cache_control = PRIVATE_CACHE
        if method == "GET" and "service" in self.lower_params and self.lower_params["service"] == "wms":
            if self.lower_params.get("request") in ("getmap", "getfeatureinfo"):
                cache_control = NO_CACHE
            elif self.lower_params.get("request") == "getlegendgraphic":
                cache_control = PUBLIC_CACHE
        elif method == "GET" and "service" in self.lower_params and self.lower_params["service"] == "wfs":
            if self.lower_params.get("request") == "getfeature":
                cache_control = NO_CACHE
        elif method != "GET":
            cache_control = NO_CACHE

        headers = self._get_headers()
        # Add headers for Geoserver
        if self.ogc_server.auth == main.OGCSERVER_AUTH_GEOSERVER:
            headers["sec-username"] = self.user.username
            headers["sec-roles"] = ";".join(get_roles_name(self.request))

        response = self._proxy_callback(
            cache_control,
            url=_url,
            params=self.params,
            cache=use_cache,
            headers=headers,
            body=self.request.body,
        )

        if (
            self.lower_params.get("request") == "getmap"
            and not response.content_type.startswith("image/")
            and response.status_code < 400
        ):
            response.status_code = 400

        return response
Пример #5
0
    def proxy(self) -> Response:
        if self.user is not None:
            # We have a user logged in. We need to set group_id and
            # possible layer_name in the params. We set layer_name
            # when either QUERY_PARAMS or LAYERS is set in the
            # WMS params, i.e. for GetMap and GetFeatureInfo
            # requests. For GetLegendGraphic requests we do not
            # send layer_name, but MapServer should not use the DATA
            # string for GetLegendGraphic.

            role = self.user.role
            if role is not None:
                if self._get_ogc_server().auth == OGCSERVER_AUTH_STANDARD:
                    self.params["role_id"] = role.id

                    # In some application we want to display the features owned by a user
                    # than we need his id.
                    self.params["user_id"] = self.user.id  # pragma: no cover
            else:  # pragma nocover
                log.warning("The user '%s' has no role", self.user.name)

        # do not allows direct variable substitution
        for k in list(self.params.keys()):
            if k[:2].capitalize() == "S_":
                log.warning("Direct substitution not allowed ({0!s}={1!s}).".format(k, self.params[k]))
                del self.params[k]

        # add functionalities params
        self.params.update(get_mapserver_substitution_params(self.request))

        # get method
        method = self.request.method

        # we want the browser to cache GetLegendGraphic and
        # DescribeFeatureType requests
        use_cache = False

        if method == "GET":
            # For GET requests, params are added only if the self.request
            # parameter is actually provided.
            if "request" not in self.lower_params:
                self.params = {}  # pragma: no cover
            else:
                use_cache = self.lower_params["request"] in (
                    "getcapabilities",
                    "getlegendgraphic",
                    "describelayer",
                    "describefeaturetype",
                )

                # no user_id and role_id or cached queries
                if use_cache and "user_id" in self.params:
                    del self.params["user_id"]
                if use_cache and "role_id" in self.params:
                    del self.params["role_id"]

            if "service" in self.lower_params and self.lower_params["service"] == "wfs":
                _url = self._get_wfs_url()
            else:
                _url = self._get_wms_url()
        else:
            # POST means WFS
            _url = self._get_wfs_url()

        cache_control = PRIVATE_CACHE
        if method == "GET" and \
                "service" in self.lower_params and \
                self.lower_params["service"] == "wms":
            if self.lower_params["request"] in ("getmap", "getfeatureinfo"):
                cache_control = NO_CACHE
            elif self.lower_params["request"] == "getlegendgraphic":
                cache_control = PUBLIC_CACHE
        elif method == "GET" and \
                "service" in self.lower_params and \
                self.lower_params["service"] == "wfs":
            if self.lower_params["request"] == "getfeature":
                cache_control = NO_CACHE
        elif method != "GET":
            cache_control = NO_CACHE

        role = None if self.user is None else self.user.role

        headers = self._get_headers()
        # Add headers for Geoserver
        if self._get_ogc_server().auth == OGCSERVER_AUTH_GEOSERVER and \
                self.user is not None:
            headers["sec-username"] = self.user.username
            headers["sec-roles"] = role.name

        response = self._proxy_callback(
            role.id if role is not None else None, cache_control,
            url=_url, params=self.params, cache=use_cache,
            headers=headers, body=self.request.body
        )
        return response