~didrocks/unity/altf10

« back to all changes in this revision

Viewing changes to grackle/service.py

  • Committer: Curtis Hovey
  • Date: 2012-03-17 23:01:16 UTC
  • Revision ID: curtis.hovey@canonical.com-20120317230116-vjf7ztzwg0asr2x0
Use wsgiref.headers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
__metaclass__ = type
 
2
__all__ = [
 
3
    'ForkedFakeService',
 
4
    'GrackleService',
 
5
    ]
2
6
 
3
7
import httplib
4
8
import logging
6
10
from signal import SIGKILL
7
11
import simplejson
8
12
import sys
 
13
from wsgiref.headers import Headers
9
14
from wsgiref.simple_server import make_server
10
15
from wsgiref.util import shift_path_info
 
16
 
11
17
from grackle.store import (
12
18
    MemoryStore,
13
19
    )
14
20
 
15
21
 
16
22
class GrackleService:
17
 
    """A request handler that forwards to server.store."""
 
23
    """A request handler that forwards to an archive store."""
18
24
 
19
25
    def __init__(self, store):
20
26
        self.store = store
23
29
    def __call__(self, environ, start_response):
24
30
        self.environ = environ
25
31
        self.start_response = start_response
 
32
        self.headers = Headers([('content-type', 'application/json')])
26
33
        self.method = environ['REQUEST_METHOD']
27
 
        self.host_port = shift_path_info(environ)
28
 
        self.application = shift_path_info(environ)
29
 
        self.path = environ['PATH_INFO'].split('/')[1:]
 
34
        if '://' in environ['PATH_INFO']:
 
35
            # All the needed information is embedded in PATH_INFO.
 
36
            shift_path_info(environ)  # shift the host and or port.
 
37
            self.application = shift_path_info(environ)
 
38
            path = environ['PATH_INFO'].split('/')
 
39
            path.pop(0)  # Pop the scheme.
 
40
            self.path = path
 
41
        elif environ['SCRIPT_NAME'] == '':
 
42
            # Remove the application to set the path.
 
43
            self.application = shift_path_info(environ)
 
44
            self.path = environ['PATH_INFO'].split('/')
 
45
        else:
 
46
            self.application = environ['SCRIPT_NAME']
 
47
            self.path = environ['PATH_INFO'].split('/')
30
48
        self.query_string = environ['QUERY_STRING']
31
49
        return self.handle_request()
32
50
 
33
51
    def handle_request(self):
34
 
        if self.method == 'PUT':
 
52
        """Select the method to handle the request and return a response."""
 
53
        if self.application != 'archive':
 
54
            return self.send_response(httplib.NOT_FOUND)
 
55
        elif self.method == 'PUT':
35
56
            return self.do_PUT()
36
 
        if self.method == 'POST':
 
57
        elif self.method == 'POST':
37
58
            return self.do_POST()
38
 
        if self.method == 'GET':
 
59
        elif self.method == 'GET':
39
60
            return self.do_GET()
 
61
        return self.send_response(httplib.METHOD_NOT_ALLOWED)
40
62
 
41
 
    def send_response(self, code, headers={}, reason=None):
 
63
    def send_response(self, code, response='', reason=None):
 
64
        """Set the status code and reason, then return the response."""
42
65
        if reason is None:
43
 
            reason = httplib.responses[code].upper()
44
 
        response_code = '%s %s' % (code, reason)
45
 
        response_headers = {'content-type': 'application/json'}
46
 
        response_headers.update(headers.items())
47
 
        self.start_response(response_code, response_headers.items())
 
66
            reason = httplib.responses[code]
 
67
        response_status = '%s %s' % (code, reason)
 
68
        self.start_response(response_status, self.headers.items())
 
69
        return [response]
48
70
 
49
71
    def do_PUT(self):
50
72
        """Create an archive or message on PUT."""
52
74
            # This expected path is /archive/archive_id.
53
75
            try:
54
76
                self.store.put_archive(self.path[0])
55
 
                self.send_response(httplib.CREATED)
56
 
                return ['']
 
77
                return self.send_response(httplib.CREATED)
57
78
            except Exception, error:
58
 
                self.send_response(
 
79
                return self.send_response(
59
80
                    httplib.BAD_REQUEST, reason=error.__doc__)
60
 
                return ['']
61
 
        if len(self.path) == 2:
 
81
        elif len(self.path) == 2:
62
82
            # This expected path is /archive/archive_id/message_id.
63
83
            try:
64
84
                put_input = self.environ['wsgi.input']
65
85
                message = put_input.read(int(self.environ['CONTENT_LENGTH']))
66
86
                self.store.put_message(self.path[0], self.path[1], message)
67
 
                self.send_response(httplib.CREATED)
68
 
                return ['']
69
 
            except:
70
 
                self.send_response(httplib.BAD_REQUEST)
71
 
                return ['']
 
87
                return self.send_response(httplib.CREATED)
 
88
            except Exception, error:
 
89
                return self.send_response(
 
90
                    httplib.BAD_REQUEST, reason=error.__doc__)
72
91
 
73
92
    def do_POST(self):
74
93
        """Change a message on POST."""
78
97
                # This expected path is /archive/archive_id/message_id.
79
98
                response = self.store.hide_message(
80
99
                    self.path[0], self.path[1], self.query_string)
81
 
                self.send_response(httplib.OK)
82
 
                return [simplejson.dumps(response)]
83
 
            except:
84
 
                self.send_response(httplib.BAD_REQUEST)
85
 
                return ['']
 
100
                response = simplejson.dumps(response)
 
101
                return self.send_response(httplib.OK, response=response)
 
102
            except Exception, error:
 
103
                return self.send_response(
 
104
                    httplib.BAD_REQUEST, reason=error.__doc__)
86
105
 
87
106
    def do_GET(self):
88
107
        """Retrieve a list of messages on GET."""
89
108
        try:
90
109
            response = self.store.get_messages(
91
110
                self.path[0], self.query_string)
92
 
            self.send_response(httplib.OK)
93
 
            return [simplejson.dumps(response)]
 
111
            response = simplejson.dumps(response)
 
112
            return self.send_response(httplib.OK, response=response)
94
113
        except Exception, error:
95
 
            self.send_response(httplib.BAD_REQUEST, reason=error.__doc__)
96
 
            return ['']
 
114
            return self.send_response(
 
115
                httplib.BAD_REQUEST, reason=error.__doc__)
97
116
 
98
117
    def log_message(self, format, *args):
99
118
        """Override log_message to use standard Python logging."""
164
183
        os.kill(self.pid, SIGKILL)
165
184
 
166
185
 
167
 
def application(environ, start_response):
168
 
    start_response('200 OK', [('Content-Type', 'text/plain')])
169
 
    return "Hello World"
170
 
 
171
 
 
172
186
if __name__ == '__main__':
173
187
    app = GrackleService(MemoryStore({}))
174
188
    service = make_server('', 8787, app)