#1071: let the controller handler define response header Content-Type
----------------------+-----------------------------------------------------
Reporter: dalke | Owner: anonymous
Type: defect | Status: new
Priority: normal | Milestone:
Component: CherryPy | Version: 0.9a5
Severity: normal | Keywords:
----------------------+-----------------------------------------------------
As mentioned in ticket 1070, I have controllers which can respond in a
format selected by a URL parameter. (This parameter is named "format" and
cannot be changed to use "tg_format" or con-neg.)
Sometimes it's plain text. In that case I do something like
{{{
def format_as_raw_text():
cherrypy.response.headers["Content-Type"] = "text/plain"
def response():
yield "Perhaps this is over kill. Doing it this way "
yield "so I know the header is set before I return anything.\n"
yield "I should read the cherrypy docs on this.\n"
return response()
}}}
I expected that I could do the same when I choose to respond via XML
{{{
def format_as_das2xml():
cherrypy.response.headers["Content-Type"] = "application/x-das2text+xml"
return dict(question="What's the capital of Florida?",
answer="Umm.... 'F'!",
tg_format="xml",
tg_template="das2.templates.q_and_a")
}}}
With patch 1070 the "tg_format" works so the returned template is correct.
Rather, it generates a correct byte stream in the HTTP payload. The
header is not correct.
It shows a content-type of "text/xml; charset='utf-8'".
In more details, the content-type before calling my handler is
"text/html". My handler sets it to "application/x-...+xml". Then
turbogears.view.base.render looks as the @expose setting, sees there is no
"content_type", and the response header to the "text/html;
charset='utf-8'".
This is annoying. I didn't set the @expose content_type because there is
no meaningful value at that point, but I do have one later on.
I came up with two solutions. First, I could use the approach of
"tg_template" (and "tg_format" in patch 1070) and return a
"tg_content_type" in the dictionary. I rejected this because it's
different than what I would do with the plain text solution, where I set
the response header myself. I want the two to be structurally similar so
if one sets cherrypy.headers[...] then the other should as well.
Second I could set the initial response Content-Type to None. If after
calling the user-defined controller handler the Content-Type is set then
use the new value. Here's the relevant change to
controller.py:_execute_func
{{{
old_content_type = cherrypy.response.headers["Content-Type"]
cherrypy.response.headers["Content-Type"] = None
output = errorhandling.try_call(func, *args, **kw)
if cherrypy.response.headers["Content-Type"] is not None:
content_type = cherrypy.response.headers["Content-Type"]
else:
content_type = old_content_type
}}}
I think of this as a hack. If this is the right approach then I think
TurboGears should set "server.default_content_type" to None (is that
possible?) so CherryPy's response header starts off being None instead of
"text/html". Only after the controller handler is run should TG check the
content-type and if it's still None then set it based on the various other
settings.
Or not. Who gets to override whom? Does the controller function override
the @expose or vice versa? In my case the @expose's content_type is None
so it doesn't matter.
--
Ticket URL: <http://trac.turbogears.org/turbogears/ticket/1071>
TurboGears <http://www.turbogears.org/>
TurboGears front-to-back web development
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"TurboGears Tickets" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/turbogears-tickets
-~----------~----~----~----~------~----~------~--~---