コード例 #1
0
def serve_protected_file(request,
                         path,
                         document_root=None,
                         show_indexes=False):
    user_file = get_object_or_404(File, file=path)

    if user_file.user_id != request.user.id:
        raise Http404

    path = posixpath.normpath(path).lstrip('/')
    fullpath = Path(safe_join(document_root, path))

    if fullpath.is_dir():
        if show_indexes:
            return directory_index(path, fullpath)

        raise Http404("Directory indexes are not allowed here.")

    if not fullpath.exists():
        raise Http404('“%(path)s” does not exist' % {'path': fullpath})

    # Respect the If-Modified-Since header.
    statobj = fullpath.stat()
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj.st_mtime, statobj.st_size):
        return HttpResponseNotModified()

    content_type, encoding = mimetypes.guess_type(str(fullpath))
    content_type = content_type or 'application/octet-stream'

    response = FileResponse(fullpath.open('rb'), content_type=content_type)
    response["Last-Modified"] = http_date(statobj.st_mtime)

    if encoding:
        response["Content-Encoding"] = encoding

    return response
コード例 #2
0
    def get(self, request, *args, **kwargs):
        filename = self.get_filename().format(
            filename=self.kwargs.get('filename', ''),
            media=settings.MEDIA_ROOT,
            static=settings.STATIC_ROOT,
        )
        if not os.path.exists(filename) or os.path.isdir(filename):
            raise Http404(_('No file found matching the query'))

        filestats = os.stat(filename)
        if not self.was_modified(filename, filestats):
            return HttpResponseNotModified()

        charset = self.get_charset(filename, filestats)
        mimetype = self.get_mimetype(filename, filestats)
        encoding = self.get_encoding(filename, filestats)

        try:
            fileobj = open(filename, 'rb')
        except IOError:
            raise Http404(_('No file found matching the query'))

        if not charset and mimetype and not mimetype.startswith('text'):
            content_type = mimetype or 'application/octet-stream'
        else:
            content_type = '{0}; charset={1}'.format(
                mimetype or settings.DEFAULT_CONTENT_TYPE,
                charset or settings.DEFAULT_CHARSET,
            )
        response = FileResponse(fileobj, content_type=content_type)
        response['Last-Modified'] = http_date(filestats.st_mtime)
        if stat.S_ISREG(filestats.st_mode):
            response['Content-Length'] = filestats.st_size
        if encoding:
            response['Content-Encoding'] = encoding

        return response
コード例 #3
0
ファイル: static.py プロジェクト: tbbug/django
def serve(request, path, document_root=None, show_indexes=False):
    """
    Serve static files below a given point in the directory structure.

    To use, put a URL pattern such as::

        from django.views.static import serve

        path('<path:path>', serve, {'document_root': '/path/to/my/files/'})

    in your URLconf. You must provide the ``document_root`` param. You may
    also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
    of the directory.  This index view will use the template hardcoded below,
    but if you'd like to override it, you can create a template called
    ``static/directory_index.html``.
    """
    path = posixpath.normpath(path).lstrip("/")
    fullpath = Path(safe_join(document_root, path))
    if fullpath.is_dir():
        if show_indexes:
            return directory_index(path, fullpath)
        raise Http404(_("Directory indexes are not allowed here."))
    if not fullpath.exists():
        raise Http404(_("“%(path)s” does not exist") % {"path": fullpath})
    # Respect the If-Modified-Since header.
    statobj = fullpath.stat()
    if not was_modified_since(
        request.META.get("HTTP_IF_MODIFIED_SINCE"), statobj.st_mtime, statobj.st_size
    ):
        return HttpResponseNotModified()
    content_type, encoding = mimetypes.guess_type(str(fullpath))
    content_type = content_type or "application/octet-stream"
    response = FileResponse(fullpath.open("rb"), content_type=content_type)
    response.headers["Last-Modified"] = http_date(statobj.st_mtime)
    if encoding:
        response.headers["Content-Encoding"] = encoding
    return response
コード例 #4
0
 def get(self, request, *args, **kwargs):
     exporter = self.get_exporter(request)
     lang_code = request.GET.get("lang")
     if lang_code and lang_code in request.event.locales:
         activate(lang_code)
     elif "lang" in request.GET:
         activate(request.event.locale)
     with suppress(Exception):
         exporter.schedule = self.schedule
         exporter.is_orga = getattr(self.request, "is_orga", False)
         file_name, file_type, data = exporter.render()
         etag = hashlib.sha1(str(data).encode()).hexdigest()
         if "If-None-Match" in request.headers:
             if request.headers["If-None-Match"] == etag:
                 return HttpResponseNotModified()
         response = HttpResponse(data, content_type=file_type)
         response["ETag"] = etag
         if file_type not in ["application/json", "text/xml"]:
             response[
                 "Content-Disposition"] = f'attachment; filename="{safe_filename(file_name)}"'
         if exporter.cors:
             response["Access-Control-Allow-Origin"] = exporter.cors
         return response
     raise Http404()
コード例 #5
0
def _not_modified(request, response=None):
    new_response = HttpResponseNotModified()
    if response:
        # Preserve the headers required by Section 4.1 of RFC 7232, as well as
        # Last-Modified.
        for header in (
                "Cache-Control",
                "Content-Location",
                "Date",
                "ETag",
                "Expires",
                "Last-Modified",
                "Vary",
        ):
            if header in response:
                new_response[header] = response[header]

        # Preserve cookies as per the cookie specification: "If a proxy server
        # receives a response which contains a Set-cookie header, it should
        # propagate the Set-cookie header to the client, regardless of whether
        # the response was 304 (Not Modified) or 200 (OK).
        # https://curl.haxx.se/rfc/cookie_spec.html
        new_response.cookies = response.cookies
    return new_response
コード例 #6
0
ファイル: views_get.py プロジェクト: AG-Schumann/webmonitor
def get_host_detail(request, host_name=""):
    ret = {'html': {}, 'value': {}}
    if host_name not in base.db.distinct('common', 'hosts', 'hostname'):
        return HttpResponseNotModified()
    doc = base.db.get_host_setting(host_name)
    ret['value']['sysmon_timer'] = doc['sysmon_timer']
    default = doc['default']
    ret['value']['host_name'] = host_name
    ret['html'][
        'grafana'] = f'http://10.4.73.172:3000/d/WzsbkBwWk/system-mon?refresh=5s&kiosk=tv&var-hostname={host_name}'
    ret['html']['host_legend'] = host_name
    ret['html']['default_table'] = '<tr><td colspan="2">Default</td></tr>'
    for sensor in default:
        ret['html']['default_table'] += f'<tr><td>{sensor}</td>'
        ret['html'][
            'default_table'] += f'<td><input type="checkbox" name="checkbox_{sensor}" value="{sensor}" checked></td></tr>'
    unmonitored = base.db.get_unmonitored_sensors()
    ret['html'][
        'unmonitored_table'] = '<tr><td colspan="2">Unmonitored</td></tr>'
    for sensor in unmonitored:
        ret['html']['unmonitored_table'] += f'<tr><td>{sensor}</td>'
        ret['html'][
            'unmonitored_table'] += f'<td><input type="checkbox" name="checkbox_{sensor}" value="{sensor}"></td></tr>'
    return JsonResponse(ret)
コード例 #7
0
ファイル: api.py プロジェクト: juagargi/scionlab
    def get(self, request, *args, **kwargs):
        host = self.get_object()
        if 'secret' not in request.GET \
                or not hmac.compare_digest(request.GET['secret'], host.secret):
            return HttpResponseForbidden()
        if 'version' in request.GET:
            version_str = request.GET['version']
            if not version_str.isnumeric():
                return HttpResponseBadRequest()
            version = int(version_str)
            if version >= host.config_version:
                return HttpResponseNotModified()

        if config_tar.is_empty_config(host):
            return HttpResponse(status=204)

        # All good, return generate and return the config
        # Use the response as file-like object to write the tar
        filename = '{host}_v{version}.tar.gz'.format(
            host=host.path_str(), version=host.config_version)
        resp = HttpResponseAttachment(filename=filename,
                                      content_type='application/gzip')
        config_tar.generate_host_config_tar(host, resp)
        return resp
コード例 #8
0
 def get(self, request, *args, **kwargs):
     id = kwargs.get('id', None)
     if id is not None:
         query = IconData.objects.filter(icon__id=kwargs['id'])
     else:
         collection = kwargs.get('collection')
         icon = kwargs.get('icon')
         query = IconData.objects.filter(icon__collection__slug=collection).filter(icon__slug=icon)
     params = request.GET.copy()
     version = params.pop('version', None)
     if version:
         icon = query.filter(version=version)[0]
     else:
         icon = query.latest('version')
     stale = request.META.get('HTTP_IF_MODIFIED_SINCE', None)
     if stale:
         if icon.modified.replace(microsecond=0, tzinfo=None) <= datetime.strptime(stale, _date_fmt):
             return HttpResponseNotModified()
     svg = icon.svg
     if params:
         svg = process_svg(svg, params)
     resp = HttpResponse(svg, content_type='image/svg+xml')
     resp['Last-Modified'] = icon.modified.strftime(_date_fmt)
     return resp
コード例 #9
0
    def serve(self, request, relative_path):
        # the following code is largely borrowed from `django.views.static.serve`
        # and django-filetransfers: filetransfers.backends.default

        full_path = self.get_full_path(relative_path)

        if not os.path.exists(full_path):
            raise Http404('"{0}" does not exist'.format(full_path))

        # Respect the If-Modified-Since header.
        content_type = self.get_mimetype(relative_path)
        statobj = os.stat(full_path)

        if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                                  statobj[stat.ST_MTIME],
                                  statobj[stat.ST_SIZE]):
            response = HttpResponseNotModified(content_type=content_type)
        else:
            response = HttpResponse(open(full_path, 'rb').read(),
                                    content_type=content_type)
            response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
            response = self.prepare_response(request, response, relative_path)

        return response
コード例 #10
0
def send_file_response(request, path, name, content_type, attachment=True):
    # Based on: django.views.static.serve

    # FIXME: If running on real Apache server, we should use "X-SENDFILE" header to let Apache
    # serve the file. It's much faster. Possibly will be fixed in Django 1.8.
    # See: http://django.readthedocs.org/en/latest/ref/request-response.html#django.http.FileResponse

    # FIXME: "Content-Disposition" filename is very fragile if contains non-ASCII characters.
    # Current implementation works on Firefox, but probably fails on other browsers. We should test
    # and fix it for them and/or sanitize and normalize file names.
    statobj = os.stat(path)
    if not stat.S_ISREG(statobj.st_mode):
        raise OSError(u'Not a regular file: {}'.format(path))
    http_header = request.META.get(u'HTTP_IF_MODIFIED_SINCE')
    if not was_modified_since(http_header, statobj.st_mtime, statobj.st_size):
        return HttpResponseNotModified()
    response = FileResponse(open(path, u'rb'), content_type=content_type)
    response[u'Last-Modified'] = http_date(statobj.st_mtime)
    response[u'Content-Length'] = statobj.st_size
    if attachment:
        response[
            u'Content-Disposition'] = "attachment; filename*=UTF-8''{}".format(
                urlquote(name))
    return response
コード例 #11
0
ファイル: views.py プロジェクト: iamr0cka/qabel-drop
    def _get_drops(self, drop_id):
        """Return (response, drops) for a request. response are errors and no-content/not-modified, otherwise None."""
        if not check_drop_id(drop_id):
            return error('Invalid drop id'), None

        drops = Drop.objects.filter(drop_id=drop_id)

        try:
            have_since, since = self.get_if_modified_since()
        except ValueError as value_error:
            logger.warning('Could not parse modified-since header pack: %s',
                           value_error)
            have_since, since = False, None

        if have_since:
            drops = drops.filter(created_at__gt=since)

        if not drops.exists():
            if have_since:
                return HttpResponseNotModified(), None
            else:
                return HttpResponse(status=status.HTTP_204_NO_CONTENT), None

        return None, list(drops)
コード例 #12
0
def dynamic_css(request, css):
	if not _dynamic_cssmap.has_key(css):
		raise Http404('CSS not found')
	files = _dynamic_cssmap[css]
	resp = HttpResponse(content_type='text/css')

	# We honor if-modified-since headers by looking at the most recently
	# touched CSS file.
	latestmod = 0
	for fn in files:
		try:
			stime = os.stat(fn).st_mtime
			if latestmod < stime:
				latestmod = stime
		except OSError:
			# If we somehow referred to a file that didn't exist, or
			# one that we couldn't access.
			raise Http404('CSS (sub) not found')
	if request.META.has_key('HTTP_IF_MODIFIED_SINCE'):
		# This code is mostly stolen from django :)
		matches = re.match(r"^([^;]+)(; length=([0-9]+))?$",
						   request.META.get('HTTP_IF_MODIFIED_SINCE'),
						   re.IGNORECASE)
		header_mtime = parse_http_date(matches.group(1))
		# We don't do length checking, just the date
		if int(latestmod) <= header_mtime:
			return HttpResponseNotModified(content_type='text/css')
	resp['Last-Modified'] = http_date(latestmod)

	for fn in files:
		with open(fn) as f:
			resp.write("/* %s */\n" % fn)
			resp.write(f.read())
			resp.write("\n")

	return resp
