diff --git a/README.rst b/README.rst
index 0459d54634..f40492b8a0 100644
--- a/README.rst
+++ b/README.rst
@@ -51,6 +51,7 @@ To get up and running:
- To run your own **private** homeserver on localhost:8008, generate a basic
config file: ``./synctl start`` will give you instructions on how to do this.
+ For this purpose, you can use 'localhost' or your hostname as a server name.
Once you've done so, running ``./synctl start`` again will start your private
home sserver. You will find a webclient running at http://localhost:8008.
Please use a recent Chrome or Firefox for now (or Safari if you don't need
@@ -253,7 +254,7 @@ http://localhost:8080. Simply run::
Running The Demo Web Client
===========================
-The homeserver runs a web client by default at http://localhost:8080.
+The homeserver runs a web client by default at https://localhost:8448/.
If this is the first time you have used the client from that browser (it uses
HTML5 local storage to remember its config), you will need to log in to your
@@ -273,7 +274,7 @@ account. Your name will take the form of::
Specify your desired localpart in the topmost box of the "Register for an
account" form, and click the "Register" button. Hostnames can contain ports if
-required due to lack of SRV records (e.g. @matthew:localhost:8080 on an
+required due to lack of SRV records (e.g. @matthew:localhost:8448 on an
internal synapse sandbox running on localhost)
diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py
index 2f1b954902..61d574a00f 100755
--- a/synapse/app/homeserver.py
+++ b/synapse/app/homeserver.py
@@ -25,7 +25,7 @@ from twisted.web.static import File
from twisted.web.server import Site
from synapse.http.server import JsonResource, RootRedirect
from synapse.http.content_repository import ContentRepoResource
-from synapse.http.client import TwistedHttpClient
+from synapse.http.client import MatrixHttpClient
from synapse.api.urls import (
CLIENT_PREFIX, FEDERATION_PREFIX, WEB_CLIENT_PREFIX, CONTENT_REPO_PREFIX
)
@@ -47,7 +47,7 @@ logger = logging.getLogger(__name__)
class SynapseHomeServer(HomeServer):
def build_http_client(self):
- return TwistedHttpClient(self)
+ return MatrixHttpClient(self)
def build_resource_for_client(self):
return JsonResource()
diff --git a/synapse/config/_base.py b/synapse/config/_base.py
index 809f9c922b..b3aeff327c 100644
--- a/synapse/config/_base.py
+++ b/synapse/config/_base.py
@@ -123,7 +123,8 @@ class Config(object):
# style mode markers into the file, to hint to people that
# this is a YAML file.
yaml.dump(config, config_file, default_flow_style=False)
- print "A config file has been generated in %s (your server name is '%s'). Please review this file and customise it to your needs." % (config_args.config_path, config['server_name'])
+ print "A config file has been generated in %s for server name '%s') with corresponding SSL keys and self-signed certificates. Please review this file and customise it to your needs." % (config_args.config_path, config['server_name'])
+ print "If this server name is incorrect, you will need to regenerate the SSL certificates"
sys.exit(0)
return cls(args)
diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py
index 96b82f00cb..5f96f79998 100644
--- a/synapse/federation/replication.py
+++ b/synapse/federation/replication.py
@@ -159,7 +159,8 @@ class ReplicationLayer(object):
return defer.succeed(None)
@log_function
- def make_query(self, destination, query_type, args):
+ def make_query(self, destination, query_type, args,
+ retry_on_dns_fail=True):
"""Sends a federation Query to a remote homeserver of the given type
and arguments.
@@ -174,7 +175,9 @@ class ReplicationLayer(object):
a Deferred which will eventually yield a JSON object from the
response
"""
- return self.transport_layer.make_query(destination, query_type, args)
+ return self.transport_layer.make_query(
+ destination, query_type, args, retry_on_dns_fail=retry_on_dns_fail
+ )
@defer.inlineCallbacks
@log_function
diff --git a/synapse/federation/transport.py b/synapse/federation/transport.py
index afc777ec9e..93296af204 100644
--- a/synapse/federation/transport.py
+++ b/synapse/federation/transport.py
@@ -193,13 +193,14 @@ class TransportLayer(object):
@defer.inlineCallbacks
@log_function
- def make_query(self, destination, query_type, args):
+ def make_query(self, destination, query_type, args, retry_on_dns_fail):
path = PREFIX + "/query/%s" % query_type
response = yield self.client.get_json(
destination=destination,
path=path,
- args=args
+ args=args,
+ retry_on_dns_fail=retry_on_dns_fail,
)
defer.returnValue(response)
diff --git a/synapse/handlers/directory.py b/synapse/handlers/directory.py
index 84c3a1d56f..a56830d520 100644
--- a/synapse/handlers/directory.py
+++ b/synapse/handlers/directory.py
@@ -18,7 +18,6 @@ from twisted.internet import defer
from ._base import BaseHandler
from synapse.api.errors import SynapseError
-from synapse.http.client import HttpClient
from synapse.api.events.room import RoomAliasesEvent
import logging
@@ -98,8 +97,8 @@ class DirectoryHandler(BaseHandler):
query_type="directory",
args={
"room_alias": room_alias.to_string(),
- HttpClient.RETRY_DNS_LOOKUP_FAILURES: False
- }
+ },
+ retry_on_dns_fail=False,
)
if result and "room_id" in result and "servers" in result:
diff --git a/synapse/handlers/login.py b/synapse/handlers/login.py
index 80ffdd2726..3f152e18f0 100644
--- a/synapse/handlers/login.py
+++ b/synapse/handlers/login.py
@@ -17,7 +17,7 @@ from twisted.internet import defer
from ._base import BaseHandler
from synapse.api.errors import LoginError, Codes
-from synapse.http.client import PlainHttpClient
+from synapse.http.client import IdentityServerHttpClient
from synapse.util.emailutils import EmailException
import synapse.util.emailutils as emailutils
@@ -97,10 +97,10 @@ class LoginHandler(BaseHandler):
@defer.inlineCallbacks
def _query_email(self, email):
- httpCli = PlainHttpClient(self.hs)
+ httpCli = IdentityServerHttpClient(self.hs)
data = yield httpCli.get_json(
'matrix.org:8090', # TODO FIXME This should be configurable.
"/_matrix/identity/api/v1/lookup?medium=email&address=" +
"%s" % urllib.quote(email)
)
- defer.returnValue(data)
\ No newline at end of file
+ defer.returnValue(data)
diff --git a/synapse/handlers/register.py b/synapse/handlers/register.py
index a019d770d4..df562aa762 100644
--- a/synapse/handlers/register.py
+++ b/synapse/handlers/register.py
@@ -22,7 +22,8 @@ from synapse.api.errors import (
)
from ._base import BaseHandler
import synapse.util.stringutils as stringutils
-from synapse.http.client import PlainHttpClient
+from synapse.http.client import IdentityServerHttpClient
+from synapse.http.client import CaptchaServerHttpClient
import base64
import bcrypt
@@ -154,7 +155,9 @@ class RegistrationHandler(BaseHandler):
@defer.inlineCallbacks
def _threepid_from_creds(self, creds):
- httpCli = PlainHttpClient(self.hs)
+ # TODO: get this from the homeserver rather than creating a new one for
+ # each request
+ httpCli = IdentityServerHttpClient(self.hs)
# XXX: make this configurable!
trustedIdServers = ['matrix.org:8090']
if not creds['idServer'] in trustedIdServers:
@@ -173,7 +176,7 @@ class RegistrationHandler(BaseHandler):
@defer.inlineCallbacks
def _bind_threepid(self, creds, mxid):
- httpCli = PlainHttpClient(self.hs)
+ httpCli = IdentityServerHttpClient(self.hs)
data = yield httpCli.post_urlencoded_get_json(
creds['idServer'],
"/_matrix/identity/api/v1/3pid/bind",
@@ -203,7 +206,9 @@ class RegistrationHandler(BaseHandler):
@defer.inlineCallbacks
def _submit_captcha(self, ip_addr, private_key, challenge, response):
- client = PlainHttpClient(self.hs)
+ # TODO: get this from the homeserver rather than creating a new one for
+ # each request
+ client = CaptchaServerHttpClient(self.hs)
data = yield client.post_urlencoded_get_raw(
"www.google.com:80",
"/recaptcha/api/verify",
diff --git a/synapse/http/client.py b/synapse/http/client.py
index 822afeec1d..5c2fbd1f87 100644
--- a/synapse/http/client.py
+++ b/synapse/http/client.py
@@ -36,49 +36,6 @@ import urllib
logger = logging.getLogger(__name__)
-class HttpClient(object):
- """ Interface for talking json over http
- """
- RETRY_DNS_LOOKUP_FAILURES = "__retry_dns"
-
- def put_json(self, destination, path, data):
- """ Sends the specifed json data using PUT
-
- Args:
- destination (str): The remote server to send the HTTP request
- to.
- path (str): The HTTP path.
- data (dict): A dict containing the data that will be used as
- the request body. This will be encoded as JSON.
-
- Returns:
- Deferred: Succeeds when we get a 2xx HTTP response. The result
- will be the decoded JSON body. On a 4xx or 5xx error response a
- CodeMessageException is raised.
- """
- pass
-
- def get_json(self, destination, path, args=None):
- """ Get's some json from the given host homeserver and path
-
- Args:
- destination (str): The remote server to send the HTTP request
- to.
- path (str): The HTTP path.
- args (dict): A dictionary used to create query strings, defaults to
- None.
- **Note**: The value of each key is assumed to be an iterable
- and *not* a string.
-
- Returns:
- Deferred: Succeeds when we get *any* HTTP response.
-
- The result of the deferred is a tuple of `(code, response)`,
- where `response` is a dict representing the decoded JSON body.
- """
- pass
-
-
class MatrixHttpAgent(_AgentBase):
def __init__(self, reactor, pool=None):
@@ -102,12 +59,8 @@ class MatrixHttpAgent(_AgentBase):
parsed_URI.originForm)
-class TwistedHttpClient(HttpClient):
- """ Wrapper around the twisted HTTP client api.
-
- Attributes:
- agent (twisted.web.client.Agent): The twisted Agent used to send the
- requests.
+class BaseHttpClient(object):
+ """Base class for HTTP clients using twisted.
"""
def __init__(self, hs):
@@ -115,101 +68,6 @@ class TwistedHttpClient(HttpClient):
self.hs = hs
@defer.inlineCallbacks
- def put_json(self, destination, path, data, on_send_callback=None):
- if destination in _destination_mappings:
- destination = _destination_mappings[destination]
-
- response = yield self._create_request(
- destination.encode("ascii"),
- "PUT",
- path.encode("ascii"),
- producer=_JsonProducer(data),
- headers_dict={"Content-Type": ["application/json"]},
- on_send_callback=on_send_callback,
- )
-
- logger.debug("Getting resp body")
- body = yield readBody(response)
- logger.debug("Got resp body")
-
- defer.returnValue((response.code, body))
-
- @defer.inlineCallbacks
- def get_json(self, destination, path, args={}):
- if destination in _destination_mappings:
- destination = _destination_mappings[destination]
-
- logger.debug("get_json args: %s", args)
-
- retry_on_dns_fail = True
- if HttpClient.RETRY_DNS_LOOKUP_FAILURES in args:
- # FIXME: This isn't ideal, but the interface exposed in get_json
- # isn't comprehensive enough to give caller's any control over
- # their connection mechanics.
- retry_on_dns_fail = args.pop(HttpClient.RETRY_DNS_LOOKUP_FAILURES)
-
- query_bytes = urllib.urlencode(args, True)
- logger.debug("Query bytes: %s Retry DNS: %s", args, retry_on_dns_fail)
-
- response = yield self._create_request(
- destination.encode("ascii"),
- "GET",
- path.encode("ascii"),
- query_bytes=query_bytes,
- retry_on_dns_fail=retry_on_dns_fail
- )
-
- body = yield readBody(response)
-
- defer.returnValue(json.loads(body))
-
- @defer.inlineCallbacks
- def post_urlencoded_get_json(self, destination, path, args={}):
- if destination in _destination_mappings:
- destination = _destination_mappings[destination]
-
- logger.debug("post_urlencoded_get_json args: %s", args)
- query_bytes = urllib.urlencode(args, True)
-
- response = yield self._create_request(
- destination.encode("ascii"),
- "POST",
- path.encode("ascii"),
- producer=FileBodyProducer(StringIO(urllib.urlencode(args))),
- headers_dict={"Content-Type": ["application/x-www-form-urlencoded"]}
- )
-
- body = yield readBody(response)
-
- defer.returnValue(json.loads(body))
-
- # XXX FIXME : I'm so sorry.
- @defer.inlineCallbacks
- def post_urlencoded_get_raw(self, destination, path, accept_partial=False, args={}):
- if destination in _destination_mappings:
- destination = _destination_mappings[destination]
-
- query_bytes = urllib.urlencode(args, True)
-
- response = yield self._create_request(
- destination.encode("ascii"),
- "POST",
- path.encode("ascii"),
- producer=FileBodyProducer(StringIO(urllib.urlencode(args))),
- headers_dict={"Content-Type": ["application/x-www-form-urlencoded"]}
- )
-
- try:
- body = yield readBody(response)
- defer.returnValue(body)
- except PartialDownloadError as e:
- if accept_partial:
- defer.returnValue(e.response)
- else:
- raise e
-
-
- @defer.inlineCallbacks
def _create_request(self, destination, method, path_bytes, param_bytes=b"",
query_bytes=b"", producer=None, headers_dict={},
retry_on_dns_fail=True, on_send_callback=None):
@@ -232,7 +90,6 @@ class TwistedHttpClient(HttpClient):
retries_left = 5
- # TODO: setup and pass in an ssl_context to enable TLS
endpoint = self._getEndpoint(reactor, destination);
while True:
@@ -283,6 +140,85 @@ class TwistedHttpClient(HttpClient):
defer.returnValue(response)
+
+class MatrixHttpClient(BaseHttpClient):
+ """ Wrapper around the twisted HTTP client api. Implements
+
+ Attributes:
+ agent (twisted.web.client.Agent): The twisted Agent used to send the
+ requests.
+ """
+
+ RETRY_DNS_LOOKUP_FAILURES = "__retry_dns"
+
+ @defer.inlineCallbacks
+ def put_json(self, destination, path, data, on_send_callback=None):
+ """ Sends the specifed json data using PUT
+
+ Args:
+ destination (str): The remote server to send the HTTP request
+ to.
+ path (str): The HTTP path.
+ data (dict): A dict containing the data that will be used as
+ the request body. This will be encoded as JSON.
+
+ Returns:
+ Deferred: Succeeds when we get a 2xx HTTP response. The result
+ will be the decoded JSON body. On a 4xx or 5xx error response a
+ CodeMessageException is raised.
+ """
+ response = yield self._create_request(
+ destination.encode("ascii"),
+ "PUT",
+ path.encode("ascii"),
+ producer=_JsonProducer(data),
+ headers_dict={"Content-Type": ["application/json"]},
+ on_send_callback=on_send_callback,
+ )
+
+ logger.debug("Getting resp body")
+ body = yield readBody(response)
+ logger.debug("Got resp body")
+
+ defer.returnValue((response.code, body))
+
+ @defer.inlineCallbacks
+ def get_json(self, destination, path, args={}, retry_on_dns_fail=True):
+ """ Get's some json from the given host homeserver and path
+
+ Args:
+ destination (str): The remote server to send the HTTP request
+ to.
+ path (str): The HTTP path.
+ args (dict): A dictionary used to create query strings, defaults to
+ None.
+ **Note**: The value of each key is assumed to be an iterable
+ and *not* a string.
+
+ Returns:
+ Deferred: Succeeds when we get *any* HTTP response.
+
+ The result of the deferred is a tuple of `(code, response)`,
+ where `response` is a dict representing the decoded JSON body.
+ """
+ logger.debug("get_json args: %s", args)
+
+ query_bytes = urllib.urlencode(args, True)
+ logger.debug("Query bytes: %s Retry DNS: %s", args, retry_on_dns_fail)
+
+ response = yield self._create_request(
+ destination.encode("ascii"),
+ "GET",
+ path.encode("ascii"),
+ query_bytes=query_bytes,
+ retry_on_dns_fail=retry_on_dns_fail
+ )
+
+ body = yield readBody(response)
+
+ defer.returnValue(json.loads(body))
+
+
def _getEndpoint(self, reactor, destination):
return matrix_endpoint(
reactor, destination, timeout=10,
@@ -290,10 +226,63 @@ class TwistedHttpClient(HttpClient):
)
-class PlainHttpClient(TwistedHttpClient):
+class IdentityServerHttpClient(BaseHttpClient):
+ """Separate HTTP client for talking to the Identity servers since they
+ don't use SRV records and talk x-www-form-urlencoded rather than JSON.
+ """
def _getEndpoint(self, reactor, destination):
+ #TODO: This should be talking TLS
return matrix_endpoint(reactor, destination, timeout=10)
-
+
+ @defer.inlineCallbacks
+ def post_urlencoded_get_json(self, destination, path, args={}):
+ logger.debug("post_urlencoded_get_json args: %s", args)
+ query_bytes = urllib.urlencode(args, True)
+
+ response = yield self._create_request(
+ destination.encode("ascii"),
+ "POST",
+ path.encode("ascii"),
+ producer=FileBodyProducer(StringIO(query_bytes)),
+ headers_dict={
+ "Content-Type": ["application/x-www-form-urlencoded"]
+ }
+ )
+
+ body = yield readBody(response)
+
+ defer.returnValue(json.loads(body))
+
+
+class CaptchaServerHttpClient(MatrixHttpClient):
+ """Separate HTTP client for talking to google's captcha servers"""
+
+ def _getEndpoint(self, reactor, destination):
+ return matrix_endpoint(reactor, destination, timeout=10)
+
+ @defer.inlineCallbacks
+ def post_urlencoded_get_raw(self, destination, path, accept_partial=False,
+ args={}):
+ query_bytes = urllib.urlencode(args, True)
+
+ response = yield self._create_request(
+ destination.encode("ascii"),
+ "POST",
+ path.encode("ascii"),
+ producer=FileBodyProducer(StringIO(query_bytes)),
+ headers_dict={
+ "Content-Type": ["application/x-www-form-urlencoded"]
+ }
+ )
+
+ try:
+ body = yield readBody(response)
+ defer.returnValue(body)
+ except PartialDownloadError as e:
+ if accept_partial:
+ defer.returnValue(e.response)
+ else:
+ raise e
def _print_ex(e):
if hasattr(e, "reasons") and e.reasons:
diff --git a/synctl b/synctl
index 7523fd3dbc..c227a9e1e4 100755
--- a/synctl
+++ b/synctl
@@ -14,7 +14,7 @@ case "$1" in
start)
if [ ! -f "$CONFIGFILE" ]; then
echo "No config file found"
- echo "To generate a config file, run '$SYNAPSE -c $CONFIGFILE --generate-config'"
+ echo "To generate a config file, run '$SYNAPSE -c $CONFIGFILE --generate-config --server-name=<server name>'"
exit 1
fi
diff --git a/tests/federation/test_federation.py b/tests/federation/test_federation.py
index bb17e9aafe..d95b9013a3 100644
--- a/tests/federation/test_federation.py
+++ b/tests/federation/test_federation.py
@@ -253,7 +253,7 @@ class FederationTestCase(unittest.TestCase):
response = yield self.federation.make_query(
destination="remote",
query_type="a-question",
- args={"one": "1", "two": "2"}
+ args={"one": "1", "two": "2"},
)
self.assertEquals({"your": "response"}, response)
@@ -261,7 +261,8 @@ class FederationTestCase(unittest.TestCase):
self.mock_http_client.get_json.assert_called_with(
destination="remote",
path="/_matrix/federation/v1/query/a-question",
- args={"one": "1", "two": "2"}
+ args={"one": "1", "two": "2"},
+ retry_on_dns_fail=True,
)
@defer.inlineCallbacks
diff --git a/tests/handlers/test_directory.py b/tests/handlers/test_directory.py
index dd5d85dde6..e10a49a8ac 100644
--- a/tests/handlers/test_directory.py
+++ b/tests/handlers/test_directory.py
@@ -20,7 +20,6 @@ from twisted.internet import defer
from mock import Mock
from synapse.server import HomeServer
-from synapse.http.client import HttpClient
from synapse.handlers.directory import DirectoryHandler
from synapse.storage.directory import RoomAliasMapping
@@ -95,8 +94,8 @@ class DirectoryTestCase(unittest.TestCase):
query_type="directory",
args={
"room_alias": "#another:remote",
- HttpClient.RETRY_DNS_LOOKUP_FAILURES: False
- }
+ },
+ retry_on_dns_fail=False,
)
@defer.inlineCallbacks
|