def _create_forwarded_url(self, request_url):
        """Constructs a destination endpoint to request.

        Finds the matching URL pattern for the request_url. Anything trailing
        the pattern is appended to _forwarding_url to construct the final
        destination URL.

        Args:
            request_url: Incoming request URL from the client to be matched to
                a URL pattern and parsed to form the final destination URL.

        Returns:
            Final destination URL to which the incoming request should be
            forwarded.

        Raises:
            RequestError: The incoming request did not match any URL patterns
                for this route.

        """
        url_pattern = self._find_pattern_for_request(request_url)
        if not url_pattern:
            raise RequestError('Requested URL "{0}" did not match the '
                               'forwarding route "{1}"'.format(
                                   request_url, ', '.join(self._url_patterns)))

        url_pattern_escaped = re.escape(url_pattern)

        forwarded_url = re.subn(url_pattern_escaped, self._forwarding_url,
                                request_url, 1, re.IGNORECASE)

        return forwarded_url[0]
Example #2
0
    def _create_forwarded_urls(self, request_url):
        """Constructs the destination endpoint(s) to request.

        Finds the matching URL pattern for the request_url. Once found, the
        final destination URLs are determined based on the endpoint IDs
        specified in the request in place of the wildcard section of the URL
        pattern. Finally, anything trailing the URL pattern is appended to each
        destination URL.

        Args:
            request_url: Incoming request URL from the client to be matched to
                a URL pattern and parsed to form the final destination URL(s).

        Returns:
            List of final destination URL(s) to which the incoming request
            should be forwarded.

        Raises:
            RequestError: The incoming request did not match any URL patterns
                for this route.

        """
        # Extract endpoints from request
        url_pattern = self._find_pattern_for_request(request_url)
        url_pattern_parts = url_pattern.split(ENDPOINTS_WILDCARD)
        match_expression = re.escape(url_pattern_parts[0]) + \
            "(?P<endpoint_ids>.*)" + \
            re.escape(url_pattern_parts[1])
        endpoint_ids_group = re.match(match_expression,
                                      request_url).group("endpoint_ids")
        endpoint_ids = endpoint_ids_group.split(',')
        endpoint_ids = [urllib.unquote(e_id) for e_id in endpoint_ids]
        endpoint_ids = [e_id.strip().lower() for e_id in endpoint_ids]

        # Extract trailing portion of request URL
        trailing_route = request_url[len(url_pattern_parts[0]
                                         + endpoint_ids_group
                                         + url_pattern_parts[1]):]

        # Create final URLs to be forwarded
        endpoint_urls = []
        all_endpoints = False
        if '*' in endpoint_ids:
            all_endpoints = True

        for endpoint_id in self._endpoints:
            if all_endpoints or endpoint_id in endpoint_ids:
                url = self._endpoints[endpoint_id] + trailing_route
                endpoint_urls.append(
                    self._resolve_query_string(url, endpoint_id)
                )

        if len(endpoint_urls) == 0:
            raise RequestError('The incoming request did not specify a valid '
                               'endpoint identifier for matched route: {0}'
                               .format(url_pattern))

        return endpoint_urls
Example #3
0
    def _match_route(self, request_url):
        """Matches an incoming request to a configured route.

        Args:
            request_url: URL of the incoming request.

        Returns:
            Route matching the incoming request.

        Raises:
            RequestError: A suitable route wasn't found to handle the incoming
                request.

        """
        for route in self._routes:
            if route.match(request_url):
                return route

        raise RequestError('Unable to find a route to handle the request '
                           'to {0}'.format(request_url))