Opened 13 years ago
Closed 13 years ago
#19046 closed Bug (needsinfo)
staticfiles not finding the files on Windows
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | contrib.staticfiles | Version: | 1.4 | 
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description
I'm using Django 1.4 on Windows XP and when a file is requested from STATIC_ROOT I get the following error: 
Traceback (most recent call last):
  File "C:\Python27\lib\wsgiref\handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "C:\Python27\lib\site-packages\django\contrib\staticfiles\handlers.py", line 68, in __call__
    return super(StaticFilesHandler, self).__call__(environ, start_response)
  File "C:\Python27\lib\site-packages\django\core\handlers\wsgi.py", line 241, in __call__
    response = self.get_response(request)
  File "C:\Python27\lib\site-packages\django\contrib\staticfiles\handlers.py", line 58, in get_response
    return self.serve(request)
  File "C:\Python27\lib\site-packages\django\contrib\staticfiles\handlers.py", line 51, in serve
    return serve(request, self.file_path(request.path), insecure=True)
  File "C:\Python27\lib\site-packages\django\contrib\staticfiles\views.py", line 35, in serve
    absolute_path = finders.find(normalized_path)
  File "C:\Python27\lib\site-packages\django\contrib\staticfiles\finders.py", line 238, in find
    result = finder.find(path, all=all)
  File "C:\Python27\lib\site-packages\django\contrib\staticfiles\finders.py", line 78, in find
    matched_path = self.find_location(root, path, prefix)
  File "C:\Python27\lib\site-packages\django\contrib\staticfiles\finders.py", line 95, in find_location
    path = safe_join(root, path)
  File "C:\Python27\lib\site-packages\django\utils\_os.py", line 52, in safe_join
    'path component (%s)' % (final_path, base_path))
ValueError: The joined path (C:\images\common\fnurse.jpg) is located outside of the base path component (C:\DJANGO\webtech-proto-work\static)
[01/Oct/2012 09:34:06] "GET /static/images/common/fnurse.jpg HTTP/1.1" 500 59
I have traced the cause of the error to line 37 in staticfiles/views.py :
normalized_path = posixpath.normpath(unquote(path)).lstrip('/')
I have replaced the hardcoded '/' to os.sep and after that static files have been served on Windows. Please check if this change is correct and if it correct than please integrate it.
Change History (3)
comment:1 by , 13 years ago
| Severity: | Normal → Release blocker | 
|---|---|
| Triage Stage: | Unreviewed → Accepted | 
| Type: | Uncategorized → Bug | 
comment:2 by , 13 years ago
| Easy pickings: | unset | 
|---|---|
| Severity: | Release blocker → Normal | 
comment:3 by , 13 years ago
| Resolution: | → needsinfo | 
|---|---|
| Status: | new → closed | 
posixpath is the module that is used on POSIX systems when import os.path. It uses the hardcoded forward slash and a couple of other things different to the ntpath module that does the same for Windows systems. In other words os.path just a facade for the platform specific tools. The different modules are documented on http://docs.python.org/2/library/os.path.html
The lstrip('/') happens there since the path passed to the serve view may be formatted as http://localhost:8000/static///someother/file.ext making path having a value of //someother/file.ext. The posix.normpath happens there to remove redundancies in the path (e.g. path/to/../some//file.ext is converted to path/some/file.ext). The finder api expects that kind of cleaned up name to make sure it does the right thing later on.
As I'm not able to reproduce the issue with the current code, I'm closing as needsinfo. A testcase that demostrates the issue would be appreciated, for example.
It wasn't easy but I eventually managed to reproduce this problem.
Here's what I did:
STATIC_ROOT = './static'(no trailing slash -- otherwise the bug doesn't happen),STATICFILES_DIRS = ('./static_src/',)django/conf/__init__.pyto cancel the effects of fbfaa35fb0a2a1206221e00c56cf6136cf93b6f1 -- otherwise Django refuses to startstatic_src/yay.txthttp://localhost:8000/static/yay.txtSince fbfaa35fb0a2a1206221e00c56cf6136cf93b6f1, Django requires
STATIC_URLto end with a slash, so this problem cannot occur in Django 1.5. For this reason, I'm going to downgrade the severity.However, I still feel there's something wrong with this line:
normalized_path = posixpath.normpath(unquote(path)).lstrip('/')As far as I can tell:
posixpathmodule from Python's standard library is used to perform path normalization with forward slashes, which seems suitable for URLs;.lstrip('/')is intended to strip the leading slash from the URL, in caseSTATIC_URLsetting doesn't end in a slash.I see two problems:
serve()function receivespath = '\yay.txt'— the backslash has absolutely no reason for being here; everything's happening in "URL-space", not in "file-space" until this point;.lstrip('/')isn't necessary any longer since Django >= 1.5 requiresSTATIC_URLto end in a slash.