add an isso.dispatch module to support multiple sites, #34

legacy/0.5
Martin Zimmermann 11 years ago
parent b21e216b06
commit 6f66960df8

@ -0,0 +1,63 @@
import os
import logging
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse
from werkzeug.exceptions import ImATeapot
from isso import make_app, wsgi
from isso.core import Config
logger = logging.getLogger("isso")
class Dispatcher(object):
"""
A dispatcher to support different websites. Dispatches based on
HTTP-Host. If HTTP-Host is not provided, display an error message.
"""
def __init__(self, *confs):
self.isso = {}
for conf in map(Config.load, confs):
app = make_app(conf)
for origin in conf.getiter("general", "host"):
self.isso[origin.rstrip("/")] = app
def __call__(self, environ, start_response):
if "HTTP_ORIGIN" in environ:
origin = environ["HTTP_ORIGIN"]
elif "HTTP_REFERER" in environ:
rv = urlparse(environ["HTTP_REFERER"])
origin = rv.scheme + "://" + rv.hostname + (":" + str(rv.port) if rv.port else "")
else:
origin = wsgi.host(environ)
try:
# logger.info("dispatch %s", origin)
return self.isso[origin](environ, start_response)
except KeyError:
# logger.info("unable to dispatch %s", origin)
resp = ImATeapot("unable to dispatch %s" % origin)
return resp(environ, start_response)
if "ISSO_SETTINGS" not in os.environ:
logger.fatal('no such environment variable: ISSO_SETTINGS')
else:
confs = os.environ["ISSO_SETTINGS"].split(";")
for path in confs:
if not os.path.isfile(path):
logger.fatal("%s: no such file", path)
break
else:
application = Dispatcher(*confs)

@ -208,6 +208,89 @@ reply-to-self
Do not forget to configure the client.
Multiple Sites
--------------
Isso is designed to serve comments for a single website and therefore stores
comments for a relative URL to support HTTP, HTTPS and even domain transfers
without manual intervention. But you can chain Isso to support multiple
websites on different domains.
The following example uses [gunicorn](http://gunicorn.org/) as WSGI server (you
can use uWSGI as well). It is *not* possible to run the isso executable for
multiple sites.
Let's say you maintain two websites, like foo.example and other.foo:
.. code-block:: bash
$ cat /etc/isso.d/foo.example.cfg
[general]
host = http://foo.example/
dbpath = /var/lib/isso/foo.example.db
$ cat /etc/isso.d/other.foo.cfg
[general]
host = http://other.foo/
dbpath = /var/lib/isso/other.foo.db
$ export ISSO_SETTINGS="/etc/isso.d/foo.example.cfg;/etc/isso.d/other.foo.cfg"
$ gunicorn isso.dispatch -b localhost:8080
Now, there are two options to configure the webserver:
1. using a single host to serve comments for both websites
2. different hosts for both websites
In the former case, Isso dispatches based on the HTTP Referer and (if provided)
HTTP Origin. If you expect users to supress their referer completely, you
should use the second option.
1. Using a single host to serve comments.
.. code-block:: nginx
server {
listen [::]:80;
server_name comments.example;
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}
To verify the setup, run:
.. code-block:: bash
$ curl -vH "Origin: http://foo.example" http://comments.example/
...
$ curl -vH "Origin: http://other.foo" http://comments.example/
...
In case of a 418 (I'm a teapot), the setup is *not* correctly configured.
2. Using different hosts for both websites (no need for a dedicated domain,
you can also proxy Isso on a sub-uri like /isso).
.. code-block:: nginx
server {
listen [::]:80;
server_name comments.foo.example comments.other.foo;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}
No need to verify this setup, here the webserver automatically sets the
proper host.
Appendum
---------

Loading…
Cancel
Save