Skip to content

Accept header normalization #620

Merged
merged 3 commits into from Aug 23, 2012

3 participants

@lmctv
lmctv commented Jun 8, 2012

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 pyramid_view_accept.py 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 pyramid_view_accept.py
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 pyramid_view_accept.py
Traceback (most recent call last):
  File "pyramid_view_accept.py", line 38, in <module>
    app = config.make_wsgi_app()
  File "/home/lorenzo/pyramid/pyramid/config/__init__.py", line 921, in make_wsgi_app
    self.commit()
  File "/home/lorenzo/pyramid/pyramid/config/__init__.py", line 594, in commit
    self.action_state.execute_actions(introspector=self.introspector)
  File "/home/lorenzo/pyramid/pyramid/config/__init__.py", line 1030, in execute_actions
    for action in resolveConflicts(self.actions):
  File "/home/lorenzo/pyramid/pyramid/config/__init__.py", 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 pyramid_view_accept.py:
        accept="text/HTML")
    Line 18 of file pyramid_view_accept.py:
        accept="text/html")

pyramid_view_accept.py:

#!python
# 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',
             accept="text/HTML")
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',
             accept="text/html")
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])
    else:
        httpport = 6543
    settings = {}
    settings['reload_all'] = True
    settings['debug_all'] = True
    # configuration setup
    config = Configurator(settings=settings)
    config.add_route(name='service', pattern='/')
    config.scan()
    # 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.name, _route.path, _callable, _accept)
    server = make_server('', httpport, app)
    print 'Listening on port %i' % httpport
    server.serve_forever()
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.
34f00ae
@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.
ed9663c
@mcdonc
Pylons Project member
mcdonc commented Jun 13, 2012

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.
ce5b5e4
@mmerickel mmerickel merged commit ce5b5e4 into Pylons:master Aug 23, 2012
@mmerickel
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
Something went wrong with that request. Please try again.