Skip to content

Commit

Permalink
resources should not return complex responses, also sendfile needs re…
Browse files Browse the repository at this point in the history
…quest which is only available in view
  • Loading branch information
Tobias Zanke committed May 16, 2017
1 parent 5925667 commit 23919b4
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 46 deletions.
46 changes: 5 additions & 41 deletions djangodav/fs/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,13 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with DjangoDav. If not, see <http://www.gnu.org/licenses/>.
import hashlib
import mimetypes
from sys import getfilesystemencoding
import os
import datetime
import os
import shutil
import urllib

from django.http import HttpResponse
from django.utils.http import http_date
from sys import getfilesystemencoding

from djangodav.base.resources import BaseDavResource
from djangodav.responses import ResponseException
from djangodav.utils import safe_join, url_join

from djangodav.utils import url_join

fs_encoding = getfilesystemencoding()

Expand All @@ -43,6 +35,8 @@ class BaseFSDavResource(BaseDavResource):
python's os library to do most of the work."""

root = None
quote = False
prefix = "/"

def get_abs_path(self):
"""Return the absolute path of the resource. Used internally to interface with
Expand Down Expand Up @@ -129,33 +123,3 @@ def write(self, request):

class DummyFSDAVResource(DummyReadFSDavResource, DummyWriteFSDavResource, BaseFSDavResource):
pass


class SendFileFSDavResource(BaseFSDavResource):
quote = False

def read(self):
response = HttpResponse()
full_path = self.get_abs_path().encode('utf-8')
if self.quote:
full_path = urllib.quote(full_path)
response['X-SendFile'] = full_path
response['Content-Type'] = mimetypes.guess_type(self.displayname)
response['Content-Length'] = self.getcontentlength
response['Last-Modified'] = http_date(self.getlastmodified)
response['ETag'] = self.getetag
raise ResponseException(response)


class RedirectFSDavResource(BaseFSDavResource):
prefix = "/"

def read(self):
response = HttpResponse()
response['X-Accel-Redirect'] = url_join(self.prefix, self.get_path().encode('utf-8'))
response['X-Accel-Charset'] = 'utf-8'
response['Content-Type'] = mimetypes.guess_type(self.displayname)
response['Content-Length'] = self.getcontentlength
response['Last-Modified'] = http_date(self.getlastmodified)
response['ETag'] = self.getetag
raise ResponseException(response)
8 changes: 8 additions & 0 deletions djangodav/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ def __init__(self, response, *args, **kwargs):
self.response = response


class AsSendFileFS(Exception):
pass


class RedirectFSException(Exception):
pass


class HttpResponsePreconditionFailed(HttpResponse):
status_code = httplib.PRECONDITION_FAILED

Expand Down
31 changes: 26 additions & 5 deletions djangodav/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,27 @@
from sys import version_info as python_version
from django.utils.timezone import now
from lxml import etree
import mimetypes
import urllib

from django.http import HttpResponseForbidden, HttpResponseNotAllowed, HttpResponseBadRequest, \
HttpResponseNotModified, HttpResponseRedirect, Http404
HttpResponseNotModified, HttpResponseRedirect, Http404, HttpResponse
from django.utils.decorators import method_decorator
from django.utils.functional import cached_property
from django.utils.http import parse_etags
from django.utils.http import parse_etags, http_date
from django.shortcuts import render_to_response
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View

from djangodav.responses import ResponseException, HttpResponsePreconditionFailed, HttpResponseCreated, HttpResponseNoContent, \
from djangodav.responses import HttpResponsePreconditionFailed, HttpResponseCreated, HttpResponseNoContent, \
HttpResponseConflict, HttpResponseMediatypeNotSupported, HttpResponseBadGateway, \
HttpResponseMultiStatus, HttpResponseLocked, HttpResponse
HttpResponseMultiStatus, HttpResponseLocked, RedirectFSException, ResponseException, AsSendFileFS
from djangodav.utils import WEBDAV_NSMAP, D, url_join, get_property_tag_list, rfc1123_date
from djangodav import VERSION as djangodav_version
from django import VERSION as django_version, get_version

from sendfile import sendfile

PATTERN_IF_DELIMITER = re.compile(r'(<([^>]+)>)|(\(([^\)]+)\))')

class DavView(View):
Expand Down Expand Up @@ -190,7 +194,24 @@ def get(self, request, path, head=False, *args, **kwargs):
response['ETag'] = self.resource.getetag
if not head:
response['Content-Length'] = self.resource.getcontentlength
response.content = self.resource.read()
try:
response.content = self.resource.read()
except AsSendFileFS:
assert sendfile is not None, "django-sendfile is not installed."
full_path = self.resource.get_abs_path().encode('utf-8')
if self.resource.quote:
full_path = urllib.quote(full_path)
response = sendfile(request, full_path)
return response
except RedirectFSException:
response = HttpResponse()
response['X-Accel-Redirect'] = url_join(self.resource.prefix, self.resource.get_path().encode('utf-8'))
response['X-Accel-Charset'] = 'utf-8'
response['Content-Type'] = mimetypes.guess_type(self.resource.displayname)
response['Content-Length'] = self.resource.getcontentlength
response['Last-Modified'] = http_date(self.resource.getlastmodified)
response['ETag'] = self.resource.getetag
raise ResponseException(response)
elif not head:
response = render_to_response(self.template_name, dict(resource=self.resource, base_url=self.base_url))
response['Last-Modified'] = self.resource.getlastmodified
Expand Down

0 comments on commit 23919b4

Please sign in to comment.