views:

253

answers:

2

I'm new to mod_python and Apache, and I'm having trouble returning a file to a user after a GET request. I've got a very simple setup right now, and was hoping to simply open the file and write it to the response:

from mod_python import apache

def handler(req):
    req.content_type = 'application/octet-stream'
    fIn = open('response.bin', 'rb')
    req.write(fIn.read())
    fIn.close()
    return apache.OK

However, I'm getting errors when I use open(), saying that the file doesn't exist (even though I've checked a dozen times that it does). This happens when using relative and absolute filepaths.

I've got two questions:

  • Why isn't open() finding the right files?
  • What is the best way to return a file from the filesystem? (I ask to make sure I'm not missing some better way to use mod_python to return a file.)

Thanks

Edit: After finding this thread: http://www.programmingforums.org/thread12384.html I discovered that open() works for me if I move the file to another directory outside of home (I was aliasing out of /home/myname/httpdocs, but it works if I use /data). Any ideas why that works?

Edit 2: Part of my debug error, as requested:

MOD_PYTHON ERROR

ProcessId:      13642
Interpreter:    '127.0.1.1'

ServerName:     '127.0.1.1'
DocumentRoot:   '/var/www'

URI:            '/test/mptest.py'
Location:       None
Directory:      '/home/myname/httpdocs/'
Filename:       '/home/myname/httpdocs/mptest.py'
PathInfo:       ''

Phase:          'PythonHandler'
Handler:        'mptest'

Traceback (most recent call last):

  File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1537, in HandlerDispatch
    default=default_handler, arg=req, silent=hlist.silent)

  File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1229, in _process_target
    result = _execute_target(config, req, object, arg)

  File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1128, in _execute_target
    result = object(arg)

  File "/home/myname/httpdocs/mptest.py", line 13, in handler
    fIn = open('/home/myname/httpdocs/files/response.bin', 'rb')

IOError: [Errno 2] No such file or directory: '/home/myname/httpdocs/files/response.bin'
+4  A: 

To debug this kind of thing, you need to gather all information from the running mod_python instance.

Stop messing with "checking a dozen times that it [exists]". Some assumption isn't correct.

Do something like this to get some debugging information.

def handler(req):
    req.content_type = 'text/plain'
    req.write(os.environ)
    req.write(os.getcwd())
    # etc.
    return apache.OK


Edit

Now you have a glimpse of the Important Stuff. In this case it might be permissions -- you'll need to use os.filestat to be sure. Apache runs mod_python as a user who has almost no usable permissions. Apache does not like links, either, but this shouldn't affect mod_python. If your file doesn't have read-by-everybody and isn't in the right directory you'll have problems.

You might want to switch to mod_wsgi.

S.Lott
I've updated my question after finding a clue on what's going on. Also I tried your advice and found out some interesting factoids: mod_python runs as "www-data", and runs out of "/".
A: 

Could you paste the error(s) you get?

It's likely to be a permission error (if you tried using the full path to the file). Remember the script runs as the user running the web-server process - so you will be accessing the file as "www-data", or "nobody" usually.

Check the permissions of the folder /home/myname/httpdocs/files/ also. The folder should be +x for the www-data user:

$ mkdir blah
$ echo works > blah/response.bin
$ chmod 000 blah/
$ cat blah/response.bin
cat: blah/response.bin: Permission denied
$ chmod +x blah/
$ cat blah/response.bin
works

You could eliminate Apache/your-script from the equation by doing the following:

you:~$ sudo su - www-data
www-data:~$ file /home/myname/httpdocs/files/response.bin

(the su may not work, depending on what OS/distribution you are using, for example OS X prevents you logging in as it's www user)

File permissions aside, why is the script dependant on a file in your home folder anyway? Can response.bin be moved to the same folder as your Python script? Or possibly even moved into a database? (perhaps SQLite? Might be unnecessary/excessive, depending on what is in response.bin and how much it changes)

dbr
I've pasted most of an error to my question. However, I have tried chowning the files to www-data without success. (Maybe I'm misunderstanding Unix OS permissions, though)