diff --git a/develop/httpserver.rst b/develop/httpserver.rst new file mode 100644 index 0000000..ff51219 --- /dev/null +++ b/develop/httpserver.rst @@ -0,0 +1,169 @@ +******************************************** +Using Limnoria's HTTP server in your plugins +******************************************** + +Introduction +============ + +Having a HTTP server in an IRC may be baffling, because it seems to be useless. +Yes, you are right, it is useless in most of the cases. But it may be cool. + +Some plugins (WebStats, Github, and UfrPaste are the only one, as far as I +know) have their own embedded HTTP server. Unfortunately, a HTTP need a port, +and consumes a few resources (CPU/memory). So, if you want many of these plugins, +it becomes embarrassing. +Last pro for this server: a plugin that use this HTTP server is really tinier, +as shown in `this commit`_ (note that the path of the httpserver is no more +*supybot.utils.httpserver* but *supybot.httpserver*) + +.. _this commit: https://github.com/ProgVal/Supybot-plugins/commit/220146ea + +Anyway, if you are on this page, this is probably because you want to use this +HTTP server, so I don't need to convince you. +Before reading further, be sure you have a Limnoria (or any Supybot fork that +merged this HTTP server). + +Using the HTTP server in a plugin +================================= + +Let's try to make a basic dictionary about Supybot! We'll call it Supystory. + +We want to get plain text information about Supybot, Gribble, and Limnoria when +accessing http://localhost:8080/supystory/supybot, +http://localhost:8080/supystory/gribble, and +http://localhost:8080/supystory/limnoria, and an HTML error page if the page +is not found + +Importing the HTTP server +------------------------- + +On only have to add this line:: + + import supybot.httpserver as httpserver. + + +Creating a callback +------------------- + +If you are familiar with `BaseHTTPServer`, you will recognize the design, +except you don't need to subclass BaseHTTPServer, because I already did +it in *supybot.httpserver*. + +Now, you have to subclass `httpserver.SupyHTTPServerCallback`. A callback is +pretty much like an handler, but this is not an handler, because a callback is +called by the handler. + +Here is how to do it:: + + class SupystoryServerCallback(httpserver.SupyHTTPServerCallback): + name = 'WebStats' + +Now, you have to register the callback, because the HTTP server does not know +what subdirectory it should assign to your callback. Do it with adding a +*__init__* to your plugin (read Supybot's docs about it, for more +informations):: + + class Supystory(callbacks.Plugin): + def __init__(self, irc): + # Some stuff needed by Supybot + self.__parent = super(Supystory, self) + callbacks.Plugin.__init__(self, irc) + + # registering the callback + callback = SupystoryServerCallback() # create an instance of the callback + httpserver.hook('webstats', callback) # register the callback at `/webstats` + +By the way, don't forget to unhook your callback when unloading your plugin, +unless what it will be impossible to reload the plugin! Append this code to +the following:: + + def die(self): + # unregister the callback + httpserver.unhook('supystory') # unregister the callback hooked at /supystory + + # Stuff for Supybot + self.__parent.die() + +Now, you can load your plugin, and you'll see on the server a beautiful link +to `/supystory` called `Supystory`. + +Overriding the default error message +------------------------------------ + +But our plugin does not do anything for the moment. If click the link, you'll +get this message:: + + This is a default response of the Supybot HTTP server. If you see this + message, it probably means you are developping a plugin, and you have + neither overriden this message or defined an handler for this query. + +That mean your browser sent a GET request, but you didn't teach your plugin how +to handle it. First, we'll change this error message. +Here is a new code for your callback:: + + class SupystoryServerCallback(httpserver.SupyHTTPServerCallback): + name = 'Supystory' + defaultResponse = """ + This plugin handles only GET request, please don't use other requests.""" + +Now, you'll get your customized message. But your plugin still doesn't work. +You need to implement the GET request. + +Implementing the GET request +---------------------------- + +As I said before, callbacks are pretty much like handlers. In order to handle +GET requests, you have to implement a method called... `doGet` (if you used +BaseHTTPServer, you will notice this is not do_GET, because doGet is more +homogeneous with Supybot naming style: `doPrivmsg`, `doPing`, and so on). + +You will get the handler and the URI as arguments. The handler is a +`BaseHTTPRequestHandler`_, and the URI is a string. + +.. _BaseHTTPRequestHandler: http://docs.python.org/library/basehttpserver.html#BaseHTTPServer.BaseHTTPRequestHandler + +Here is the code of the callback... pretty much simple, as ever:: + + class SupystoryServerCallback(httpserver.SupyHTTPServerCallback): + name = 'Supystory' + defaultResponse = """ + This plugin handles only GET request, please don't use other requests.""" + + def doGet(self, handler, path): + if path == '/supybot': + response = 'Supybot is the best IRC bot ever.' + elif path == '/gribble': + response = 'Thanks to Gribble, we have many bug fixes and SQLite 3 support' + elif path == '/limnoria': + response = 'Because of Limnoria, you need to internationalize your plugins and read this f*cking do.' + else: + response = None + if response is None: + handler.send_response(404) # Not found, as described by the HTTP protocol + handler.send_header('Content-type', 'text/html') # This is the MIME for HTML data + handler.end_headers() # We won't send more headers + handler.wfile.write(""" + +
++ The document could not be found. Try one of this links: + Supybot + Gribble + Limnoria +
+ + """) + else: + handler.send_response(404) # Not found, as described by the HTTP protocol + handler.send_header('Content-type', 'text/plain') # This is the MIME for plain text + handler.end_headers() # We won't send more headers + handler.wfile.write(response) + +That's all ! + +You may not understand everything (I know I don't speak English very well); +come on #limnoria at Freenode and ask for help of make suggestions! diff --git a/develop/plugins.rst b/develop/plugins.rst index f8f824e..5849e6c 100644 --- a/develop/plugins.rst +++ b/develop/plugins.rst @@ -4,14 +4,22 @@ Developping plugins for Limnoria ################################ +Doc provided with Supybot: + .. toctree:: :maxdepth: 0 - import/PLUGIN_TUTORIAL.rst - import/USING_WRAP.rst - import/STYLE.rst - import/CONFIGURATION.rst - import/CAPABILITIES.rst - import/USING_UTILS.rst - import/ADVANCED_PLUGIN_CONFIG.rst - import/ADVANCED_PLUGIN_TESTING.rst + ../import/PLUGIN_TUTORIAL.rst + ../import/USING_WRAP.rst + ../import/STYLE.rst + ../import/CONFIGURATION.rst + ../import/USING_UTILS.rst + ../import/ADVANCED_PLUGIN_CONFIG.rst + ../import/ADVANCED_PLUGIN_TESTING.rst + +Other docs: + +.. toctree:: + :maxdepth: 0 + + httpserver.rst diff --git a/develop/import/ADVANCED_PLUGIN_CONFIG.rst b/import/ADVANCED_PLUGIN_CONFIG.rst similarity index 100% rename from develop/import/ADVANCED_PLUGIN_CONFIG.rst rename to import/ADVANCED_PLUGIN_CONFIG.rst diff --git a/develop/import/ADVANCED_PLUGIN_TESTING.rst b/import/ADVANCED_PLUGIN_TESTING.rst similarity index 100% rename from develop/import/ADVANCED_PLUGIN_TESTING.rst rename to import/ADVANCED_PLUGIN_TESTING.rst diff --git a/develop/import/CAPABILITIES.rst b/import/CAPABILITIES.rst similarity index 100% rename from develop/import/CAPABILITIES.rst rename to import/CAPABILITIES.rst diff --git a/develop/import/CONFIGURATION.rst b/import/CONFIGURATION.rst similarity index 100% rename from develop/import/CONFIGURATION.rst rename to import/CONFIGURATION.rst diff --git a/develop/import/FAQ.rst b/import/FAQ.rst similarity index 100% rename from develop/import/FAQ.rst rename to import/FAQ.rst diff --git a/develop/import/GETTING_STARTED.rst b/import/GETTING_STARTED.rst similarity index 100% rename from develop/import/GETTING_STARTED.rst rename to import/GETTING_STARTED.rst diff --git a/develop/import/PLUGIN_TUTORIAL.rst b/import/PLUGIN_TUTORIAL.rst similarity index 100% rename from develop/import/PLUGIN_TUTORIAL.rst rename to import/PLUGIN_TUTORIAL.rst diff --git a/develop/import/README b/import/README similarity index 100% rename from develop/import/README rename to import/README diff --git a/develop/import/STYLE.rst b/import/STYLE.rst similarity index 100% rename from develop/import/STYLE.rst rename to import/STYLE.rst diff --git a/develop/import/USING_UTILS.rst b/import/USING_UTILS.rst similarity index 100% rename from develop/import/USING_UTILS.rst rename to import/USING_UTILS.rst diff --git a/develop/import/USING_WRAP.rst b/import/USING_WRAP.rst similarity index 100% rename from develop/import/USING_WRAP.rst rename to import/USING_WRAP.rst diff --git a/use/httpserver.rst b/use/httpserver.rst new file mode 100644 index 0000000..1135ffc --- /dev/null +++ b/use/httpserver.rst @@ -0,0 +1,40 @@ +********************* +Using the HTTP server +********************* + +Configuration +============= + +The HTTP comes with a couple of additional variables: + +* :ref:`supybot.servers.http.host`: The host the bot will bind. In most of + the cases, you will use 0.0.0.0 (everything) or 127.0.0.1 (restricted to + local connections). Defaults to 0.0.0.0 +* :ref:`supybot.servers.http.port`: The port the bot will bind. May not work + if the number is too low. Defaults to 8080 (alternative HTTP port). +* :ref:`supybot.servers.http.keepAlive`: Determines weather the HTTP server + will run even if has nothing to serve. Defaults to False, because the HTTP + might require to change the port, if it is already taken. + +Using the server +================ + +At the root of the server, you will find a list of the plugins that have a Web +interface, and a link to them. Each plugin has its own subdirectory(ies). + +You may also want to have Apache behind Supybot's HTTP server, if you want to +use subdomains. Here is an example of configuration (I didn't test it with the +rewrite, please notify me whether it works or not): + +.. code-block:: apache + +