Accept header normalization #620

merged 3 commits into from Aug 23, 2012

3 participants


According to RFC 2616, the mimetype in the accept header should be matched in a case insensitive way.

While fixing the root case insensitivity in webob (Pylons/webob#56), I noticed a glitch in view registration: if you run with an unpatched pyramid, both the view callables get registered; which one will be called depends on the client-supplied Accept header, and the webob available version...

$ python
Route: service, Path: /, Callable: service_HTML, Accept: text/HTML
Route: service, Path: /, Callable: service_html, Accept: text/html
Listening on port 6543
Accept: text/html
localhost.localdomain - - [08/Jun/2012 18:05:41] "GET / HTTP/1.1" 200 92
Accept: text/HTML
localhost.localdomain - - [08/Jun/2012 18:10:39] "GET / HTTP/1.0" 200 92

With the proposed patches, the configurator would notice the attempted shadowing and correctly raises a ConfigurationConflictError:

$ python
Traceback (most recent call last):
  File "", line 38, in <module>
    app = config.make_wsgi_app()
  File "/home/lorenzo/pyramid/pyramid/config/", line 921, in make_wsgi_app
  File "/home/lorenzo/pyramid/pyramid/config/", line 594, in commit
  File "/home/lorenzo/pyramid/pyramid/config/", line 1030, in execute_actions
    for action in resolveConflicts(self.actions):
  File "/home/lorenzo/pyramid/pyramid/config/", line 1136, in resolveConflicts
    raise ConfigurationConflictError(conflicts)
pyramid.exceptions.ConfigurationConflictError: Conflicting configuration actions
  For: ('view', None, '', None, <InterfaceClass pyramid.interfaces.IView>, None, None, ('GET', 'HEAD'), 'service', None, False, 'text/html', None, None, None)
    Line 12 of file
    Line 18 of file

# encoding: utf-8

from pyramid.config import Configurator
from wsgiref.simple_server import make_server
from pyramid.view import view_config
from pyramid.response import Response

import sys

@view_config(route_name='service', request_method='GET',
def service_HTML(request):
    return Response('<html><head><title>HTML SERVICE</title></head><body><p>route_name=service</p></body></html>\n')

@view_config(route_name='service', request_method='GET',
def service_html(request):
    return Response('<html><head><title>html service</title></head><body><p>route_name=service</p></body></html>\n')

if __name__ == '__main__':
    # configuration settings
    if len(sys.argv) > 1:
        httpport = int(sys.argv[1])
        httpport = 6543
    settings = {}
    settings['reload_all'] = True
    settings['debug_all'] = True
    # configuration setup
    config = Configurator(settings=settings)
    config.add_route(name='service', pattern='/')
    # serve app
    app = config.make_wsgi_app()
    # print view mappings
    rt_map = config.get_routes_mapper()
    views = config.introspector.get_category('views')
    for view in views:
        _callable = view['introspectable']['callable'].__name__
        _accept = view['introspectable']['accept']
        _route_nm = view['introspectable']['route_name']
        _route = rt_map.get_route(_route_nm)
        if _route:
            print 'Route: %s, Path: %s, Callable: %s, Accept: %s' % (, _route.path, _callable, _accept)
    server = make_server('', httpport, app)
    print 'Listening on port %i' % httpport
lmctv added some commits Jun 8, 2012
@lmctv lmctv RFC 2616 sec. 3.7 case insensitive match test
Since "... The type, subtype, and parameter attribute names are case-
insensitive..." the type and subtype in the accept parameter in add_view
should be treated in a case insensitive way.
@lmctv lmctv Lowercase the accept parameter in add_view
Fix the RFC 2616 sec. 3.7 compliance by storing a canonical cased
version of the parameter.
Pylons Project member

This looks good. Do you think you can also put your name in CONTRIBUTORS.txt (in the Pyramid root project dir)?

@lmctv lmctv Accept the Contributor Agreement.
as suggested by "Contributing Source Code and Documentation" document.
@mmerickel mmerickel merged commit ce5b5e4 into Pylons:master Aug 23, 2012
Pylons Project member

thanks, I fixed a py3 compatibility and updated changes.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment