1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
-
+
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This file is part of the web2py Web Framework
Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
This file is based, althought a rewrite, on MIT code from the Bottle web framework.
"""
import os, sys, optparse
import os, sys, optparse, urllib
path = os.path.dirname(os.path.abspath(__file__))
os.chdir(path)
sys.path = [path]+[p for p in sys.path if not p==path]
import gluon.main
from gluon.fileutils import read_file, write_file
class Servers:
|
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
163
164
165
166
167
168
169
170
|
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
|
import gunicorn.arbiter
gunicorn.arbiter.Arbiter(address, 4, app).run()
@staticmethod
def eventlet(app,address, **options):
from eventlet import wsgi, listen
wsgi.server(listen(address), app)
@staticmethod
def mongrel2(app,address,**options):
import uuid
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
from mongrel2 import handler
conn = handler.Connection(str(uuid.uuid4()),
"tcp://127.0.0.1:9997",
"tcp://127.0.0.1:9996")
mongrel2_handler(app,conn,debug=False)
def run(servername,ip,port,softcron=True,logging=False,profiler=None):
if logging:
application = gluon.main.appfactory(wsgiapp=gluon.main.wsgibase,
logfilename='httpserver.log',
profilerfilename=profiler)
else:
application = gluon.main.wsgibase
if softcron:
from gluon.settings import global_settings
global_settings.web2py_crontype = 'soft'
getattr(Servers,servername)(application,(ip,int(port)))
def mongrel2_handler(application,conn,debug=False):
"""
Based on :
https://github.com/berry/Mongrel2-WSGI-Handler/blob/master/wsgi-handler.py
WSGI handler based on the Python wsgiref SimpleHandler.
A WSGI application should return a iterable op StringTypes.
Any encoding must be handled by the WSGI application itself.
"""
from wsgiref.handlers import SimpleHandler
try:
import cStringIO as StringIO
except:
import StringIO
# TODO - this wsgi handler executes the application and renders a page
# in memory completely before returning it as a response to the client.
# Thus, it does not "stream" the result back to the client. It should be
# possible though. The SimpleHandler accepts file-like stream objects. So,
# it should be just a matter of connecting 0MQ requests/response streams to
# the SimpleHandler requests and response streams. However, the Python API
# for Mongrel2 doesn't seem to support file-like stream objects for requests
# and responses. Unless I have missed something.
while True:
if debug: print "WAITING FOR REQUEST"
# receive a request
req = conn.recv()
if debug: print "REQUEST BODY: %r\n" % req.body
if req.is_disconnect():
if debug: print "DISCONNECT"
continue #effectively ignore the disconnect from the client
# Set a couple of environment attributes a.k.a. header attributes
# that are a must according to PEP 333
environ = req.headers
environ['SERVER_PROTOCOL'] = 'HTTP/1.1' # SimpleHandler expects a server_protocol, lets assume it is HTTP 1.1
environ['REQUEST_METHOD'] = environ['METHOD']
if ':' in environ['Host']:
environ['SERVER_NAME'] = environ['Host'].split(':')[0]
environ['SERVER_PORT'] = environ['Host'].split(':')[1]
else:
environ['SERVER_NAME'] = environ['Host']
environ['SERVER_PORT'] = ''
environ['SCRIPT_NAME'] = '' # empty for now
environ['PATH_INFO'] = urllib.unquote(environ['PATH'])
if '?' in environ['URI']:
environ['QUERY_STRING'] = environ['URI'].split('?')[1]
else:
environ['QUERY_STRING'] = ''
if environ.has_key('Content-Length'):
environ['CONTENT_LENGTH'] = environ['Content-Length'] # necessary for POST to work with Django
environ['wsgi.input'] = req.body
if debug: print "ENVIRON: %r\n" % environ
# SimpleHandler needs file-like stream objects for
# requests, errors and reponses
reqIO = StringIO.StringIO(req.body)
errIO = StringIO.StringIO()
respIO = StringIO.StringIO()
# execute the application
handler = SimpleHandler(reqIO, respIO, errIO, environ, multithread = False, multiprocess = False)
handler.run(application)
# Get the response and filter out the response (=data) itself,
# the response headers,
# the response status code and the response status description
response = respIO.getvalue()
response = response.split("\r\n")
data = response[-1]
headers = dict([r.split(": ") for r in response[1:-2]])
code = response[0][9:12]
status = response[0][13:]
# strip BOM's from response data
# Especially the WSGI handler from Django seems to generate them (2 actually, huh?)
# a BOM isn't really necessary and cause HTML parsing errors in Chrome and Safari
# See also: http://www.xs4all.nl/~mechiel/projects/bomstrip/
# Although I still find this a ugly hack, it does work.
data = data.replace('\xef\xbb\xbf', '')
# Get the generated errors
errors = errIO.getvalue()
# return the response
if debug: print "RESPONSE: %r\n" % response
if errors:
if debug: print "ERRORS: %r" % errors
data = "%s\r\n\r\n%s" % (data, errors)
conn.reply_http(req, data, code = code, status = status, headers = headers)
def main():
usage = "python anyserver.py -s tornado -i 127.0.0.1 -p 8000 -l -P"
try:
version = read_file('VERSION')
except IOError:
version = ''
parser = optparse.OptionParser(usage, None, optparse.Option, version)
parser.add_option('-l',
'--logging',
action='store_true',
default=False,
dest='logging',
help='log into httpserver.log')
parser.add_option('-P',
'--profiler',
'--profiler',
default=False,
dest='profiler',
help='profiler filename')
servers = ', '.join(x for x in dir(Servers) if not x[0]=='_')
parser.add_option('-s',
'--server',
default='rocket',
|
184
185
186
187
188
189
190
191
192
193
|
289
290
291
292
293
294
295
296
297
298
299
300
|
+
+
|
'--workers',
default='',
dest='workers',
help='number of workers number')
(options, args) = parser.parse_args()
print 'starting %s on %s:%s...' % (options.server,options.ip,options.port)
run(options.server,options.ip,options.port,logging=options.logging,profiler=options.profiler)
if __name__=='__main__':
main()
|