108 lines
3.6 KiB
Python
108 lines
3.6 KiB
Python
# w.c.s. - web application for online forms
|
|
# Copyright (C) 2005-2010 Entr'ouvert
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import sys
|
|
import os
|
|
import signal
|
|
|
|
from scgi import scgi_server
|
|
|
|
import quixote.server.scgi_server
|
|
|
|
import cron
|
|
import quixote.server.simple_server as simple_server
|
|
|
|
|
|
class QommonHandler(quixote.server.scgi_server.QuixoteHandler):
|
|
connection_limit = -1
|
|
number_of_connection_handled = 0
|
|
|
|
def handle_connection(self, conn):
|
|
self.number_of_connection_handled = self.number_of_connection_handled + 1
|
|
quixote.server.scgi_server.QuixoteHandler.handle_connection(self, conn)
|
|
# input, output and conn are closed, long running jobs could be done
|
|
# here.
|
|
self.publisher.response.process_after_jobs()
|
|
if self.number_of_connection_handled == self.connection_limit:
|
|
raise SystemExit
|
|
|
|
|
|
class SCGIServer(scgi_server.SCGIServer):
|
|
def reap_children(self):
|
|
while self.children:
|
|
(pid, status) = os.waitpid(-1, os.WNOHANG)
|
|
if pid <= 0:
|
|
break
|
|
try:
|
|
os.close(self.children[pid])
|
|
except KeyError:
|
|
print >> sys.stderr, 'Closing connection to unknown pid:', pid
|
|
continue
|
|
del self.children[pid]
|
|
|
|
def restart():
|
|
'''Tell the server process to stop all worker process and start again'''
|
|
ppid = os.getppid()
|
|
os.kill(ppid, signal.SIGHUP)
|
|
|
|
def run(create_publisher, host='localhost', port=3000, script_name=None,
|
|
max_children = 5, spawn_cron = False, handler_connection_limit = -1):
|
|
|
|
if spawn_cron:
|
|
cron.spawn_cron(create_publisher)
|
|
|
|
def create_handler(parent_fd):
|
|
h = QommonHandler(parent_fd, create_publisher, script_name)
|
|
h.connection_limit = handler_connection_limit
|
|
return h
|
|
|
|
s = SCGIServer(create_handler, host=host, port=port,
|
|
max_children=max_children)
|
|
s.serve()
|
|
|
|
|
|
class QommonHTTPRequestHandler(simple_server.HTTPRequestHandler):
|
|
def process(self, env, include_body=True):
|
|
simple_server.HTTPRequestHandler.process(self, env, include_body=include_body)
|
|
self.publisher.response.process_after_jobs()
|
|
|
|
|
|
def http_run(create_publisher, spawn_cron = False,
|
|
handler_connection_limit = -1, host = '', port = 80, https = False):
|
|
"""Runs a simple, single threaded, synchronous HTTP server that
|
|
publishes a Quixote application.
|
|
"""
|
|
|
|
if spawn_cron:
|
|
cron.spawn_cron(create_publisher)
|
|
|
|
if https:
|
|
QommonHTTPRequestHandler.required_cgi_environment['HTTPS'] = 'on'
|
|
|
|
httpd = simple_server.HTTPServer((host, port), QommonHTTPRequestHandler)
|
|
def handle_error(request, client_address):
|
|
simple_server.HTTPServer.handle_error(httpd, request, client_address)
|
|
if sys.exc_info()[0] is SystemExit:
|
|
raise sys.exc_info()[0]
|
|
httpd.handle_error = handle_error
|
|
QommonHTTPRequestHandler.publisher = create_publisher()
|
|
try:
|
|
httpd.serve_forever()
|
|
finally:
|
|
httpd.server_close()
|
|
|
|
|