Skip to content

Commit 23919b4

Browse files
author
Tobias Zanke
committed
resources should not return complex responses, also sendfile needs request which is only available in view
1 parent 5925667 commit 23919b4

File tree

3 files changed

+39
-46
lines changed

3 files changed

+39
-46
lines changed

djangodav/fs/resources.py

+5-41
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,13 @@
1818
#
1919
# You should have received a copy of the GNU Affero General Public License
2020
# along with DjangoDav. If not, see <http://www.gnu.org/licenses/>.
21-
import hashlib
22-
import mimetypes
23-
from sys import getfilesystemencoding
24-
import os
2521
import datetime
22+
import os
2623
import shutil
27-
import urllib
28-
29-
from django.http import HttpResponse
30-
from django.utils.http import http_date
24+
from sys import getfilesystemencoding
3125

3226
from djangodav.base.resources import BaseDavResource
33-
from djangodav.responses import ResponseException
34-
from djangodav.utils import safe_join, url_join
35-
27+
from djangodav.utils import url_join
3628

3729
fs_encoding = getfilesystemencoding()
3830

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

4537
root = None
38+
quote = False
39+
prefix = "/"
4640

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

130124
class DummyFSDAVResource(DummyReadFSDavResource, DummyWriteFSDavResource, BaseFSDavResource):
131125
pass
132-
133-
134-
class SendFileFSDavResource(BaseFSDavResource):
135-
quote = False
136-
137-
def read(self):
138-
response = HttpResponse()
139-
full_path = self.get_abs_path().encode('utf-8')
140-
if self.quote:
141-
full_path = urllib.quote(full_path)
142-
response['X-SendFile'] = full_path
143-
response['Content-Type'] = mimetypes.guess_type(self.displayname)
144-
response['Content-Length'] = self.getcontentlength
145-
response['Last-Modified'] = http_date(self.getlastmodified)
146-
response['ETag'] = self.getetag
147-
raise ResponseException(response)
148-
149-
150-
class RedirectFSDavResource(BaseFSDavResource):
151-
prefix = "/"
152-
153-
def read(self):
154-
response = HttpResponse()
155-
response['X-Accel-Redirect'] = url_join(self.prefix, self.get_path().encode('utf-8'))
156-
response['X-Accel-Charset'] = 'utf-8'
157-
response['Content-Type'] = mimetypes.guess_type(self.displayname)
158-
response['Content-Length'] = self.getcontentlength
159-
response['Last-Modified'] = http_date(self.getlastmodified)
160-
response['ETag'] = self.getetag
161-
raise ResponseException(response)

djangodav/responses.py

+8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ def __init__(self, response, *args, **kwargs):
4141
self.response = response
4242

4343

44+
class AsSendFileFS(Exception):
45+
pass
46+
47+
48+
class RedirectFSException(Exception):
49+
pass
50+
51+
4452
class HttpResponsePreconditionFailed(HttpResponse):
4553
status_code = httplib.PRECONDITION_FAILED
4654

djangodav/views/views.py

+26-5
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,27 @@
66
from sys import version_info as python_version
77
from django.utils.timezone import now
88
from lxml import etree
9+
import mimetypes
10+
import urllib
911

1012
from django.http import HttpResponseForbidden, HttpResponseNotAllowed, HttpResponseBadRequest, \
11-
HttpResponseNotModified, HttpResponseRedirect, Http404
13+
HttpResponseNotModified, HttpResponseRedirect, Http404, HttpResponse
1214
from django.utils.decorators import method_decorator
1315
from django.utils.functional import cached_property
14-
from django.utils.http import parse_etags
16+
from django.utils.http import parse_etags, http_date
1517
from django.shortcuts import render_to_response
1618
from django.views.decorators.csrf import csrf_exempt
1719
from django.views.generic import View
1820

19-
from djangodav.responses import ResponseException, HttpResponsePreconditionFailed, HttpResponseCreated, HttpResponseNoContent, \
21+
from djangodav.responses import HttpResponsePreconditionFailed, HttpResponseCreated, HttpResponseNoContent, \
2022
HttpResponseConflict, HttpResponseMediatypeNotSupported, HttpResponseBadGateway, \
21-
HttpResponseMultiStatus, HttpResponseLocked, HttpResponse
23+
HttpResponseMultiStatus, HttpResponseLocked, RedirectFSException, ResponseException, AsSendFileFS
2224
from djangodav.utils import WEBDAV_NSMAP, D, url_join, get_property_tag_list, rfc1123_date
2325
from djangodav import VERSION as djangodav_version
2426
from django import VERSION as django_version, get_version
2527

28+
from sendfile import sendfile
29+
2630
PATTERN_IF_DELIMITER = re.compile(r'(<([^>]+)>)|(\(([^\)]+)\))')
2731

2832
class DavView(View):
@@ -190,7 +194,24 @@ def get(self, request, path, head=False, *args, **kwargs):
190194
response['ETag'] = self.resource.getetag
191195
if not head:
192196
response['Content-Length'] = self.resource.getcontentlength
193-
response.content = self.resource.read()
197+
try:
198+
response.content = self.resource.read()
199+
except AsSendFileFS:
200+
assert sendfile is not None, "django-sendfile is not installed."
201+
full_path = self.resource.get_abs_path().encode('utf-8')
202+
if self.resource.quote:
203+
full_path = urllib.quote(full_path)
204+
response = sendfile(request, full_path)
205+
return response
206+
except RedirectFSException:
207+
response = HttpResponse()
208+
response['X-Accel-Redirect'] = url_join(self.resource.prefix, self.resource.get_path().encode('utf-8'))
209+
response['X-Accel-Charset'] = 'utf-8'
210+
response['Content-Type'] = mimetypes.guess_type(self.resource.displayname)
211+
response['Content-Length'] = self.resource.getcontentlength
212+
response['Last-Modified'] = http_date(self.resource.getlastmodified)
213+
response['ETag'] = self.resource.getetag
214+
raise ResponseException(response)
194215
elif not head:
195216
response = render_to_response(self.template_name, dict(resource=self.resource, base_url=self.base_url))
196217
response['Last-Modified'] = self.resource.getlastmodified

0 commit comments

Comments
 (0)