コード例 #13
0
def static_serve(request):
    path = request.GET.get('p') or ''
    file_path = posixpath.normpath(path)

    if not os.path.exists(file_path):
        raise Http404('"%s" does not exist' % file_path)
    if os.path.isdir(file_path):
        raise Http404('"%s" is dir' % file_path)

    statobj = os.stat(file_path)
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj.st_mtime, statobj.st_size):
        return HttpResponseNotModified()

    content_type, encoding = mimetypes.guess_type(file_path)
    content_type = content_type or 'application/octet-stream'
    response = FileResponse(open(file_path, 'rb'), content_type=content_type)
    response["Last-Modified"] = http_date(statobj.st_mtime)

    if stat.S_ISREG(statobj.st_mode):
        response["Content-Length"] = statobj.st_size
    if encoding:
        response["Content-Encoding"] = encoding
    return response
コード例 #14
0
    def serve(private_file):
        # Support If-Last-Modified
        if sys.version_info >= (3, ):
            mtime = private_file.modified_time.timestamp()
        else:
            mtime = time.mktime(private_file.modified_time.timetuple())
        size = private_file.size
        if not was_modified_since(
                private_file.request.META.get('HTTP_IF_MODIFIED_SINCE'), mtime,
                size):
            return HttpResponseNotModified()

        # As of Django 1.8, FileResponse triggers 'wsgi.file_wrapper' in Django's WSGIHandler.
        # This uses efficient file streaming, such as sendfile() in uWSGI.
        # When the WSGI container doesn't provide 'wsgi.file_wrapper', it submits the file in 4KB chunks.
        if private_file.request.method == 'HEAD':
            # Avoid reading the file at all
            response = HttpResponse()
        else:
            response = FileResponse(private_file.open())
        response['Content-Type'] = private_file.content_type
        response['Content-Length'] = size
        response["Last-Modified"] = http_date(mtime)
        return response
コード例 #15
0
 def get(self, request, download_target, filename):
     """
     The view class for downloading files 2019-04-09
     :param request:
     :return: HttpResponse
     """
     if download_target == 'file':
         path = UPLOAD_DIR + filename
     else:
         path = PDF_DIR + filename
     if not os.path.isfile(path):
         raise Http404('"%s" does not exist' % path)
     stat = os.stat(path)
     content_type, encoding = mimetypes.guess_type(path)
     content_type = content_type or 'application/octet-stream'
     if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                               stat.st_mtime, stat.st_size):
         return HttpResponseNotModified(content_type=content_type)
     response = HttpResponse(open(path, 'rb').read(), content_type=content_type)
     response['Last-Modified'] = http_date(stat.st_mtime)
     response['Content-Length'] = stat.st_size
     if encoding:
         response['Content-Encoding'] = encoding
     return response
コード例 #16
0
    def get(self, request, *args, **kwargs):
        """Handle GET requests for this view.

        This will create the renderer for the diff fragment, render it, and
        return it.

        If there's an error when rendering the diff fragment, an error page
        will be rendered and returned instead.

        Args:
            request (django.http.HttpRequest):
                The HTTP request.

            *args (tuple):
                Additional positional arguments for the view.

            **kwargs (dict):
                Additional keyword arguments for the view.

        Returns:
            django.http.HttpResponse:
            A response containing the rendered fragment.
        """
        filediff_id = kwargs.get('filediff_id')
        interfilediff_id = kwargs.get('interfilediff_id')
        chunk_index = kwargs.get('chunk_index')

        try:
            renderer_settings = self._get_renderer_settings(**kwargs)
            etag = self.make_etag(renderer_settings, **kwargs)

            if etag_if_none_match(request, etag):
                return HttpResponseNotModified()

            diff_info_or_response = self.process_diffset_info(**kwargs)

            if isinstance(diff_info_or_response, HttpResponse):
                return diff_info_or_response
        except Http404:
            raise
        except Exception as e:
            logging.exception(
                '%s.get: Error when processing diffset info '
                'for filediff ID=%s, interfilediff ID=%s, '
                'chunk_index=%s: %s',
                self.__class__.__name__,
                filediff_id,
                interfilediff_id,
                chunk_index,
                e,
                request=request)

            return exception_traceback(self.request, e,
                                       self.error_template_name)

        kwargs.update(diff_info_or_response)

        try:
            context = self.get_context_data(**kwargs)

            renderer = self.create_renderer(
                context=context,
                renderer_settings=renderer_settings,
                *args,
                **kwargs)
            response = renderer.render_to_response(request)
        except PatchError as e:
            logging.warning(
                '%s.get: PatchError when rendering diffset for filediff '
                'ID=%s, interfilediff ID=%s, chunk_index=%s: %s',
                self.__class__.__name__,
                filediff_id,
                interfilediff_id,
                chunk_index,
                e,
                request=request)

            try:
                url_kwargs = {
                    key: kwargs[key]
                    for key in ('chunk_index', 'interfilediff_id',
                                'review_request_id', 'filediff_id', 'revision',
                                'interdiff_revision')
                    if key in kwargs and kwargs[key] is not None
                }

                bundle_url = local_site_reverse('patch-error-bundle',
                                                kwargs=url_kwargs,
                                                request=request)
            except NoReverseMatch:
                # We'll sometimes see errors about this failing to resolve when
                # web crawlers start accessing fragment URLs without the proper
                # attributes. Ignore them.
                bundle_url = ''

            if e.rejects:
                lexer = get_lexer_by_name('diff')
                formatter = HtmlFormatter()
                rejects = highlight(e.rejects, lexer, formatter)
            else:
                rejects = None

            return HttpResponseServerError(
                render_to_string(
                    self.patch_error_template_name,
                    RequestContext(
                        request, {
                            'bundle_url': bundle_url,
                            'file': diff_info_or_response['diff_file'],
                            'filename': os.path.basename(e.filename),
                            'patch_output': e.error_output,
                            'rejects': mark_safe(rejects),
                        })))
        except FileNotFoundError as e:
            return HttpResponseServerError(
                render_to_string(
                    self.error_template_name,
                    RequestContext(request, {
                        'error': e,
                        'file': diff_info_or_response['diff_file'],
                    })))
        except Exception as e:
            logging.exception(
                '%s.get: Error when rendering diffset for '
                'filediff ID=%s, interfilediff ID=%s, '
                'chunkindex=%s: %s',
                self.__class__.__name__,
                filediff_id,
                interfilediff_id,
                chunk_index,
                e,
                request=request)

            return exception_traceback(self.request,
                                       e,
                                       self.error_template_name,
                                       extra_context={
                                           'file':
                                           diff_info_or_response['diff_file'],
                                       })

        if response.status_code == 200:
            set_etag(response, etag)

        return response
コード例 #17
0
        def inner(request, *args, **kwargs):
            # Get HTTP request headers
            if_modified_since = request.META.get("HTTP_IF_MODIFIED_SINCE")
            if_none_match = request.META.get("HTTP_IF_NONE_MATCH")
            if_match = request.META.get("HTTP_IF_MATCH")
            if if_none_match or if_match:
                # There can be more than one ETag in the request, so we
                # consider the list of values.
                try:
                    etags = parse_etags(if_none_match or if_match)
                except ValueError:
                    # In case of invalid etag ignore all ETag headers.
                    # Apparently Opera sends invalidly quoted headers at times
                    # (we should be returning a 400 response, but that's a
                    # little extreme) -- this is Django bug #10681.
                    if_none_match = None
                    if_match = None

            # Compute values (if any) for the requested resource.
            if etag_func:
                res_etag = etag_func(request, *args, **kwargs)
            else:
                res_etag = None
            if last_modified_func:
                dt = last_modified_func(request, *args, **kwargs)
                if dt:
                    res_last_modified = formatdate(timegm(
                        dt.utctimetuple()))[:26] + 'GMT'
                else:
                    res_last_modified = None
            else:
                res_last_modified = None

            response = None
            if not ((if_match and (if_modified_since or if_none_match)) or
                    (if_match and if_none_match)):
                # We only get here if no undefined combinations of headers are
                # specified.
                if ((if_none_match and
                     (res_etag in etags or "*" in etags and res_etag))
                        and (not if_modified_since
                             or res_last_modified == if_modified_since)):
                    if request.method in ("GET", "HEAD"):
                        response = HttpResponseNotModified()
                    else:
                        logger.warning('Precondition Failed: %s' %
                                       request.path,
                                       extra={
                                           'status_code': 412,
                                           'request': request
                                       })
                        response = HttpResponse(status=412)
                elif if_match and ((not res_etag and "*" in etags) or
                                   (res_etag and res_etag not in etags)):
                    logger.warning('Precondition Failed: %s' % request.path,
                                   extra={
                                       'status_code': 412,
                                       'request': request
                                   })
                    response = HttpResponse(status=412)
                elif (not if_none_match and if_modified_since
                      and request.method == "GET"
                      and res_last_modified == if_modified_since):
                    response = HttpResponseNotModified()

            if response is None:
                response = func(request, *args, **kwargs)

            # Set relevant headers on the response if they don't already exist.
            if res_last_modified and not response.has_header('Last-Modified'):
                response['Last-Modified'] = res_last_modified
            if res_etag and not response.has_header('ETag'):
                response['ETag'] = quote_etag(res_etag)

            return response
コード例 #18
0
def plugin_static_serve(request, plugin, path, show_indexes=False):
    """
    Serve static files below a given point in the directory structure.

    To use, put a URL pattern such as::

        (r'^(?P<path>.*)$', 'django.views.static.serve', {'document_root' : '/path/to/my/files/'})

    in your URLconf. You must provide the ``document_root`` param. You may
    also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
    of the directory.  This index view will use the template hardcoded below,
    but if you'd like to override it, you can create a template called
    ``static/directory_index.html``.
    """

    import mimetypes
    import os
    import posixpath
    import stat
    from six.moves.urllib.request import unquote

    from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
    from django.utils.http import http_date
    from django.views.static import was_modified_since, directory_index

    from django.conf import settings

    document_root = os.path.join(settings.PROJECT_ROOT, 'plugins', plugin,
                                 'media')

    # Clean up given path to only allow serving files below document_root.
    path = posixpath.normpath(unquote(path))
    path = path.lstrip('/')
    newpath = ''
    for part in path.split('/'):
        if not part:
            # Strip empty path components.
            continue
        drive, part = os.path.splitdrive(part)
        head, part = os.path.split(part)
        if part in (os.curdir, os.pardir):
            # Strip '.' and '..' in path.
            continue
        newpath = os.path.join(newpath, part).replace('\\', '/')

    if newpath and path != newpath:
        return HttpResponseRedirect(newpath)
    fullpath = os.path.join(document_root, newpath)

    if os.path.isdir(fullpath):
        if show_indexes:
            return directory_index(newpath, fullpath)
        raise Http404(_("Directory indexes are not allowed here."))
    if not os.path.exists(fullpath):
        raise Http404('"%s" does not exist' % fullpath)

    # Respect the If-Modified-Since header.
    statobj = os.stat(fullpath)
    mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
        return HttpResponseNotModified(content_type=mimetype)
    contents = open(fullpath, 'rb').read()
    response = HttpResponse(contents, content_type=mimetype)
    response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
    response["Content-Length"] = len(contents)
    return response
コード例 #19
0
ファイル: tests.py プロジェクト: suhailvs/django
 def test_not_modified_repr(self):
     response = HttpResponseNotModified()
     self.assertEqual(repr(response),
                      '<HttpResponseNotModified status_code=304>')
