mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-01-11 20:52:42 +01:00
httpserver: Add support for multiple hosts and IPv6. Closes GH-387.
This commit is contained in:
parent
247ed460b0
commit
784b8c37f8
@ -1085,8 +1085,12 @@ class IP(registry.String):
|
|||||||
else:
|
else:
|
||||||
registry.String.setValue(self, v)
|
registry.String.setValue(self, v)
|
||||||
|
|
||||||
registerGlobalValue(supybot.servers.http, 'host',
|
registerGlobalValue(supybot.servers.http, 'hosts4',
|
||||||
IP('0.0.0.0', _("Determines what host the HTTP server will bind.")))
|
IP('0.0.0.0', _("""Space-separated list of IPv4 hosts the HTTP server
|
||||||
|
will bind.""")))
|
||||||
|
registerGlobalValue(supybot.servers.http, 'hosts6',
|
||||||
|
IP('', _("""Space-separated list of IPv6 hosts the HTTP server will
|
||||||
|
bind.""")))
|
||||||
registerGlobalValue(supybot.servers.http, 'port',
|
registerGlobalValue(supybot.servers.http, 'port',
|
||||||
registry.Integer(8080, _("""Determines what port the HTTP server will
|
registry.Integer(8080, _("""Determines what port the HTTP server will
|
||||||
bind.""")))
|
bind.""")))
|
||||||
|
@ -33,6 +33,7 @@ An embedded and centralized HTTP server for Supybot's plugins.
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import cgi
|
import cgi
|
||||||
|
import socket
|
||||||
from threading import Event, Thread
|
from threading import Event, Thread
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from SocketServer import ThreadingMixIn
|
from SocketServer import ThreadingMixIn
|
||||||
@ -54,8 +55,18 @@ class RequestNotHandled(Exception):
|
|||||||
class RealSupyHTTPServer(HTTPServer):
|
class RealSupyHTTPServer(HTTPServer):
|
||||||
# TODO: make this configurable
|
# TODO: make this configurable
|
||||||
timeout = 0.5
|
timeout = 0.5
|
||||||
callbacks = {}
|
|
||||||
running = False
|
running = False
|
||||||
|
|
||||||
|
def __init__(self, address, protocol, callback):
|
||||||
|
if protocol == 4:
|
||||||
|
self.address_family = socket.AF_INET
|
||||||
|
elif protocol == 6:
|
||||||
|
self.address_family = socket.AF_INET6
|
||||||
|
else:
|
||||||
|
raise AssertionError(protocol)
|
||||||
|
HTTPServer.__init__(self, address, callback)
|
||||||
|
self.callbacks = {}
|
||||||
|
|
||||||
def hook(self, subdir, callback):
|
def hook(self, subdir, callback):
|
||||||
if subdir in self.callbacks:
|
if subdir in self.callbacks:
|
||||||
log.warning(('The HTTP subdirectory `%s` was already hooked but '
|
log.warning(('The HTTP subdirectory `%s` was already hooked but '
|
||||||
@ -68,6 +79,9 @@ class RealSupyHTTPServer(HTTPServer):
|
|||||||
callback.doUnhook(self)
|
callback.doUnhook(self)
|
||||||
return callback
|
return callback
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'server at %s %i' % self.server_address[0:2]
|
||||||
|
|
||||||
class TestSupyHTTPServer(RealSupyHTTPServer):
|
class TestSupyHTTPServer(RealSupyHTTPServer):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
@ -241,39 +255,50 @@ class Favicon(SupyHTTPServerCallback):
|
|||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(response)
|
self.wfile.write(response)
|
||||||
|
|
||||||
httpServer = None
|
http_servers = None
|
||||||
|
|
||||||
def startServer():
|
def startServer():
|
||||||
"""Starts the HTTP server. Shouldn't be called from other modules.
|
"""Starts the HTTP server. Shouldn't be called from other modules.
|
||||||
The callback should be an instance of a child of SupyHTTPServerCallback."""
|
The callback should be an instance of a child of SupyHTTPServerCallback."""
|
||||||
global httpServer
|
global http_servers
|
||||||
log.info('Starting HTTP server.')
|
addresses4 = [(4, (x, configGroup.port()))
|
||||||
address = (configGroup.host(), configGroup.port())
|
for x in configGroup.hosts4().split(' ') if x != '']
|
||||||
httpServer = SupyHTTPServer(address, SupyHTTPRequestHandler)
|
addresses6 = [(6, (x, configGroup.port()))
|
||||||
Thread(target=httpServer.serve_forever, name='HTTP Server').start()
|
for x in configGroup.hosts6().split(' ') if x != '']
|
||||||
|
http_servers = []
|
||||||
|
for protocol, address in (addresses4 + addresses6):
|
||||||
|
server = SupyHTTPServer(address, protocol, SupyHTTPRequestHandler)
|
||||||
|
Thread(target=server.serve_forever, name='HTTP Server').start()
|
||||||
|
http_servers.append(server)
|
||||||
|
log.info('Starting HTTP server: %s' % str(server))
|
||||||
|
|
||||||
def stopServer():
|
def stopServer():
|
||||||
"""Stops the HTTP server. Should be run only from this module or from
|
"""Stops the HTTP server. Should be run only from this module or from
|
||||||
when the bot is dying (ie. from supybot.world)"""
|
when the bot is dying (ie. from supybot.world)"""
|
||||||
global httpServer
|
global http_servers
|
||||||
if httpServer is not None:
|
if http_servers is not None:
|
||||||
log.info('Stopping HTTP server.')
|
for server in http_servers:
|
||||||
httpServer.shutdown()
|
log.info('Stopping HTTP server: %s' % str(server))
|
||||||
httpServer = None
|
server.shutdown()
|
||||||
|
server = None
|
||||||
|
|
||||||
if configGroup.keepAlive():
|
if configGroup.keepAlive():
|
||||||
startServer()
|
startServer()
|
||||||
|
|
||||||
def hook(subdir, callback):
|
def hook(subdir, callback):
|
||||||
"""Sets a callback for a given subdir."""
|
"""Sets a callback for a given subdir."""
|
||||||
if httpServer is None:
|
if http_servers is None:
|
||||||
startServer()
|
startServer()
|
||||||
httpServer.hook(subdir, callback)
|
assert isinstance(http_servers, list)
|
||||||
|
for server in http_servers:
|
||||||
|
server.hook(subdir, callback)
|
||||||
|
|
||||||
def unhook(subdir):
|
def unhook(subdir):
|
||||||
"""Unsets the callback assigned to the given subdir, and return it."""
|
"""Unsets the callback assigned to the given subdir, and return it."""
|
||||||
global httpServer
|
global http_servers
|
||||||
assert httpServer is not None
|
assert isinstance(http_servers, list)
|
||||||
callback = httpServer.unhook(subdir)
|
for server in http_servers:
|
||||||
if len(httpServer.callbacks) <= 0 and not configGroup.keepAlive():
|
callback = server.unhook(subdir)
|
||||||
stopServer()
|
if len(server.callbacks) <= 0 and not configGroup.keepAlive():
|
||||||
|
server.shutdown()
|
||||||
|
http_servers.remove(server)
|
||||||
|
Loading…
Reference in New Issue
Block a user