Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #1842 (closed enhancement: fixed)

Opened 10 years ago

Last modified 10 years ago

Determination of the right content type for template engines

Reported by: chrisz Owned by: anonymous
Priority: normal Milestone: 1.5
Component: TurboGears Version:
Severity: normal Keywords: TurboJson


There are some problems with the determination of the right content type for TurboJson and other template engines (see also ticket #1480).

If no content type is explicitly requested, the generic render() function in view/base.py calls a method get_content_type(user_agent) of the template engine, currently only implemented by TurboJson.

  • Issue 1: TurboJson always returns "text/javascript", but nowadays "application/json" should be used. I'd like to change that, and make expose() also understand "application/json". MochiKit also uses that content type in loadJSONDoc.
  • Issue 2: There is actually a case destinction for Opera as the user agent, where "text/plain" is returned. But since the user agent is always passed as None due to a bug in view/base.py, this case distinction has never been effective. And I don't know if it was ever needed, surely not for current Opera versions. So I'd like to completely remove that.
  • Issue 3: Should get_content_type really be a function? If yes, what input parameters does it need? I think much more important than the user_agent are the accept header and the format parameter. For instance, if format is 'plain', then get_content_type (if implemented in TurboKid, for instance) should return 'text/plain'. Currently we need to set content_type explicitly to 'text/plain'.
  • Issue 4: I noticed that the expose decorator gets passed the full Accept header in controller.py. But the Accept header can be a list. Shouldn't we better pass only the first item of that list?


preferred_type.py Download (1.8 KB) - added by chrisz 10 years ago.
Determination of the preferred media type

Change History

comment:1 follow-up: ↓ 2 Changed 10 years ago by chrisz

To clarify Issue 4: I actually mean the _expose function, not the expose decorator. It's accept parameter is compared with the accept_format argument of the expose decorator. And with "list" I mean a string with a list of accepted formats like


Wouldn't it make more sense to set accept to text/xml only in this case?

comment:2 in reply to: ↑ 1 Changed 10 years ago by chrisz

Another and maybe better solution for issue 4 is to parse the accept header into a real list or set, and to replace the comparisons with == in the rules in controllers.py with in operations, i.e. (accept_format in accept instead of accept == accept_format).

comment:3 Changed 10 years ago by chrisz

Concerning the last suggestion for issue 4, this could lead to conflicting rules if more than one mime type is accepted. Also, the format of the accept header is a bit complicated. It can include media ranges and qvalues (see RFC2616). It may be best to reduce the accept header to the most preferred media type (which can be a range, though). For instance

Accept: text/plain; q=0.5, text/html,
               text/x-dvi; q=0.8, text/x-c

should be reduced to just "text/x-c".

comment:4 Changed 10 years ago by chrisz

The example above should be reduced to "text/html" because that comes first. Both text/html and text/x-c have a qvalue of 1.

Also, a media type of "text/html;level=1" should be reduced to simply "text/html".

comment:5 Changed 10 years ago by chrisz

Concerning issue 4, I've now attached a function for determining the preferred media type, so we can write: accept_format==preferred_type(accept).

Changed 10 years ago by chrisz

Determination of the preferred media type

comment:6 Changed 10 years ago by chrisz

Just noticed that a similar function parse_http_accept_header already exists in turbogears.util, but that function returns a list. I improved it a bit (proper handling of whitespace, media range parameters and zero qvalues) and accompanied it with a function simplify_http_accept_header similar to preferred_type (r4715), which is now called before the comparison with accept_format (r4716). This should solve issue 4.

comment:7 Changed 10 years ago by chrisz

  • Status changed from new to closed
  • Resolution set to fixed

Issues 1-3 have now been solved in r4724. The content type is now determined from the format parameter, so that get_content_type gets obsolete. Setting the content type in the response header has been moved from view.render to controllers._process_output, as suggested by ChrisA.

Note: See TracTickets for help on using tickets.