1# Copyright 2018 New Vector Ltd 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import logging 16from typing import TYPE_CHECKING, Optional 17 18from twisted.web.resource import Resource 19from twisted.web.server import Request 20 21from synapse.http.server import set_cors_headers 22from synapse.types import JsonDict 23from synapse.util import json_encoder 24from synapse.util.stringutils import parse_server_name 25 26if TYPE_CHECKING: 27 from synapse.server import HomeServer 28 29logger = logging.getLogger(__name__) 30 31 32class WellKnownBuilder: 33 def __init__(self, hs: "HomeServer"): 34 self._config = hs.config 35 36 def get_well_known(self) -> Optional[JsonDict]: 37 if not self._config.server.serve_client_wellknown: 38 return None 39 40 result = {"m.homeserver": {"base_url": self._config.server.public_baseurl}} 41 42 if self._config.registration.default_identity_server: 43 result["m.identity_server"] = { 44 "base_url": self._config.registration.default_identity_server 45 } 46 47 return result 48 49 50class ClientWellKnownResource(Resource): 51 """A Twisted web resource which renders the .well-known/matrix/client file""" 52 53 isLeaf = 1 54 55 def __init__(self, hs: "HomeServer"): 56 Resource.__init__(self) 57 self._well_known_builder = WellKnownBuilder(hs) 58 59 def render_GET(self, request: Request) -> bytes: 60 set_cors_headers(request) 61 r = self._well_known_builder.get_well_known() 62 if not r: 63 request.setResponseCode(404) 64 request.setHeader(b"Content-Type", b"text/plain") 65 return b".well-known not available" 66 67 logger.debug("returning: %s", r) 68 request.setHeader(b"Content-Type", b"application/json") 69 return json_encoder.encode(r).encode("utf-8") 70 71 72class ServerWellKnownResource(Resource): 73 """Resource for .well-known/matrix/server, redirecting to port 443""" 74 75 isLeaf = 1 76 77 def __init__(self, hs: "HomeServer"): 78 super().__init__() 79 self._serve_server_wellknown = hs.config.server.serve_server_wellknown 80 81 host, port = parse_server_name(hs.config.server.server_name) 82 83 # If we've got this far, then https://<server_name>/ must route to us, so 84 # we just redirect the traffic to port 443 instead of 8448. 85 if port is None: 86 port = 443 87 88 self._response = json_encoder.encode({"m.server": f"{host}:{port}"}).encode( 89 "utf-8" 90 ) 91 92 def render_GET(self, request: Request) -> bytes: 93 if not self._serve_server_wellknown: 94 request.setResponseCode(404) 95 request.setHeader(b"Content-Type", b"text/plain") 96 return b"404. Is anything ever truly *well* known?\n" 97 98 request.setHeader(b"Content-Type", b"application/json") 99 return self._response 100 101 102def well_known_resource(hs: "HomeServer") -> Resource: 103 """Returns a Twisted web resource which handles '.well-known' requests""" 104 res = Resource() 105 matrix_resource = Resource() 106 res.putChild(b"matrix", matrix_resource) 107 108 matrix_resource.putChild(b"server", ServerWellKnownResource(hs)) 109 matrix_resource.putChild(b"client", ClientWellKnownResource(hs)) 110 111 return res 112