summaryrefslogtreecommitdiff
path: root/repoze/bfg/request.py
blob: 20e8070fcf03650e01754c253c63a2045d7a4859 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from zope.interface import implements
from webob import Request as WebobRequest

from zope.deprecation import deprecated
from zope.interface.interface import InterfaceClass

from repoze.bfg.interfaces import IRequest
from repoze.bfg.interfaces import IGETRequest
from repoze.bfg.interfaces import IPOSTRequest
from repoze.bfg.interfaces import IPUTRequest
from repoze.bfg.interfaces import IDELETERequest
from repoze.bfg.interfaces import IHEADRequest

def request_factory(environ):
    try:
        method = environ['REQUEST_METHOD']
    except KeyError:
        method = None

    if 'bfg.routes.route' in environ:
        route = environ['bfg.routes.route']
        request_factories = route.request_factories
    else:
        request_factories = DEFAULT_REQUEST_FACTORIES

    try:
        request_factory = request_factories[method]['factory']
    except KeyError:
        request_factory = request_factories[None]['factory']

    return request_factory(environ)

def make_request_ascii(event):
    """ An event handler that causes the request charset to be ASCII;
    used as an INewRequest subscriber so code written before 0.7.0 can
    continue to work without a change"""
    request = event.request
    request.charset = None

def named_request_factories(name=None):
    # We use 'precooked' Request subclasses that correspond to HTTP
    # request methods when returning a request object from
    # ``request_factory`` rather than using ``alsoProvides`` to attach
    # the proper interface to an unsubclassed webob.Request.  This
    # pattern is purely an optimization (e.g. preventing calls to
    # ``alsoProvides`` means the difference between 590 r/s and 690
    # r/s on a MacBook 2GHz).  This method should be never imported
    # directly by user code; it is *not* an API.
    if name is None:
        default_iface = IRequest
        get_iface = IGETRequest
        post_iface = IPOSTRequest
        put_iface = IPUTRequest
        delete_iface = IDELETERequest
        head_iface = IHEADRequest
    else:
        IC = InterfaceClass
        default_iface = IC('%s_IRequest' % name, (IRequest,))
        get_iface = IC('%s_IGETRequest' % name, (default_iface, IGETRequest))
        post_iface = IC('%s_IPOSTRequest' % name, (default_iface, IPOSTRequest))
        put_iface = IC('%s_IPUTRequest' % name, (default_iface, IPUTRequest))
        delete_iface = IC('%s_IDELETERequest' % name, (default_iface,
                                                       IDELETERequest))
        head_iface = IC('%s_IHEADRequest' % name, (default_iface,
                                                   IHEADRequest,))
        
    class Request(WebobRequest):
        implements(default_iface)
        charset = 'utf-8'

    class GETRequest(WebobRequest):
        implements(get_iface)
        charset = 'utf-8'

    class POSTRequest(WebobRequest):
        implements(post_iface)
        charset = 'utf-8'
    
    class PUTRequest(WebobRequest):
        implements(put_iface)
        charset = 'utf-8'

    class DELETERequest(WebobRequest):
        implements(delete_iface)
        charset = 'utf-8'

    class HEADRequest(WebobRequest):
        implements(head_iface)
        charset = 'utf-8'

    factories = {
        IRequest:{'interface':default_iface, 'factory':Request},
        IGETRequest:{'interface':get_iface, 'factory':GETRequest},
        IPOSTRequest:{'interface':post_iface, 'factory':POSTRequest},
        IPUTRequest:{'interface':put_iface, 'factory':PUTRequest},
        IDELETERequest:{'interface':delete_iface, 'factory':DELETERequest},
        IHEADRequest:{'interface':head_iface, 'factory':HEADRequest},
        None:{'interface':default_iface, 'factory':Request},
        'GET':{'interface':get_iface, 'factory':GETRequest},
        'POST':{'interface':post_iface, 'factory':POSTRequest},
        'PUT':{'interface':put_iface, 'factory':PUTRequest},
        'DELETE':{'interface':delete_iface, 'factory':DELETERequest},
        'HEAD':{'interface':head_iface, 'factory':HEADRequest},
        }

    return factories

DEFAULT_REQUEST_FACTORIES = named_request_factories()

from repoze.bfg.threadlocal import get_current_request as get_request # b/c

deprecated('get_request',
           'As of repoze.bfg 1.0, any import of get_request from'
           '``repoze.bfg.request`` is '
           'deprecated.  Use ``from repoze.bfg.threadlocal import '
           'get_current_request instead.')