def server_error_404_subdomain(request, template_name='404.html'): """ Handler for 404 pages on subdomains. Check if the project associated has a custom ``404.html`` and serve this page. First search for a 404 page in the current version, then continues with the default version and finally, if none of them are found, the Read the Docs default page (Maze Found) is rendered by Django and served. """ def resolve_404_path(project, version_slug=None, language=None, filename='404.html'): """ Helper to resolve the path of ``404.html`` for project. The resolution is based on ``project`` object, version slug and language. :returns: tuple containing the (basepath, filename) :rtype: tuple """ filename = resolve_path( project, version_slug=version_slug, language=language, filename=filename, subdomain=True, # subdomain will make it a "full" path without a URL prefix ) # This breaks path joining, by ignoring the root when given an "absolute" path if filename[0] == '/': filename = filename[1:] version = None if version_slug: version_qs = project.versions.filter(slug=version_slug) if version_qs.exists(): version = version_qs.first() private = any([ version and version.privacy_level == PRIVATE, not version and project.privacy_level == PRIVATE, ]) if private: symlink = PrivateSymlink(project) else: symlink = PublicSymlink(project) basepath = symlink.project_root fullpath = os.path.join(basepath, filename) return (basepath, filename, fullpath) project, full_path = project_and_path_from_request(request, request.get_full_path()) if project: language = None version_slug = None schema, netloc, path, params, query, fragments = urlparse(full_path) if not project.single_version: language, version_slug, path = language_and_version_from_path(path) # Firstly, attempt to serve the 404 of the current version (version_slug) # Secondly, try to serve the 404 page for the default version # (project.get_default_version()) for slug in (version_slug, project.get_default_version()): for tryfile in ('404.html', '404/index.html'): basepath, filename, fullpath = resolve_404_path(project, slug, language, tryfile) if os.path.exists(fullpath): log.debug( 'serving 404.html page current version: [project: %s] [version: %s]', project.slug, slug, ) r = static_serve(request, filename, basepath) r.status_code = 404 return r # Finally, return the default 404 page generated by Read the Docs r = render(request, template_name) r.status_code = 404 return r
def server_error_404_subdomain(request, template_name='404.html'): """ Handler for 404 pages on subdomains. Check if the project associated has a custom ``404.html`` and serve this page. First search for a 404 page in the current version, then continues with the default version and finally, if none of them are found, the Read the Docs default page (Maze Found) is rendered by Django and served. """ def resolve_404_path(project, version_slug=None, language=None): """ Helper to resolve the path of ``404.html`` for project. The resolution is based on ``project`` object, version slug and language. :returns: tuple containing the (basepath, filename) :rtype: tuple """ filename = resolve_path( project, version_slug=version_slug, language=language, filename='404.html', subdomain=True, # subdomain will make it a "full" path without a URL prefix ) # This breaks path joining, by ignoring the root when given an "absolute" path if filename[0] == '/': filename = filename[1:] version = None if version_slug: version_qs = project.versions.filter(slug=version_slug) if version_qs.exists(): version = version_qs.first() private = any([ version and version.privacy_level == PRIVATE, not version and project.privacy_level == PRIVATE, ]) if private: symlink = PrivateSymlink(project) else: symlink = PublicSymlink(project) basepath = symlink.project_root fullpath = os.path.join(basepath, filename) return (basepath, filename, fullpath) project, full_path = project_and_path_from_request(request, request.get_full_path()) if project: language = None version_slug = None schema, netloc, path, params, query, fragments = urlparse(full_path) if not project.single_version: language, version_slug, path = language_and_version_from_path(path) # Firstly, attempt to serve the 404 of the current version (version_slug) # Secondly, try to serve the 404 page for the default version (project.get_default_version()) for slug in (version_slug, project.get_default_version()): basepath, filename, fullpath = resolve_404_path(project, slug, language) if os.path.exists(fullpath): log.debug( 'serving 404.html page current version: [project: %s] [version: %s]', project.slug, slug, ) r = _serve_file(request, filename, basepath) r.status_code = 404 return r # Finally, return the default 404 page generated by Read the Docs r = render(request, template_name) r.status_code = 404 return r