コード例 #20
0
    def process_request(self, request):
        """Process the given request"""
        if self.is_asset_request(request):
            # Make sure we can convert this request into a location.
            if AssetLocator.CANONICAL_NAMESPACE in request.path:
                request.path = request.path.replace('block/', 'block@', 1)
            try:
                loc = StaticContent.get_location_from_path(request.path)
            except (InvalidLocationError, InvalidKeyError):
                return HttpResponseBadRequest()

            # Try and load the asset.
            content = None
            try:
                content = self.load_asset_from_location(loc)
            except (ItemNotFoundError, NotFoundError):
                return HttpResponseNotFound()

            # Set the basics for this request.
            newrelic.agent.add_custom_parameter('course_id', loc.course_key)
            newrelic.agent.add_custom_parameter('org', loc.org)
            newrelic.agent.add_custom_parameter('contentserver.path', loc.path)

            # Figure out if this is a CDN using us as the origin.
            is_from_cdn = StaticContentServer.is_cdn_request(request)
            newrelic.agent.add_custom_parameter('contentserver.from_cdn',
                                                True if is_from_cdn else False)

            # Check if this content is locked or not.
            locked = self.is_content_locked(content)
            newrelic.agent.add_custom_parameter('contentserver.locked',
                                                True if locked else False)

            # Check that user has access to the content.
            if not self.is_user_authorized(request, content, loc):
                return HttpResponseForbidden('Unauthorized')

            # Figure out if the client sent us a conditional request, and let them know
            # if this asset has changed since then.
            last_modified_at_str = content.last_modified_at.strftime(
                HTTP_DATE_FORMAT)
            if 'HTTP_IF_MODIFIED_SINCE' in request.META:
                if_modified_since = request.META['HTTP_IF_MODIFIED_SINCE']
                if if_modified_since == last_modified_at_str:
                    return HttpResponseNotModified()

            # *** File streaming within a byte range ***
            # If a Range is provided, parse Range attribute of the request
            # Add Content-Range in the response if Range is structurally correct
            # Request -> Range attribute structure: "Range: bytes=first-[last]"
            # Response -> Content-Range attribute structure: "Content-Range: bytes first-last/totalLength"
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
            response = None
            if request.META.get('HTTP_RANGE'):
                # If we have a StaticContent, get a StaticContentStream.  Can't manipulate the bytes otherwise.
                if type(content) == StaticContent:
                    content = AssetManager.find(loc, as_stream=True)

                header_value = request.META['HTTP_RANGE']
                try:
                    unit, ranges = parse_range_header(header_value,
                                                      content.length)
                except ValueError as exception:
                    # If the header field is syntactically invalid it should be ignored.
                    log.exception(u"%s in Range header: %s for content: %s",
                                  exception.message, header_value,
                                  unicode(loc))
                else:
                    if unit != 'bytes':
                        # Only accept ranges in bytes
                        log.warning(
                            u"Unknown unit in Range header: %s for content: %s",
                            header_value, unicode(loc))
                    elif len(ranges) > 1:
                        # According to Http/1.1 spec content for multiple ranges should be sent as a multipart message.
                        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
                        # But we send back the full content.
                        log.warning(
                            u"More than 1 ranges in Range header: %s for content: %s",
                            header_value, unicode(loc))
                    else:
                        first, last = ranges[0]

                        if 0 <= first <= last < content.length:
                            # If the byte range is satisfiable
                            response = HttpResponse(
                                content.stream_data_in_range(first, last))
                            response[
                                'Content-Range'] = 'bytes {first}-{last}/{length}'.format(
                                    first=first,
                                    last=last,
                                    length=content.length)
                            range_len = last - first + 1
                            response['Content-Length'] = str(range_len)
                            response.status_code = 206  # Partial Content

                            newrelic.agent.add_custom_parameter(
                                'contentserver.range_len', range_len)
                        else:
                            log.warning(
                                u"Cannot satisfy ranges in Range header: %s for content: %s",
                                header_value, unicode(loc))
                            return HttpResponse(
                                status=416)  # Requested Range Not Satisfiable

            # If Range header is absent or syntactically invalid return a full content response.
            if response is None:
                response = HttpResponse(content.stream_data())
                response['Content-Length'] = content.length

                newrelic.agent.add_custom_parameter(
                    'contentserver.content_len', content.length)
                newrelic.agent.add_custom_parameter(
                    'contentserver.content_type', content.content_type)

            # "Accept-Ranges: bytes" tells the user that only "bytes" ranges are allowed
            response['Accept-Ranges'] = 'bytes'
            response['Content-Type'] = content.content_type

            # Set any caching headers, and do any response cleanup needed.  Based on how much
            # middleware we have in place, there's no easy way to use the built-in Django
            # utilities and properly sanitize and modify a response to ensure that it is as
            # cacheable as possible, which is why we do it ourselves.
            self.set_caching_headers(content, response)

            return response
コード例 #21
0
ファイル: views.py プロジェクト: 7venminutes/WebService
def get_file_response(request, path):
    """
    返回下载文件流, 此处path为服务器上文件实际存储的位置
    """
    # 注释原因, 没看懂原代码是否有其他的安全考虑 Baixu 2020-07-08
    # # 防止目录遍历漏洞
    # path = posixpath.normpath(path).lstrip('/')
    # full_path = safe_join(document_root, path)
    full_path = path
    if os.path.isdir(full_path):
        raise Http404('Directory indexes are not allowed here.')
    if not os.path.exists(full_path):
        raise Http404('"%(path)s" does not exist' % {'path': full_path})

    stat_obj = os.stat(full_path)

    # 判断下载过程中文件是否被修改过
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              stat_obj.st_mtime, stat_obj.st_size):
        return HttpResponseNotModified()

    # 获取文件的content_type
    content_type, encoding = mimetypes.guess_type(full_path)
    # content_type = content_type or 'application/octet-stream'
    content_type = 'application/octet-stream'

    # 计算读取文件的起始位置
    start_bytes = re.search(r'bytes=(\d+)-',
                            request.META.get('HTTP_RANGE', ''), re.S)
    print(request.META.get('HTTP_RANGE', ''))
    start_bytes = int(start_bytes.group(1)) if start_bytes else 0

    # 打开文件并移动下标到起始位置,客户端点击继续下载时,从上次断开的点继续读取
    the_file = open(full_path, 'rb')
    the_file.seek(start_bytes, os.SEEK_SET)

    # status=200表示下载开始,status=206表示下载暂停后继续,为了兼容火狐浏览器而区分两种状态
    # 关于django的response对象,参考:https://www.cnblogs.com/scolia/p/5635546.html
    # 关于response的状态码,参考:https://www.cnblogs.com/DeasonGuan/articles/Hanami.html
    # FileResponse默认block_size = 4096,因此迭代器每次读取4KB数据
    response = FileResponse(the_file,
                            content_type=content_type,
                            status=206 if start_bytes > 0 else 200)
    # 'Accept-Ranges' 设为 'bytes' 告诉客户端服务器支持按字节获取部分文件,以实现断点续传
    response['Accept-Ranges'] = 'bytes'
    # 'Last-Modified'表示文件修改时间,与'HTTP_IF_MODIFIED_SINCE'对应使用,参考:https://www.jianshu.com/p/b4ecca41bbff
    response['Last-Modified'] = http_date(stat_obj.st_mtime)

    # 这里'Content-Length'表示剩余待传输的文件字节长度
    if stat.S_ISREG(stat_obj.st_mode):
        response['Content-Length'] = stat_obj.st_size - start_bytes
    if encoding:
        response['Content-Encoding'] = encoding

    # 'Content-Range'的'/'之前描述响应覆盖的文件字节范围,起始下标为0,'/'之后描述整个文件长度,与'HTTP_RANGE'对应使用
    # 参考:http://liqwei.com/network/protocol/2011/886.shtml
    response['Content-Range'] = 'bytes %s-%s/%s' % (
        start_bytes, stat_obj.st_size - 1, stat_obj.st_size)

    # 'Cache-Control'控制浏览器缓存行为,此处禁止浏览器缓存,参考:https://blog.csdn.net/cominglately/article/details/77685214
    response['Cache-Control'] = 'no-cache, no-store, must-revalidate'

    return response
