Exemple #1
0
def cname(request):
    """
    Get the slug that a particular hostname resolves to.
    This is useful for debugging your DNS settings,
    or for getting the backing project name on Read the Docs for a URL.

    Example::

        GET https://readthedocs.org/api/v2/cname/?host=docs.python-requests.org

    This will return information about ``docs.python-requests.org``
    """
    host = request.GET.get('host')
    if not host:
        return Response({'error': 'host GET arg required'}, status=status.HTTP_400_BAD_REQUEST)
    host = clean_url(host)
    slug = cname_to_slug(host)
    return Response({
        'host': host,
        'slug': slug,
    })
def cname(request):
    """
    Get the slug that a particular hostname resolves to.
    This is useful for debugging your DNS settings,
    or for getting the backing project name on Read the Docs for a URL.

    Example::

        GET https://readthedocs.org/api/v2/cname/?host=docs.python-requests.org

    This will return information about ``docs.python-requests.org``
    """
    host = request.GET.get('host')
    if not host:
        return Response({'error': 'host GET arg required'}, status=status.HTTP_400_BAD_REQUEST)
    host = clean_url(host)
    slug = cname_to_slug(host)
    return Response({
        'host': host,
        'slug': slug,
    })
Exemple #3
0
    def process_request(self, request):
        """Process requests for unhandled domains

        If the request is not for our ``PUBLIC_DOMAIN``, or if ``PUBLIC_DOMAIN``
        is not set and the request is for a subdomain on ``PRODUCTION_DOMAIN``,
        process the request as a request a documentation project.
        """
        if not getattr(settings, 'USE_SUBDOMAIN', False):
            return None

        full_host = host = request.get_host().lower()
        path = request.get_full_path()
        log_kwargs = dict(host=host, path=path)
        public_domain = getattr(settings, 'PUBLIC_DOMAIN', None)
        production_domain = getattr(settings, 'PRODUCTION_DOMAIN',
                                    'readthedocs.org')

        if public_domain is None:
            public_domain = production_domain
        if ':' in host:
            host = host.split(':')[0]
        domain_parts = host.split('.')

        # Serve subdomains - but don't depend on the production domain only having 2 parts
        if len(domain_parts) == len(public_domain.split('.')) + 1:
            subdomain = domain_parts[0]
            is_www = subdomain.lower() == 'www'
            if not is_www and (
                    # Support ports during local dev
                    public_domain in host or public_domain in full_host):
                request.subdomain = True
                request.slug = subdomain
                request.urlconf = SUBDOMAIN_URLCONF
                return None

        # Serve CNAMEs
        if (public_domain not in host and production_domain not in host
                and 'localhost' not in host and 'testserver' not in host):
            request.cname = True
            domains = Domain.objects.filter(domain=host)
            if domains.count():
                for domain in domains:
                    if domain.domain == host:
                        request.slug = domain.project.slug
                        request.urlconf = SUBDOMAIN_URLCONF
                        request.domain_object = True
                        log.debug(
                            LOG_TEMPLATE.format(
                                msg='Domain Object Detected: %s' %
                                domain.domain,
                                **log_kwargs))
                        break
            if (not hasattr(request, 'domain_object')
                    and 'HTTP_X_RTD_SLUG' in request.META):
                request.slug = request.META['HTTP_X_RTD_SLUG'].lower()
                request.urlconf = SUBDOMAIN_URLCONF
                request.rtdheader = True
                log.debug(
                    LOG_TEMPLATE.format(msg='X-RTD-Slug header detected: %s' %
                                        request.slug,
                                        **log_kwargs))
            # Try header first, then DNS
            elif not hasattr(request, 'domain_object'):
                try:
                    slug = cache.get(host)
                    if not slug:
                        slug = cname_to_slug(host)
                        cache.set(host, slug, 60 * 60)
                        # Cache the slug -> host mapping permanently.
                        log.debug(
                            LOG_TEMPLATE.format(msg='CNAME cached: %s->%s' %
                                                (slug, host),
                                                **log_kwargs))
                    request.slug = slug
                    request.urlconf = SUBDOMAIN_URLCONF
                    log.debug(
                        LOG_TEMPLATE.format(msg='CNAME detected: %s' %
                                            request.slug,
                                            **log_kwargs))
                except:
                    # Some crazy person is CNAMEing to us. 404.
                    log.exception(
                        LOG_TEMPLATE.format(msg='CNAME 404', **log_kwargs))
                    raise Http404(_('Invalid hostname'))
        # Google was finding crazy www.blah.readthedocs.org domains.
        # Block these explicitly after trying CNAME logic.
        if len(domain_parts) > 3 and not settings.DEBUG:
            # Stop www.fooo.readthedocs.org
            if domain_parts[0] == 'www':
                log.debug(
                    LOG_TEMPLATE.format(msg='404ing long domain',
                                        **log_kwargs))
                return HttpResponseBadRequest(_('Invalid hostname'))
            log.debug(
                LOG_TEMPLATE.format(msg='Allowing long domain name',
                                    **log_kwargs))
            # raise Http404(_('Invalid hostname'))
        # Normal request.
        return None
Exemple #4
0
    def process_request(self, request):
        """
        Process requests for unhandled domains.

        If the request is not for our ``PUBLIC_DOMAIN``, or if ``PUBLIC_DOMAIN``
        is not set and the request is for a subdomain on ``PRODUCTION_DOMAIN``,
        process the request as a request a documentation project.
        """
        if not getattr(settings, 'USE_SUBDOMAIN', False):
            return None

        full_host = host = request.get_host().lower()
        path = request.get_full_path()
        log_kwargs = dict(host=host, path=path)
        public_domain = getattr(settings, 'PUBLIC_DOMAIN', None)
        production_domain = getattr(
            settings,
            'PRODUCTION_DOMAIN',
            'readthedocs.org'
        )

        if public_domain is None:
            public_domain = production_domain
        if ':' in host:
            host = host.split(':')[0]
        domain_parts = host.split('.')

        # Serve subdomains - but don't depend on the production domain only having 2 parts
        if len(domain_parts) == len(public_domain.split('.')) + 1:
            subdomain = domain_parts[0]
            is_www = subdomain.lower() == 'www'
            if not is_www and (
                # Support ports during local dev
                public_domain in host or public_domain in full_host
            ):
                request.subdomain = True
                request.slug = subdomain
                request.urlconf = SUBDOMAIN_URLCONF
                return None

        # Serve CNAMEs
        if (public_domain not in host and
                production_domain not in host and
                'localhost' not in host and
                'testserver' not in host):
            request.cname = True
            domains = Domain.objects.filter(domain=host)
            if domains.count():
                for domain in domains:
                    if domain.domain == host:
                        request.slug = domain.project.slug
                        request.urlconf = SUBDOMAIN_URLCONF
                        request.domain_object = True
                        log.debug(LOG_TEMPLATE.format(
                            msg='Domain Object Detected: %s' % domain.domain,
                            **log_kwargs))
                        break
            if (not hasattr(request, 'domain_object') and
                    'HTTP_X_RTD_SLUG' in request.META):
                request.slug = request.META['HTTP_X_RTD_SLUG'].lower()
                request.urlconf = SUBDOMAIN_URLCONF
                request.rtdheader = True
                log.debug(LOG_TEMPLATE.format(
                    msg='X-RTD-Slug header detected: %s' % request.slug,
                    **log_kwargs))
            # Try header first, then DNS
            elif not hasattr(request, 'domain_object'):
                try:
                    slug = cache.get(host)
                    if not slug:
                        slug = cname_to_slug(host)
                        cache.set(host, slug, 60 * 60)
                        # Cache the slug -> host mapping permanently.
                        log.debug(LOG_TEMPLATE.format(
                            msg='CNAME cached: %s->%s' % (slug, host),
                            **log_kwargs))
                    request.slug = slug
                    request.urlconf = SUBDOMAIN_URLCONF
                    log.debug(LOG_TEMPLATE.format(
                        msg='CNAME detected: %s' % request.slug,
                        **log_kwargs))
                except:
                    # Some crazy person is CNAMEing to us. 404.
                    log.exception(LOG_TEMPLATE.format(msg='CNAME 404', **log_kwargs))
                    raise Http404(_('Invalid hostname'))
        # Google was finding crazy www.blah.readthedocs.org domains.
        # Block these explicitly after trying CNAME logic.
        if len(domain_parts) > 3 and not settings.DEBUG:
            # Stop www.fooo.readthedocs.org
            if domain_parts[0] == 'www':
                log.debug(LOG_TEMPLATE.format(msg='404ing long domain', **log_kwargs))
                return HttpResponseBadRequest(_('Invalid hostname'))
            log.debug(LOG_TEMPLATE.format(msg='Allowing long domain name', **log_kwargs))
            # raise Http404(_('Invalid hostname'))
        # Normal request.
        return None