mirror of
https://github.com/Kozea/Radicale.git
synced 2025-08-07 18:30:54 +00:00
Move WSGI server to server.py
This commit is contained in:
parent
6f15cddfbc
commit
3d77238a4b
3 changed files with 301 additions and 278 deletions
|
@ -17,22 +17,16 @@
|
|||
"""
|
||||
Radicale executable module.
|
||||
|
||||
This module can be executed from a command line with ``$python -m radicale`` or
|
||||
from a python programme with ``radicale.__main__.run()``.
|
||||
This module can be executed from a command line with ``$python -m radicale``.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import select
|
||||
import signal
|
||||
import socket
|
||||
import ssl
|
||||
from wsgiref.simple_server import make_server
|
||||
|
||||
from radicale import (VERSION, Application, RequestHandler, ThreadedHTTPServer,
|
||||
ThreadedHTTPSServer, config, log, storage)
|
||||
from radicale import VERSION, config, log, storage
|
||||
from radicale.log import logger
|
||||
from radicale.server import serve
|
||||
|
||||
|
||||
def run():
|
||||
|
@ -133,107 +127,5 @@ def run():
|
|||
exit(1)
|
||||
|
||||
|
||||
def serve(configuration):
|
||||
"""Serve radicale from configuration."""
|
||||
logger.info("Starting Radicale")
|
||||
|
||||
# Create collection servers
|
||||
servers = {}
|
||||
if configuration.getboolean("server", "ssl"):
|
||||
server_class = ThreadedHTTPSServer
|
||||
server_class.certificate = configuration.get("server", "certificate")
|
||||
server_class.key = configuration.get("server", "key")
|
||||
server_class.certificate_authority = configuration.get(
|
||||
"server", "certificate_authority")
|
||||
server_class.ciphers = configuration.get("server", "ciphers")
|
||||
server_class.protocol = getattr(
|
||||
ssl, configuration.get("server", "protocol"), ssl.PROTOCOL_SSLv23)
|
||||
# Test if the SSL files can be read
|
||||
for name in ["certificate", "key"] + (
|
||||
["certificate_authority"]
|
||||
if server_class.certificate_authority else []):
|
||||
filename = getattr(server_class, name)
|
||||
try:
|
||||
open(filename, "r").close()
|
||||
except OSError as e:
|
||||
raise RuntimeError("Failed to read SSL %s %r: %s" %
|
||||
(name, filename, e)) from e
|
||||
else:
|
||||
server_class = ThreadedHTTPServer
|
||||
server_class.client_timeout = configuration.getint("server", "timeout")
|
||||
server_class.max_connections = configuration.getint(
|
||||
"server", "max_connections")
|
||||
|
||||
if not configuration.getboolean("server", "dns_lookup"):
|
||||
RequestHandler.address_string = lambda self: self.client_address[0]
|
||||
|
||||
shutdown_program = False
|
||||
|
||||
for host in configuration.get("server", "hosts").split(","):
|
||||
try:
|
||||
address, port = host.strip().rsplit(":", 1)
|
||||
address, port = address.strip("[] "), int(port)
|
||||
except ValueError as e:
|
||||
raise RuntimeError(
|
||||
"Failed to parse address %r: %s" % (host, e)) from e
|
||||
application = Application(configuration)
|
||||
try:
|
||||
server = make_server(
|
||||
address, port, application, server_class, RequestHandler)
|
||||
except OSError as e:
|
||||
raise RuntimeError(
|
||||
"Failed to start server %r: %s" % (host, e)) from e
|
||||
servers[server.socket] = server
|
||||
logger.info("Listening to %r on port %d%s",
|
||||
server.server_name, server.server_port, " using SSL"
|
||||
if configuration.getboolean("server", "ssl") else "")
|
||||
|
||||
# Create a socket pair to notify the select syscall of program shutdown
|
||||
# This is not available in python < 3.5 on Windows
|
||||
if hasattr(socket, "socketpair"):
|
||||
shutdown_program_socket_in, shutdown_program_socket_out = (
|
||||
socket.socketpair())
|
||||
else:
|
||||
shutdown_program_socket_in, shutdown_program_socket_out = None, None
|
||||
|
||||
# SIGTERM and SIGINT (aka KeyboardInterrupt) should just mark this for
|
||||
# shutdown
|
||||
def shutdown(*args):
|
||||
nonlocal shutdown_program
|
||||
if shutdown_program:
|
||||
# Ignore following signals
|
||||
return
|
||||
logger.info("Stopping Radicale")
|
||||
shutdown_program = True
|
||||
if shutdown_program_socket_in:
|
||||
shutdown_program_socket_in.sendall(b"goodbye")
|
||||
signal.signal(signal.SIGTERM, shutdown)
|
||||
signal.signal(signal.SIGINT, shutdown)
|
||||
|
||||
# Main loop: wait for requests on any of the servers or program shutdown
|
||||
sockets = list(servers.keys())
|
||||
if shutdown_program_socket_out:
|
||||
# Use socket pair to get notified of program shutdown
|
||||
sockets.append(shutdown_program_socket_out)
|
||||
select_timeout = None
|
||||
if not shutdown_program_socket_out or os.name == "nt":
|
||||
# Fallback to busy waiting. (select.select blocks SIGINT on Windows.)
|
||||
select_timeout = 1.0
|
||||
logger.info("Radicale server ready")
|
||||
while not shutdown_program:
|
||||
try:
|
||||
rlist, _, xlist = select.select(
|
||||
sockets, [], sockets, select_timeout)
|
||||
except (KeyboardInterrupt, select.error):
|
||||
# SIGINT is handled by signal handler above
|
||||
rlist, xlist = [], []
|
||||
if xlist:
|
||||
raise RuntimeError("unhandled socket error")
|
||||
if rlist:
|
||||
server = servers.get(rlist[0])
|
||||
if server:
|
||||
server.handle_request()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue