views:

591

answers:

3

How do I add a custom header to files pylons is serving from public?

+1  A: 

a) Let your webserver serve files from /public instead of paster and configure it to pass some special headers.

b) Add a special route and serve the files yourself ala

class FilesController(BaseController):
    def download(self, path)
        fapp = FileApp( path, headers=self.get_headers(path) )
        return fapp(request.environ, self.start_response)

c) maybe there is a way to overwrite headers and i just dont know how.

THC4k
I'm wondering if return forward(FileApp(path, headers=...)) would be better. (forward comes from pylons.controllers.util.)
Marius Gedminas
The `FileApp` method works great. Thank you so much - finally a way that actually works!
Evgeny
A: 

With a recent version of route, you can use the 'Magic path_info' feature, and follow the documentation from here to write your controller so it calls paster.DirectoryApp.

In my project, I wanted to serve any file in the public directory, including subdirs, and ended with this as controller, to be able to override content_type :

import logging
from paste.fileapp import FileApp

from paste.urlparser import StaticURLParser
from pylons import config
from os.path import basename

class ForceDownloadController(StaticURLParser):

    def __init__(self, directory=None, root_directory=None, cache_max_age=None):
        if not directory:
            directory = config['pylons.paths']['static_files']
        StaticURLParser.__init__(self, directory, root_directory, cache_max_age)

    def make_app(self, filename):
        headers = [('Content-Disposition', 'filename=%s' % (basename(filename)))]
        return FileApp(filename, headers, content_type='application/octetstream')
Antonin ENFRUN
A: 

In a standard Pylons setup, the public files are served from a StaticUrlParser. This is typically setup in your config/middleware.py:make_app() function

You need to subclass the StaticUrlParser like Antonin ENFRUN describes, though calling it a Controller is confusing because it's doing a different purpose. Add something like the following to the top of the config/middleware.py:

from paste.fileapp import FileApp
from paste.urlparser import StaticURLParser

class HeaderUrlParser(StaticURLParser):
    def make_app(self, filename):
        headers = # your headers here
        return FileApp(filename, headers, content_type='application/octetstream')

then replace StaticUrlParser in config/middleware.py:make_app() with HeaderUrlParser

    static_app = StaticURLParser(config['pylons.paths']['static_files'])

becomes

    static_app = HeaderURLParser(config['pylons.paths']['static_files'])
amashi