HttpResponseSendFile

22 views
Skip to first unread message

SmileyChris

unread,
Jun 14, 2006, 9:55:50 PM6/14/06
to Django developers
(oops, posted this before in the django users group)

I noticed http://code.djangoproject.com/ticket/2131 was marked as a
wontfix today with the comment, "Django isn't meant to serve static
files".

I don't want to go reopening the ticket, but couldn't this still be
useful functionality?
What if I wanted to limit access to a static file to certain users or
groups in Django? How would I do this otherwise?

James Bennett

unread,
Jun 14, 2006, 10:19:59 PM6/14/06
to django-d...@googlegroups.com
On 6/14/06, SmileyChris <smile...@gmail.com> wrote:
> I don't want to go reopening the ticket, but couldn't this still be
> useful functionality?

Well, I can certainly see Adrian's point in that ticket; Django really
isn't meant for handling static files, which is why there are huge
warnings all over the explanation of how to get it working with the
dev server; using Django to just grab a file from disk and shove it
down the pipe is really a horrendous waste of resources given that web
servers are highly optimized for that task already.

> What if I wanted to limit access to a static file to certain users or
> groups in Django? How would I do this otherwise?

That feels like it's getting close to implementing a feature just for
a "special case" situation, but I'm not 100% certain.

--
"May the forces of evil become confused on the way to your house."
-- George Carlin

SmileyChris

unread,
Jun 14, 2006, 10:28:55 PM6/14/06
to Django developers
I realise there are better ways to send most files. I ask about this
because I'm looking at implementing that "special case" soon
(authenticating files via logged in user in Django), and I was just
wondering about ways to do it.

Ivan Sagalaev

unread,
Jun 15, 2006, 12:45:22 AM6/15/06
to django-d...@googlegroups.com
SmileyChris wrote:
> I don't want to go reopening the ticket, but couldn't this still be
> useful functionality?
>
The regular HttpResponse already can serve files in some fashion:

f = open(filename)
return HttpResponse(f, mimetype='application/octet-stream')

Here the file-like object will work as an iterator sending one line at
a time.

SmileyChris

unread,
Jun 15, 2006, 1:18:56 AM6/15/06
to Django developers
Ivan Sagalaev wrote:
> The regular HttpResponse already can serve files in some fashion:
>
> f = open(filename)
> return HttpResponse(f, mimetype='application/octet-stream')
>
> Here the file-like object will work as an iterator sending one line at
> a time.

Thanks Ivan, this alleviates my concern of not having a
HttpReponseSendFile :)

Adrian Holovaty

unread,
Jun 15, 2006, 11:27:53 AM6/15/06
to django-d...@googlegroups.com
On 6/14/06, SmileyChris <smile...@gmail.com> wrote:

May I interest you in the "Authenticating against Django's user
database from Apache" document?

http://www.djangoproject.com/documentation/apache_auth/

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com

dougn

unread,
Jun 16, 2006, 5:16:26 PM6/16/06
to Django developers
Before I get into the details, I think I should introduce myself.
My name is Doug Napoleone and I have only been using django for about 6
months. I worked on the PyCon06 PyCon-Tech project and am trying to
kick off the PyCon07 tech work.

http://wiki.python.org/moin/PyCon2006/PyConSoftwareTalk
http://us.pycon.org/apps/

>
> May I interest you in the "Authenticating against Django's user
> database from Apache" document?
>
> http://www.djangoproject.com/documentation/apache_auth/
>
> Adrian
>

There are two issues with the current auth mod_python handler.
1. it doesn't support rich control
i.e. does user A belong to group B and is the sub directory under
this <location> the users directory (given some custom extended user
model). This work can be done using the current handler as a template
and rolling your own, or come up with something more generic. The Idea
is to instead of denoting the permissions on the apache side with
passed in env, have the auth be dynamicly configurable on the django
side based on user, group, request path, etc.

2. it doesn't work with fastcgi.
I am stuck with fastcgi for PHP reasons.

I believe that it is possable to create an extended auth bridge between
apache and django with minimal work. I will not get to this for a few
months, so I thought I would document what I have come up with so far.

If you have django as a fastcgi then you can use it directly for
handling auth verification using:

<Location /protected>
AuthName ProtectedMedia
AuthType Basic
FastCgiAccessChecker django-myproject-fastcgi.py
FastCgiAuthenticator django-myproject-fastcgi.py
FastCgiAuthorizer django-myproject-fastcgi.py
</Location>

(or put the above in the parant directory .htaccess file, sans the
<location> tags)

FastCgiAccessChecker - for verifying ip address and other header checks
return either 403 (Forbidden) or 200 (OK)
FastCgiAuthenticator - for verifying user/password
401 (Unauthorized) for:
no user credentials
invalid credentials
200 (OK)
FastCgiAuthorizer - for verifying access
401 (Unauthorized) - good creds, but no access
200 (OK)

Not all need to be supplied/handled.
Apache will send the full request (but the response is just an auth
response like the current mod_python auth handler). The resuest has two
additional variables in the environment:
FCGI_ROLE == 'AUTHORIZER' (think its 'RESPONDER' for normal
fastcgi)
FCGI_APACHE_ROLL ==
ACCESS_CHECKER - when called from FastCgiAccessChecker
AUTHENTICATOR
AUTHORIZER

A standard middleware could detect these and dispatch to a standardized
auth request interface. I say standardized because the mod_python auth
handler could be modified to use this auth request interface directly
(instead of going through the request handler/middleware framework.) I
need to read up more on the PythonAuthenHandler stuff, but I believe it
has similar distinctions to the FastCgi ones.

The coolness does not stop there (for FastCgi).
Each of the 3 auth request types have an 'Authoritative' flag which
defaults to on.
If turned off, the request is passed to the next apache auth system if
its not 200 (OK).

i.e.:
<Location /protected>
AuthName ProtectedMedia
AuthType Basic
FastCgiAuthenticator django-myproject-fastcgi.py
FastCgiAuthenticatorAuthoritative off
FastCgiAuthorizer django-myproject-fastcgi.py
FastCgiAuthorizerAuthoritative off
AuthUserFile /etc/conf/httpd.conf/auth/admin.auth
require user administrator
</Location>

So if the user is logging in as the apache administrator, even if they
do not have django creds, they will have access.

You can also pass information in via SetEnv.
Your fastcgi auth's can also modify the headerand it will stick to the
next level.
This is usefull for the above example because you may not want to do
the user lookup or passwd check a second time for the
FastCgiAuthorizer. FastCgiAuthenticator can set its status, which
FastCgiAuthorizer can then read and use.

All that needs to be done now is to come up with something that makes
sence for the Auth interface. I believe this is already being done on
the MultiAuth branch.

The end user instructions will be use a new mod_python auth handler for
mod_python, or use a new AuthApacheFastCgi middleware for fastcgi.

I would love some help working on this.

-Doug

Reply all
Reply to author
Forward
0 new messages