-
Notifications
You must be signed in to change notification settings - Fork 0
/
http-server.py
executable file
·156 lines (133 loc) · 4.77 KB
/
http-server.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
#!/usr/bin/python
# RESTful API server example
# Much of this code thanks to docs.python.org/howto/sockets.html
# We need to make a sockets to make a basic HTTP server
import socket
# Used to get the IP address
import fcntl
import struct
# Used for processing HTTP requests. Needs to be installed (i.e. through pip).
# try to import C parser then fallback in pure python parser.
try:
from http_parser.parser import HttpParser
except ImportError:
from http_parser.pyparser import HttpParser
def get_ip_address(ifname):
'''
Given an interface name (i.e. 'lo' or 'eth0') gives that interface's IP
address. Credit to http://code.activestate.com/recipes/439094/
Probably very specific to Linux, not portable code
'''
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
################
# Set up server
################
# INET, STREAMing socket
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# Bind to the local hostname on a port that probably isn't being used
#serversocket.bind((socket.gethostname(), 3000))
serversocket.bind((get_ip_address('eth1'), 3000))
# Start listening
serversocket.listen(5)
################################
# Process received HTTP requests
################################
# User database, stored as [name, password, number logins] lists
users = []
def process_request(method, path, body):
if method == 'GET':
if path == '/users':
return str(users)
elif path.startswith('/users'):
return str([x for x in users if x[0] == path[len('/users/'):]])
else:
return 'Bad URL'
elif method == 'POST':
if path == '/users/new':
name = body['name']
password = body['password']
if len([x for x in users if x[0] == name]) > 0:
return 'ERROR: User already exists'
users.append([name, password, 0])
return 'User {0} successfully created.'.format(name)
elif path == '/users/changepassword':
name = body['name']
password = body['password']
passwordnew = body['passwordnew']
match_users = [x for x in users if x[0] == name]
if len(match_users) == 0:
return 'ERROR: No such user'
user = match_users[0]
if password != user[1]:
return 'ERROR: Bad password'
user[1] = passwordnew
return 'User {0}\'s password successfully changed.'.format(name)
elif path == '/users/login':
name = body['name']
password = body['password']
match_users = [x for x in users if x[0] == name]
if len(match_users) == 0:
return 'ERROR: No such user'
user = match_users[0]
if password != user[1]:
return 'ERROR: Bad password'
user[2] += 1
return 'User {0} successfully logged in. '.format(name) + \
'Login count: {0}'.format(user[2])
else:
return 'Bad URL'
elif method == 'DELETE':
if path == '/users/delete':
name = body['name']
password = body['password']
match_users = [x for x in users if x[0] == name]
if len(match_users) == 0:
return 'ERROR: No such user'
user = match_users[0]
if password != user[1]:
return 'ERROR: Bad password'
users.remove(user)
return 'User {0} successfully deleted.'.format(name)
else:
return 'Bad URL'
else:
return 'Bad Method'
###################
# Main server loop
###################
response = '''HTTP/1.1 200 OK
Date: Sun, 13 Nov 2011 22:08:44 GMT
Content-Type: text/html; charset=UTF-8
'''
while True:
(clientsocket, address) = serversocket.accept()
parser = HttpParser()
body = []
while True:
data = clientsocket.recv(1024)
if not data:
break
recved = len(data)
nparsed = parser.execute(data, recved)
assert nparsed == recved
if parser.is_headers_complete():
print parser.get_method()
print parser.get_path()
if parser.is_partial_body():
body.append(parser.recv_body())
if parser.is_message_complete():
break
print ''.join(body)
result = process_request(parser.get_method(),
parser.get_path(),
dict([x.split('=') for x in ''.join(body).split('&') if len(x.split('=')) == 2]))
result += '\n'
clientsocket.send(response + str(result))
print result
clientsocket.close()