Skip to content

Commit 32783b8

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 32783b8

File tree

3 files changed

+50
-51
lines changed

3 files changed

+50
-51
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

+37-10
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,30 @@
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
15-
from django.shortcuts import render_to_response
16+
from django.utils.http import parse_etags, http_date
1617
from django.views.decorators.csrf import csrf_exempt
17-
from django.views.generic import View
18+
from django.views.generic import TemplateView
1819

19-
from djangodav.responses import ResponseException, HttpResponsePreconditionFailed, HttpResponseCreated, HttpResponseNoContent, \
20+
from djangodav.responses import HttpResponsePreconditionFailed, HttpResponseCreated, HttpResponseNoContent, \
2021
HttpResponseConflict, HttpResponseMediatypeNotSupported, HttpResponseBadGateway, \
21-
HttpResponseMultiStatus, HttpResponseLocked, HttpResponse
22-
from djangodav.utils import WEBDAV_NSMAP, D, url_join, get_property_tag_list, rfc1123_date
22+
HttpResponseMultiStatus, HttpResponseLocked, RedirectFSException, ResponseException, AsSendFileFS
23+
from djangodav.utils import WEBDAV_NSMAP, D, get_property_tag_list, rfc1123_date
2324
from djangodav import VERSION as djangodav_version
2425
from django import VERSION as django_version, get_version
2526

27+
from sendfile import sendfile
28+
2629
PATTERN_IF_DELIMITER = re.compile(r'(<([^>]+)>)|(\(([^\)]+)\))')
2730

28-
class DavView(View):
31+
32+
class DavView(TemplateView):
2933
resource_class = None
3034
lock_class = None
3135
acl_class = None
@@ -173,6 +177,12 @@ def evaluate_conditions(self, res):
173177
cond_if = '<*>' + cond_if
174178
#for (tmpurl, url, tmpcontent, content) in PATTERN_IF_DELIMITER.findall(cond_if):
175179

180+
def get_context_data(self, **kwargs):
181+
context = super(DavView, self).get_context_data(**kwargs)
182+
context['resource'] = self.resource
183+
context['base_url'] = self.base_url
184+
return context
185+
176186
def get(self, request, path, head=False, *args, **kwargs):
177187
if not self.resource.exists:
178188
raise Http404("Resource doesn't exists")
@@ -190,9 +200,26 @@ def get(self, request, path, head=False, *args, **kwargs):
190200
response['ETag'] = self.resource.getetag
191201
if not head:
192202
response['Content-Length'] = self.resource.getcontentlength
193-
response.content = self.resource.read()
203+
try:
204+
response.content = self.resource.read()
205+
except AsSendFileFS:
206+
assert sendfile is not None, "django-sendfile is not installed."
207+
full_path = self.resource.get_abs_path().encode('utf-8')
208+
if self.resource.quote:
209+
full_path = urllib.quote(full_path)
210+
response = sendfile(request, full_path)
211+
return response
212+
except RedirectFSException:
213+
response = HttpResponse()
214+
response['X-Accel-Redirect'] = url_join(self.resource.prefix, self.resource.get_path().encode('utf-8'))
215+
response['X-Accel-Charset'] = 'utf-8'
216+
response['Content-Type'] = mimetypes.guess_type(self.resource.displayname)
217+
response['Content-Length'] = self.resource.getcontentlength
218+
response['Last-Modified'] = http_date(self.resource.getlastmodified)
219+
response['ETag'] = self.resource.getetag
220+
raise ResponseException(response)
194221
elif not head:
195-
response = render_to_response(self.template_name, dict(resource=self.resource, base_url=self.base_url))
222+
response = super(DavView, self).get(request, *args, **kwargs)
196223
response['Last-Modified'] = self.resource.getlastmodified
197224
return response
198225

0 commit comments

Comments
 (0)