1
1
import string ,cgi ,time ,traceback , threading , SocketServer , BaseHTTPServer , os .path , urllib
2
+ import SimpleHTTPServer
2
3
import ottd_config
3
4
from ottd_lib import DataStorageClass
4
5
from log import LOG
5
6
try :
6
7
import json
7
8
except ImportError :
8
9
import simplejson as json
9
- import pickle
10
+ try :
11
+ import cPickle as pickle
12
+ except ImportError :
13
+ import pickle
10
14
11
- ext2conttype = {"jpg" : "image/jpeg" ,
12
- "jpeg" : "image/jpeg" ,
13
- "png" : "image/png" ,
14
- "gif" : "image/gif" ,
15
- "html" : "text/html" ,
16
- "htm" : "text/html" ,
17
- "swf" : "application/x-shockwave-flash" ,
18
- "xml" : "text/xml" ,
19
- }
20
15
def content_type (filename ):
21
- ext = filename [filename .rfind ("." )+ 1 :].lower ()
22
- if ext in ext2conttype .keys ():
23
- return ext2conttype [ext ]
16
+ ext = filename [filename .rfind ("." ):].lower ()
17
+ map = SimpleHTTPServer .SimpleHTTPRequestHandler .extensions_map
18
+ if ext in map :
19
+ return map [ext ]
24
20
else :
25
- return "text/html"
21
+ return map [ '' ]
26
22
27
23
class DataStorageJSONEncoder (json .JSONEncoder ):
28
24
def default (self , obj ):
@@ -43,18 +39,26 @@ def loadTemplate(self, name):
43
39
return fc
44
40
else :
45
41
return None
46
-
47
- def sendError (self , num = 404 ):
48
- txt = """\
49
- <html>
50
- <head><title>404 file not found</title></head>
51
- <body>404 file not found</body>
52
- </html>\n """
53
- self .send_response (num )
54
- self .send_header ("Content-type" , "text/html" )
55
- self .send_header ("Content-Length" , str (len (txt )))
56
- self .end_headers ()
57
- self .wfile .write (txt )
42
+ def compress (self , data ):
43
+ try :
44
+ enc = self .headers .getheader ("Accept-Encoding" ).split (',' )
45
+ fmt = []
46
+ for e in enc : fmt .append (e .strip ())
47
+ except :
48
+ fmt = []
49
+ def encoder (data ):
50
+ return data
51
+ format = None
52
+ try :
53
+ if "deflate" in fmt :
54
+ import zlib
55
+ encoder = zlib .compress
56
+ format = "deflate"
57
+ except :
58
+ pass
59
+ print fmt , format
60
+ return format , encoder (data )
61
+
58
62
59
63
def do_GET (self ):
60
64
#print self.path
@@ -84,13 +88,16 @@ def do_GET(self):
84
88
'server_port' : cls .port ,
85
89
}
86
90
else :
87
- self .sendError ( )
91
+ self .send_error ( 404 )
88
92
return
89
93
90
- self .send_response (200 )
94
+ encoding , data = self .compress (output )
95
+ self .send_response (200 , "OK" )
91
96
self .send_header ('Content-type' , 'text/html' )
97
+ if not encoding is None :
98
+ self .send_header ('Content-Encoding' , encoding )
92
99
self .end_headers ()
93
- self .wfile .write (output )
100
+ self .wfile .write (data )
94
101
elif self .path == "/data/companies" :
95
102
try :
96
103
f = open (ottd_config .config .get ("stats" , "cachefilename" ), 'rb' )
@@ -100,19 +107,28 @@ def do_GET(self):
100
107
obj = pickle .load (f )
101
108
f .close ()
102
109
cls = self .server ._callbackclass
103
- self .send_response (200 )
104
- self .send_header ('Content-type:' , 'application/json' )
105
- self .end_headers ()
106
110
jsonoutput = json .dumps (obj , sort_keys = True , indent = 4 , cls = DataStorageJSONEncoder )
107
- self .wfile .write (jsonoutput )
111
+ encoding , data = self .compress (jsonoutput )
112
+
113
+ self .send_response (200 , "OK" )
114
+ self .send_header ('Content-type' , 'application/json' )
115
+ if not encoding is None :
116
+ self .send_header ('Content-Encoding' , encoding )
117
+ self .send_header ("Content-Length" , len (data ))
118
+ self .end_headers ()
119
+ self .wfile .write (data )
108
120
elif self .path == "/data/clients" :
109
121
cls = self .server ._callbackclass
110
122
111
123
response = json .dumps (cls .playerlist , indent = 4 , sort_keys = True )
112
- self .send_response (200 )
113
- self .send_header ('Content-type:' , 'application/json' )
124
+ encoding , data = self .compress (response )
125
+ self .send_response (200 , "OK" )
126
+ self .send_header ('Content-type' , 'application/json' )
127
+ if not encoding is None :
128
+ self .send_header ('Content-Encoding' , encoding )
129
+ self .send_header ("Content-Length" , len (data ))
114
130
self .end_headers ()
115
- self .wfile .write (response )
131
+ self .wfile .write (data )
116
132
else :
117
133
path = urllib .unquote (self .path )
118
134
if path .find ("?" ) >= 0 :
@@ -124,61 +140,50 @@ def do_GET(self):
124
140
if os .path .isfile (newindex ):
125
141
fn = newindex
126
142
else :
127
- self .sendError ( )
143
+ self .send_error ( 500 , "couldn't find template" )
128
144
return
129
145
130
146
if os .path .exists (fn ):
147
+ f = open (fn , "rb" )
148
+ content = f .read ()
149
+ f .close ()
150
+ encoding , data = self .compress (content )
131
151
self .send_response (200 )
132
152
self .send_header ("Content-type" , content_type (fn ))
133
- self .send_header ("Content-Length" , os .path .getsize (fn ))
153
+ if not encoding is None :
154
+ self .send_header ("Content-Encoding" , encoding )
155
+ self .send_header ("Content-Length" , len (data ))
134
156
self .end_headers ()
135
- f = open (fn , "rb" )
136
- self .wfile .write (f .read ())
137
- f .close ()
157
+ self .wfile .write (data )
138
158
else :
139
- self .sendError ( )
159
+ self .send_error ( 404 )
140
160
return
141
161
142
162
143
163
144
- class myHTTPServer (BaseHTTPServer .HTTPServer ):
145
- def __init__ (self , addr , handlerClass , cls ):
146
- """
147
- constructor
148
- @type cls: SpectatorClient
149
- @param cls: class to get the data from
150
- """
151
- BaseHTTPServer .HTTPServer .__init__ (self , addr , handlerClass )
152
- self ._callbackclass = cls
153
-
154
-
155
- class myWebServer (threading .Thread ):
164
+ class myWebServer (threading .Thread , SocketServer .ThreadingMixIn , BaseHTTPServer .HTTPServer ):
156
165
"""
157
- webserver that display the currently connected clients
166
+ multithreaded webserver class for openttd-python
158
167
"""
159
168
def __init__ (self , cls , port ):
160
169
"""
161
170
constructor
162
171
@type cls: SpectatorClient
163
172
@param cls: class to get the data from
164
- @type port: number
165
- @param port: the port on which to start the webserver
173
+ @type port: int
174
+ @param port: port to run with
166
175
"""
167
- self .cls = cls
168
176
self .port = port
177
+ self ._callbackclass = cls
178
+ BaseHTTPServer .HTTPServer .__init__ (self , ('' , self .port ), MyHandler )
169
179
threading .Thread .__init__ (self )
170
-
171
180
def run (self ):
172
181
"""
173
182
thread entry point for the webserver
174
183
"""
175
- LOG .debug ('started httpserver...' )
176
- self .server = myHTTPServer (('' , self .port ), MyHandler , self .cls )
177
- self .server .serve_forever ()
178
-
184
+ self .serve_forever ()
179
185
def stop (self ):
180
186
"""
181
187
this stops the webserver
182
188
"""
183
- self .server .server_close ()
184
-
189
+ self .server_close ()
0 commit comments