コード例 #22
0
 def not_modified_response(self, *response_args, **response_kwargs):
     """Return :class:`django.http.HttpResponseNotModified` instance."""
     return HttpResponseNotModified(*response_args, **response_kwargs)
コード例 #23
0
def complete_task(request):
    data = request.POST
    Task.objects.filter(id=data[u'task_id']).update(
        completed=data[u'completed'])
    return HttpResponseNotModified()
コード例 #24
0
def static_media(request, module, path, root=None):
    """
    Serve static files below a given point in the directory structure.
    """
    from django.utils.http import http_date
    from django.views.static import was_modified_since
    import mimetypes
    import os.path
    import posixpath
    import stat
    import urllib

    if root:
        document_root = root
    elif module == 'sentry':
        document_root = os.path.join(settings.MODULE_ROOT, 'static', module)
    elif module == dj_settings.COMPRESS_OUTPUT_DIR:
        document_root = os.path.join(dj_settings.STATIC_ROOT, module)
    elif module not in dj_settings.INSTALLED_APPS:
        raise Http404('Invalid module provided.')
    else:
        if module not in STATIC_PATH_CACHE:
            try:
                mod = __import__(module)
            except ImportError:
                raise Http404('Import error raised while fetching module')

            STATIC_PATH_CACHE[module] = os.path.normpath(
                os.path.join(
                    os.path.dirname(mod.__file__),
                    'static',
                    module,
                ))

        document_root = STATIC_PATH_CACHE[module]

    path = posixpath.normpath(urllib.unquote(path))
    path = path.lstrip('/')
    newpath = ''
    for part in path.split('/'):
        if not part:
            # Strip empty path components.
            continue
        drive, part = os.path.splitdrive(part)
        head, part = os.path.split(part)
        if part in (os.curdir, os.pardir):
            # Strip '.' and '..' in path.
            continue
        newpath = os.path.join(newpath, part).replace('\\', '/')
    if newpath and path != newpath:
        return HttpResponseRedirect(newpath)
    fullpath = os.path.join(document_root, newpath)
    if os.path.isdir(fullpath):
        raise Http404('Directory indexes are not allowed here.')
    if not os.path.exists(fullpath):
        raise Http404('"%s" does not exist' % fullpath)
    # Respect the If-Modified-Since header.
    statobj = os.stat(fullpath)
    mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
        return HttpResponseNotModified(mimetype=mimetype)
    contents = open(fullpath, 'rb').read()
    response = HttpResponse(contents, mimetype=mimetype)
    response['Last-Modified'] = http_date(statobj[stat.ST_MTIME])
    response['Content-Length'] = len(contents)
    return response
