wcs/wcs/qommon/scgi_server.py

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()