Added a simple parser for HTTP request. Can't find anything suitable to use in python...
[ipypbx] / src / ipypbx / http.py
1 # Copyright (c) Stas Shtin, 2010
2
3 # This file is part of IPyPBX.
4
5 # IPyPBX is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9
10 # IPyPBX is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License
16 # along with IPyPBX.  If not, see <http://www.gnu.org/licenses/>.
17
18 from PyQt4 import QtCore, QtNetwork
19
20
21 class FreeswitchConfigServer(QtNetwork.QTcpServer):
22     def setSocket(self, host, port):
23         self.host = host
24         self.port = port
25
26     def startServer(self):
27         self.newConnection.connect(self.clientConnecting)
28         self.listen(QtNetwork.QHostAddress(self.host), self.port)
29
30     def stopServer(self):
31         self.close()
32
33     def clientConnecting(self, socket):
34         if self.hasPendingConnections():
35              connectingClient = self.server.nextPendingConnection()
36              connectingClient.readyRead.connect(self.receiveData)
37
38     def receiveData(self, socket):
39         self.
40         while socket.canReadLine():
41             line = socket.readLine().strip()
42             
43
44
45 class HttpParseError(Exception):
46     pass
47
48
49 class HttpRequestParser(object):
50     """
51     A simple state machine for parsing HTTP requests.
52     """
53     HTTP_NONE, HTTP_REQUEST, HTTP_HEADERS, HTTP_EMPTY, HTTP_MESSAGE = range(5)
54     HTTP_STATES = ['NONE', 'REQUEST', 'HEADERS', 'EMPTY', 'MESSAGE']
55     
56     def __init__(self):
57         super(HttpParser, self).__init__()
58
59     def reset(self):
60         """
61         Reset parser to initial state.
62         """
63         # Initial values for request data.
64         self.method = None
65         self.request_path = None
66         self.http_version = None
67         self.message = ''
68         
69         # Set initial state.
70         self.state = HTTP_NONE        
71
72     def handle(self, line):
73         """
74         Dispatch line to current state handler.
75         """
76         for state in HTTP_STATES:
77             if getattr(self, 'HTTP_%s' % state) == self.state:
78                 getattr(self, 'handle%s' % state.title()).(line)
79                 break
80         else:
81             raise HttpParseError('Unknown HTTP state')
82                 
83     def handleNone(self, line):
84         """
85         Pass line to next state.
86         """
87         self.state += 1
88         self.handle(line)
89
90     def handleRequest(self, line):
91         """
92         Retrieve HTTP method, request path and HTTP version from request.
93         """
94         self.method, self.request_path, self.http_version = line.split(' ')
95         self.state += 1
96
97     def handleHeaders(self, line):
98         """
99         Parse headers while not found an empty line.
100         """
101         if line:
102             key, value = line.split(': ')
103             self.headers[key] = value
104         else:
105             self.state += 1
106
107     def handleEmpty(self, line):
108         """
109         Empty line separator is found - proceed to next state.
110         """
111         self.state += 1
112
113     def handleMessage(self, line):
114         """
115         Append to message body.
116         """
117         self.message += line