コード例 #25
0
def review_detail(request,
                  review_request_id,
                  local_site_name=None,
                  template_name="reviews/review_detail.html"):
    """
    Main view for review requests. This covers the review request information
    and all the reviews on it.
    """
    # If there's a local_site passed in the URL, we want to look up the review
    # request based on the local_id instead of the pk. This allows each
    # local_site configured to have its own review request ID namespace
    # starting from 1.
    review_request, response = \
        _find_review_request(request, review_request_id, local_site_name)

    if not review_request:
        return response

    reviews = review_request.get_public_reviews()
    review = review_request.get_pending_review(request.user)
    review_timestamp = 0
    last_visited = 0
    starred = False

    if request.user.is_authenticated():
        # If the review request is public and pending review and if the user
        # is logged in, mark that they've visited this review request.
        if review_request.public and review_request.status == "P":
            visited, visited_is_new = ReviewRequestVisit.objects.get_or_create(
                user=request.user, review_request=review_request)
            last_visited = visited.timestamp
            visited.timestamp = datetime.now()
            visited.save()

        starred = review_request in \
                  request.user.get_profile().starred_review_requests.all()

        # Unlike review above, this covers replies as well.
        try:
            last_draft_review = Review.objects.filter(
                review_request=review_request, user=request.user,
                public=False).latest()
            review_timestamp = last_draft_review.timestamp
        except Review.DoesNotExist:
            pass

    draft = review_request.get_draft(request.user)

    # Find out if we can bail early. Generate an ETag for this.
    last_activity_time, updated_object = review_request.get_last_activity()

    if draft:
        draft_timestamp = draft.last_updated
    else:
        draft_timestamp = ""

    etag = "%s:%s:%s:%s:%s:%s" % (request.user, last_activity_time,
                                  draft_timestamp, review_timestamp,
                                  int(starred), settings.AJAX_SERIAL)

    if etag_if_none_match(request, etag):
        return HttpResponseNotModified()

    changedescs = review_request.changedescs.filter(public=True)

    try:
        latest_changedesc = changedescs.latest('timestamp')
        latest_timestamp = latest_changedesc.timestamp
    except ChangeDescription.DoesNotExist:
        latest_timestamp = None

    entries = []

    for temp_review in reviews:
        temp_review.ordered_comments = \
            temp_review.comments.order_by('filediff', 'first_line')

        state = ''

        # Mark as collapsed if the review is older than the latest change
        if latest_timestamp and temp_review.timestamp < latest_timestamp:
            state = 'collapsed'

        try:
            latest_reply = temp_review.public_replies().latest(
                'timestamp').timestamp
        except Review.DoesNotExist:
            latest_reply = None

        # Mark as expanded if there is a reply newer than last_visited
        if latest_reply and last_visited and last_visited < latest_reply:
            state = ''

        entries.append({
            'review': temp_review,
            'timestamp': temp_review.timestamp,
            'class': state,
        })

    for changedesc in changedescs:
        fields_changed = []

        for name, info in changedesc.fields_changed.items():
            multiline = False

            if 'added' in info or 'removed' in info:
                change_type = 'add_remove'

                # We don't hard-code URLs in the bug info, since the
                # tracker may move, but we can do it here.
                if (name == "bugs_closed"
                        and review_request.repository.bug_tracker):
                    bug_url = review_request.repository.bug_tracker
                    for field in info:
                        for i, buginfo in enumerate(info[field]):
                            try:
                                full_bug_url = bug_url % buginfo[0]
                                info[field][i] = (buginfo[0], full_bug_url)
                            except TypeError:
                                logging.warning(
                                    "Invalid bugtracker url format")

            elif 'old' in info or 'new' in info:
                change_type = 'changed'
                multiline = (name == "description" or name == "testing_done")

                # Branch text is allowed to have entities, so mark it safe.
                if name == "branch":
                    if 'old' in info:
                        info['old'][0] = mark_safe(info['old'][0])

                    if 'new' in info:
                        info['new'][0] = mark_safe(info['new'][0])
            elif name == "screenshot_captions":
                change_type = 'screenshot_captions'
            else:
                # No clue what this is. Bail.
                continue

            fields_changed.append({
                'title':
                fields_changed_name_map.get(name, name),
                'multiline':
                multiline,
                'info':
                info,
                'type':
                change_type,
            })

        # Expand the latest review change
        state = ''

        # Mark as collapsed if the change is older than a newer change
        if latest_timestamp and changedesc.timestamp < latest_timestamp:
            state = 'collapsed'

        entries.append({
            'changeinfo': fields_changed,
            'changedesc': changedesc,
            'timestamp': changedesc.timestamp,
            'class': state,
        })

    entries.sort(key=lambda item: item['timestamp'])

    response = render_to_response(
        template_name,
        RequestContext(
            request,
            _make_review_request_context(
                review_request, {
                    'draft': draft,
                    'review_request_details': draft or review_request,
                    'entries': entries,
                    'last_activity_time': last_activity_time,
                    'review': review,
                    'request': request,
                    'PRE_CREATION': PRE_CREATION,
                })))
    set_etag(response, etag)

    return response
コード例 #26
0
ファイル: views.py プロジェクト: sdr01810/intellij-idea-ce
def serve(request,
          path,
          document_root=None,
          show_indexes=False,
          insecure=False):
    """
    Serve static files below a given point in the directory structure or
    from locations inferred from the static files finders.

    To use, put a URL pattern such as::

        (r'^(?P<path>.*)$', 'django.contrib.staticfiles.views.serve')

    in your URLconf.

    If you provide the ``document_root`` parameter, the file won't be looked
    up with the staticfiles finders, but in the given filesystem path, e.g.::

    (r'^(?P<path>.*)$', 'django.contrib.staticfiles.views.serve', {'document_root' : '/path/to/my/files/'})

    You may also set ``show_indexes`` to ``True`` if you'd like to serve a
    basic index of the directory.  This index view will use the
    template hardcoded below, but if you'd like to override it, you can create
    a template called ``static/directory_index.html``.
    """
    if not settings.DEBUG and not insecure:
        raise ImproperlyConfigured("The view to serve static files can only "
                                   "be used if the DEBUG setting is True or "
                                   "the --insecure option of 'runserver' is "
                                   "used")
    if not document_root:
        absolute_path = finders.find(path)
        if not absolute_path:
            raise Http404('"%s" could not be found' % path)
        document_root, path = os.path.split(absolute_path)
    # Clean up given path to only allow serving files below document_root.
    path = posixpath.normpath(urllib.unquote(path))
    path = path.lstrip('/')
    newpath = ''
    for part in path.split('/'):
        if not part:
            # Strip empty path components.
            continue
        drive, part = os.path.splitdrive(part)
        head, part = os.path.split(part)
        if part in (os.curdir, os.pardir):
            # Strip '.' and '..' in path.
            continue
        newpath = os.path.join(newpath, part).replace('\\', '/')
    if newpath and path != newpath:
        return HttpResponseRedirect(newpath)
    fullpath = os.path.join(document_root, newpath)
    if os.path.isdir(fullpath):
        if show_indexes:
            return directory_index(newpath, fullpath)
        raise Http404("Directory indexes are not allowed here.")
    if not os.path.exists(fullpath):
        raise Http404('"%s" does not exist' % fullpath)
    # Respect the If-Modified-Since header.
    statobj = os.stat(fullpath)
    mimetype, encoding = mimetypes.guess_type(fullpath)
    mimetype = mimetype or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
        return HttpResponseNotModified(mimetype=mimetype)
    contents = open(fullpath, 'rb').read()
    response = HttpResponse(contents, mimetype=mimetype)
    response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
    response["Content-Length"] = len(contents)
    if encoding:
        response["Content-Encoding"] = encoding
    return response
