예제 #1
0
    def canonical_redirect(self, request, final_project, version_slug,
                           filename):
        """
        Return a redirect to the canonical domain including scheme.

        This is normally used HTTP -> HTTPS redirects or redirects to/from custom domains.
        """
        full_path = request.get_full_path()
        urlparse_result = urlparse(full_path)
        to = resolve(
            project=final_project,
            version_slug=version_slug,
            filename=filename,
            query_params=urlparse_result.query,
            external=hasattr(request, 'external_domain'),
        )

        if full_path == to:
            # check that we do have a response and avoid infinite redirect
            log.warning(
                'Infinite Redirect: FROM URL is the same than TO URL. url=%s',
                to,
            )
            raise InfiniteRedirectException()

        log.info('Canonical Redirect: host=%s, from=%s, to=%s',
                 request.get_host(), filename, to)
        resp = HttpResponseRedirect(to)
        resp['X-RTD-Redirect'] = getattr(request, 'canonicalize', 'unknown')
        return resp
예제 #2
0
    def canonical_redirect(self, request, final_project, version_slug,
                           filename):
        """
        Return a redirect to the canonical domain including scheme.

        The following cases are covered:

        - Redirect a custom domain from http to https (if supported)
          http://project.rtd.io/ -> https://project.rtd.io/
        - Redirect a domain to a canonical domain (http or https).
          http://project.rtd.io/ -> https://docs.test.com/
          http://project.rtd.io/foo/bar/ -> https://docs.test.com/foo/bar/
        - Redirect from a subproject domain to the main domain
          https://subproject.rtd.io/en/latest/foo -> https://main.rtd.io/projects/subproject/en/latest/foo  # noqa
          https://subproject.rtd.io/en/latest/foo -> https://docs.test.com/projects/subproject/en/latest/foo  # noqa
        """
        from_url = request.build_absolute_uri()
        parsed_from = urlparse(from_url)

        redirect_type = getattr(request, 'canonicalize', None)
        if redirect_type == REDIRECT_HTTPS:
            to = parsed_from._replace(scheme='https').geturl()
        else:
            to = resolve(
                project=final_project,
                version_slug=version_slug,
                filename=filename,
                query_params=parsed_from.query,
                external=hasattr(request, 'external_domain'),
            )
            # When a canonical redirect is done, only change the domain.
            if redirect_type == REDIRECT_CANONICAL_CNAME:
                parsed_to = urlparse(to)
                to = parsed_from._replace(
                    scheme=parsed_to.scheme,
                    netloc=parsed_to.netloc,
                ).geturl()

        if from_url == to:
            # check that we do have a response and avoid infinite redirect
            log.warning(
                'Infinite Redirect: FROM URL is the same than TO URL.',
                url=to,
            )
            raise InfiniteRedirectException()

        log.info('Canonical Redirect.',
                 host=request.get_host(),
                 from_url=filename,
                 to_url=to)
        resp = HttpResponseRedirect(to)
        resp['X-RTD-Redirect'] = getattr(request, 'canonicalize', 'unknown')
        return resp
예제 #3
0
    def get_redirect_response(self, request, redirect_path, proxito_path,
                              http_status):
        """
        Build the response for the ``redirect_path``, ``proxito_path`` and its ``http_status``.

        :returns: redirect respose with the correct path
        :rtype: HttpResponseRedirect or HttpResponsePermanentRedirect
        """

        schema, netloc, path, params, query, fragments = urlparse(proxito_path)
        # `proxito_path` doesn't include query params.
        query = urlparse(request.get_full_path()).query
        new_path = urlunparse(
            (schema, netloc, redirect_path, params, query, fragments))

        # Re-use the domain and protocol used in the current request.
        # Redirects shouldn't change the domain, version or language.
        # However, if the new_path is already an absolute URI, just use it
        new_path = request.build_absolute_uri(new_path)
        log.info(
            'Redirecting: from=%s to=%s http_status=%s',
            request.build_absolute_uri(proxito_path),
            new_path,
            http_status,
        )

        if request.build_absolute_uri(proxito_path) == new_path:
            # check that we do have a response and avoid infinite redirect
            log.warning(
                'Infinite Redirect: FROM URL is the same than TO URL. url=%s',
                new_path,
            )
            raise InfiniteRedirectException()

        if http_status and http_status == 301:
            resp = HttpResponsePermanentRedirect(new_path)
        else:
            resp = HttpResponseRedirect(new_path)

        # Add a user-visible header to make debugging easier
        resp['X-RTD-Redirect'] = 'user'
        return resp