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
|
#!/usr/bin/env python
'''
Simple dispatcher for the REST API.
Only intended for test purposes.
License
-------
* ===================================================================
* Copyright © 2017 AT&T Intellectual Property. All rights reserved.
* ===================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
'''
import logging
logger = logging.getLogger('collector.disp')
base_url = ''
template_404 = b'''POST {0}'''
def set_404_content(url):
'''
Called at initialization to set the base URL so that we can serve helpful
diagnostics as part of the 404 response.
'''
global base_url
base_url = url
return
def notfound_404(environ, start_response):
'''
Serve the 404 Not Found response.
Provides diagnostics in the 404 response showing the hierarchy of valid
REST resources.
'''
logger.warning('Unexpected URL/Method: {0} {1}'.format(
environ['REQUEST_METHOD'].upper(),
environ['PATH_INFO']))
start_response('404 Not Found', [ ('Content-type', 'text/plain') ])
return [template_404.format(base_url)]
class PathDispatcher:
'''
A dispatcher which can take HTTP requests in a WSGI environment and invoke
appropriate methods for each request.
'''
def __init__(self):
'''Constructor: initialize the pathmap to be empty.'''
self.pathmap = { }
def __call__(self, environ, start_response):
'''
The main callable that the WSGI app will invoke with each request.
'''
#----------------------------------------------------------------------
# Extract the method and path from the environment.
#----------------------------------------------------------------------
method = environ['REQUEST_METHOD'].lower()
path = environ['PATH_INFO']
logger.info('Dispatcher called for: {0} {1}'.format(method, path))
logger.debug('Dispatcher environment is: {0}'.format(environ))
#----------------------------------------------------------------------
# See if we have a handler for this path, and if so invoke it.
# Otherwise, return a 404.
#----------------------------------------------------------------------
handler = self.pathmap.get((method, path), notfound_404)
logger.debug('Dispatcher will use handler: {0}'.format(handler))
return handler(environ, start_response)
def register(self, method, path, function):
'''
Register a handler for a method/path, adding it to the pathmap.
'''
logger.debug('Registering for {0} at {1}'.format(method, path))
print('Registering for {0} at {1}'.format(method, path))
self.pathmap[method.lower(), path] = function
return function
|