コード例 #27
0
def serve_private_media(request, path):
    """Serve a private media file with the webserver's "sendfile" if possible.

    Here's an example of how to use this function. The 'Document' model tracks
    files. It provides a 'get_file_path' method returning the absolute path to
    the actual file. The following view serves file only to users having the
    'can_download' permission::

        @permission_required('documents.can_download')
        def download_document(request, document_id):
            path = Document.objects.get(pk=document_id).get_file_path()
            return serve_private_media(request, path)

    If ``DEBUG`` is ``False`` and ``settings.GALLERY_SENDFILE_HEADER`` is set,
    this function sets a header and doesn't send the actual contents of the
    file. Use ``'X-Accel-Redirect'`` for nginx and ``'X-SendFile'`` for Apache
    with mod_xsendfile. Otherwise, this function behaves like Django's static
    serve view.

    ``path`` must be an absolute path. Depending on your webserver's
    configuration, you might want a full path or a relative path in the
    header's value. ``settings.GALLERY_SENDFILE_ROOT`` will be stripped from
    the beginning of the path to create the header's value.
    """

    if not os.path.exists(path):
        # Don't reveal the file name on the filesystem.
        raise Http404("Requested file doesn't exist.")

    # begin copy-paste from django.views.static.serve
    statobj = os.stat(path)
    content_type, encoding = mimetypes.guess_type(path)
    content_type = content_type or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj.st_mtime,
                              statobj.st_size):  # pragma: no cover
        return HttpResponseNotModified()
    # pause copy-paste from django.views.static.serve

    sendfile_header = getattr(settings, 'GALLERY_SENDFILE_HEADER', '')
    sendfile_root = getattr(settings, 'GALLERY_SENDFILE_ROOT', '')

    if settings.DEBUG or not sendfile_header:
        response = StreamingHttpResponse(open(path, 'rb'),
                                         content_type=content_type)
    else:
        response = HttpResponse('', content_type=content_type)
        if sendfile_root:
            if not path.startswith(sendfile_root):
                raise ValueError(
                    "Requested file isn't under GALLERY_SENDFILE_ROOT.")
            path = path[len(sendfile_root):]
        response[sendfile_header] = path.encode(sys.getfilesystemencoding())

    # resume copy-paste from django.views.static.serve
    response["Last-Modified"] = http_date(statobj.st_mtime)
    if stat.S_ISREG(statobj.st_mode):  # pragma: no cover
        response["Content-Length"] = statobj.st_size
    if encoding:  # pragma: no cover
        response["Content-Encoding"] = encoding
    # end copy-paste from django.views.static.serve

    return response
コード例 #28
0
    def get(self, request, *args, **kwargs):
        """Returns the last update made to the review request.

        This shows the type of update that was made, the user who made the
        update, and when the update was made. Clients can use this to inform
        the user that the review request was updated, or automatically update
        it in the background.

        This does not take into account changes to a draft review request, as
        that's generally not update information that the owner of the draft is
        interested in. Only public updates are represented.
        """
        try:
            review_request = \
                resources.review_request.get_object(request, *args, **kwargs)
        except ObjectDoesNotExist:
            return DOES_NOT_EXIST

        if not resources.review_request.has_access_permissions(
                request, review_request):
            return self.get_no_access_error(request)

        info = review_request.get_last_activity_info()
        timestamp = info['timestamp']
        updated_object = info['updated_object']
        changedesc = info['changedesc']

        etag = encode_etag('%s:%s' % (timestamp, updated_object.pk))

        if etag_if_none_match(request, etag):
            return HttpResponseNotModified()

        summary = None
        update_type = None

        if isinstance(updated_object, ReviewRequest):
            if updated_object.status == ReviewRequest.SUBMITTED:
                summary = _('Review request submitted')
            elif updated_object.status == ReviewRequest.DISCARDED:
                summary = _('Review request discarded')
            else:
                summary = _('Review request updated')

            update_type = 'review-request'
        elif isinstance(updated_object, DiffSet):
            summary = _('Diff updated')
            update_type = 'diff'
        elif isinstance(updated_object, Review):
            if updated_object.is_reply():
                summary = _('New reply')
                update_type = 'reply'
            else:
                summary = _('New review')
                update_type = 'review'
        else:
            # Should never be able to happen. The object will always at least
            # be a ReviewRequest.
            assert False

        if changedesc:
            user = changedesc.get_user(review_request)
        else:
            # There is no changedesc which means this review request hasn't
            # been changed since it was first published, so this change must
            # be due to the original submitter.
            user = review_request.submitter

        return 200, {
            self.item_result_key: {
                'timestamp': timestamp,
                'user': user,
                'summary': summary,
                'type': update_type,
            }
        }, {
            'ETag': etag,
        }
コード例 #29
0
 def not_modified(self, data=''):
     return HttpResponseNotModified(data)
コード例 #30
0
    def get(self, request, *args, **kwargs):
        """Handle GET requests for this view.

        This will create the renderer for the diff fragment and render it in
        order to get the PatchError information. It then returns a response
        with a zip file containing all the debug data.

        If no PatchError occurred, this will return a 404.

        Args:
            request (django.http.HttpRequest):
                The HTTP request.

            *args (tuple):
                Additional positional arguments for the view.

            **kwargs (dict):
                Additional keyword arguments for the view.

        Returns:
            django.http.HttpResponse:
            A response containing the data bundle.
        """
        try:
            renderer_settings = self._get_renderer_settings(**kwargs)
            etag = self.make_etag(renderer_settings, **kwargs)

            if etag_if_none_match(request, etag):
                return HttpResponseNotModified()

            diff_info_or_response = self.process_diffset_info(**kwargs)

            if isinstance(diff_info_or_response, HttpResponse):
                return diff_info_or_response
        except Http404:
            return HttpResponseNotFound()
        except Exception as e:
            logging.exception(
                '%s.get: Error when processing diffset info for filediff '
                'ID=%s, interfilediff ID=%s, chunk_index=%s: %s',
                self.__class__.__name__,
                kwargs.get('filediff_id'),
                kwargs.get('interfilediff_id'),
                kwargs.get('chunk_index'),
                e,
                request=request)
            return HttpResponseServerError()

        kwargs.update(diff_info_or_response)

        try:
            context = self.get_context_data(**kwargs)

            renderer = self.create_renderer(
                context=context,
                renderer_settings=renderer_settings,
                *args,
                **kwargs)
            renderer.render_to_response(request)
        except PatchError as e:
            patch_error = e
        except Exception as e:
            logging.exception(
                '%s.get: Error when rendering diffset for filediff ID=%s, '
                'interfilediff ID=%s, chunk_index=%s: %s',
                self.__class__.__name__,
                kwargs.get('filediff_id'),
                kwargs.get('interfilediff_id'),
                kwargs.get('chunk_index'),
                e,
                request=request)
            return HttpResponseServerError()
        else:
            return HttpResponseNotFound()

        zip_data = StringIO()

        with ZipFile(zip_data, 'w') as zipfile:
            basename = os.path.basename(patch_error.filename)
            zipfile.writestr('%s.orig' % basename, patch_error.orig_file)
            zipfile.writestr('%s.diff' % basename, patch_error.diff)

            if patch_error.rejects:
                zipfile.writestr('%s.rej' % basename, patch_error.rejects)

            if patch_error.new_file:
                zipfile.writestr('%s.new' % basename, patch_error.new_file)

        rsp = HttpResponse(zip_data.getvalue(), content_type='application/zip')
        rsp['Content-Disposition'] = \
            'attachment; filename=%s.zip' % basename

        return rsp