-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathasynchat_demo.py
executable file
·162 lines (134 loc) · 4.42 KB
/
asynchat_demo.py
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# -*- coding: utf-8 -*-
import time
import socket
import asynchat
import asyncore
from asyncore import dispatcher
PORT = 8008
class HTTPHeaders(dict):
def getheader(self, key):
return self.get(key)
class HTTPHandler(asynchat.async_chat):
def __init__(self, sock, addr):
asynchat.async_chat.__init__(self, sock=sock)
self.addr = addr
self.ibuffer = []
self.obuffer = ""
self.set_terminator(b'\r\n\r\n')
self.reading_headers = True
self.handling = False
self.cgi_data = None
def parse_headers(self, data):
headers_lines = data.split('\r\n')
self.request_method, self.path, self.request_version = headers_lines[0].split()
self.headers = HTTPHeaders(header.split(': ', 1) for header in headers_lines[1:])
def handle_request(self):
if self.path == '/':
status = '200 OK'
else:
status = '404 NOT FOUND'
server_headers = HTTPHeaders([
('Date', time.ctime()),
('Server', 'AsynChat 0.1')
])
self.headers_set = [status, server_headers]
self.log_info('%s:%s %s for %s' % (self.addr[0], self.addr[1], self.request_method, self.path))
if self.cgi_data and self.request_method == 'POST':
self.handle_post()
else:
self.handle_get()
def handle_post(self):
response_body = """
<html>
<head>
<title>WOW</title>
</head>
<body>
<h2>Hello {name}</h2>
<p>Your mail is {mail}</p>
</body>
</html>
""".format(**self.cgi_data)
status, response_headers = self.headers_set
response_headers.update(dict([('Content-Type', 'text/html'),
('Content-Length', len(response_body))]))
response = 'HTTP/1.1 {status}\r\n'.format(status=status)
for header in response_headers.items():
response += "{0}: {1}\r\n".format(*header)
response += '\r\n'
response += response_body
self.push(response.encode('utf-8'))
def handle_get(self):
if self.path == '/':
response_body = """
<html>
<head>
<title>WOW</title>
</head>
<body>
<h2>Wow, Python Server</h2>
<p>Hello World</p>
<form method="post" action="">
Input Your name: <input type="text" name="name"><br>
Input Your mail: <input type='mail' name='mail'><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
"""
else:
response_body = """
<html>
<head>
<title>WOW</title>
</head>
<body>
<h2>Oops ... The page is not found</h2>
</body>
</html>
"""
status, response_headers = self.headers_set
response_headers.update(dict([('Content-Type', 'text/html'),
('Content-Length', len(response_body))]))
response = 'HTTP/1.1 {status}\r\n'.format(status=status)
for header in response_headers.items():
response += "{0}: {1}\r\n".format(*header)
response += '\r\n'
response += response_body
self.push(response.encode('utf-8'))
def parse(self, headers, data):
return dict([expr.split('=') for expr in data.split('&')])
def collect_incoming_data(self, data):
"""Buffer the data"""
self.ibuffer.append(data)
def found_terminator(self):
if self.reading_headers:
self.reading_headers = False
self.parse_headers(b''.join(self.ibuffer).decode('utf-8'))
self.ibuffer = []
if self.request_method.upper() == "POST":
clen = self.headers.getheader("Content-Length")
self.set_terminator(int(clen))
else:
self.handling = True
self.set_terminator(None)
self.handle_request()
elif not self.handling:
self.set_terminator(None) # browsers sometimes over-send
self.cgi_data = self.parse(self.headers, b''.join(self.ibuffer).decode('utf-8'))
self.handling = True
self.ibuffer = []
self.handle_request()
class HTTPServer(dispatcher):
def __init__(self, port):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(('', port))
self.listen(5)
def handle_accept(self):
conn, addr = self.accept()
HTTPHandler(conn, addr)
if __name__ == '__main__':
h = HTTPServer(PORT)
asyncore.loop()