Issue #829 resolved

@tools.response.headers doesn't appear to work with response.stream True

Anonymous created an issue

Using CherryPy 3.0.3.

I have a method setup as such:

{{{

!python

@cherrypy.expose @cherrypy.tools.response_headers(headers = \ [('Content-Type','application/data')]) def my_method: ... yield "blah" ...

my_method._cp_config = { 'response.stream': True } }}}

Whenever the method is executed by cherrypy's default dispatcher, the Content-Type is text/html, not application/data as I expected.

However, if I changed the method setup to be like this:

{{{

!python

@cherrypy.expose def my_method: ... yield "blah" ...

my_method._cp_config = { 'response.stream': True, 'tools.response_headers.on': True, 'tools.response_headers.headers': [('Content-Type', 'application/data')] } }}}

...then it works.

Ideas?

Reported by swalker@opensolaris.org

Comments (9)

  1. Robert Brewer

    When a Tool is used as a decorator, it simply sets _cp_config on the function for you. What is the value of my_method._cp_config?

    My guess is this is due to a bad interaction between the expose decorator and the tool decorator.

  2. Robert Brewer

    [1992] shows why this fails: the Tool decorator sets `_cp_config` behind the scenes, which is then replaced wholesale by `func._cp_config = {...}`. The workaround is to instead write:

    @cherrypy.expose
    @cherrypy.tools.response_headers(headers = \
               [('Content-Type','application/data')])
    def my_method:
            ...
            yield "blah"
            ...
    
    my_method._cp_config['response.stream'] = True
    

    It's a shame I can't think of a way for cherrypy.checker to catch that.

    What might be easier would be to introduce a new cherrypy.cp_config decorator to set `_cp_config` entries, so the above would become:

    @cherrypy.expose
    @cherrypy.tools.response_headers(
        headers = [('Content-Type', 'application/data')])
    @cherrypy.cp_config({'response.stream': True})
    def my_method:
            ...
            yield "blah"
            ...
    

    This could be made to add or update the dict as necessary (just like Tool does). I would expect it to take a single dict arg, or possibly kwargs, or both. Another alternative would be to make each config namespace callable as a decorator (e.g. `Request(stream=True)`), but I think that would be too much of a burden to place on the authors of config namespaces.

    Either approach is a bit radical to stick into 3.1, so I'm saving this for 3.2. The workaround should be enough for now.

  3. Anonymous

    Ah! I'm an idiot.

    You're completely right about the _cp_config redefining it. I just didn't make the immediate connection.

    I'd say documentation could suffice here, but it seems like a very subtle thing.

    I'd consider this an enhancement though, so feel free to de-prioritise or re-categorise as an enhancement.

    Thanks!

  4. Log in to comment