How can I set a custom response header for pylons

2020-02-12 18:17发布

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

4条回答
放我归山
2楼-- · 2020-02-12 18:42

A simpler way to use FileApp for streaming, based on the pylons book. The code below assumes your route provides some_file_identifier, but the other two variables are "magic" (see explanation after code).

class MyFileController(BaseController):
  def serve(self, environ, start_response, some_file_identifier):
      path = self._convert_id_to_path(some_file_identifier)
      app = FileApp(path)
      return app(environ, start_response)

Pylons automatically gives you the wsgi environ and start_response variables if you have variables of those names in your method signature. You should not need to set or munge headers otherwise, but if you do you can use the abilities built in to FileApp to achieve this.

查看更多
祖国的老花朵
3楼-- · 2020-02-12 18:47

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.

查看更多
不美不萌又怎样
4楼-- · 2020-02-12 18:56

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')
查看更多
太酷不给撩
5楼-- · 2020-02-12 18:58

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'])
查看更多
登录 后发表回答