mirror of
https://github.com/element-hq/synapse.git
synced 2026-05-24 17:25:22 +00:00
⏺ Synapse is running and responding to HTTP requests! The curl to /_matrix/client/versions returned a full JSON response with all the Matrix versions and unstable features. The response was 200 OK, processed in 0.001 seconds.
{"versions":["r0.0.1","r0.1.0",...,"v1.12"],"unstable_features":{...}}
And the access log shows:
Processed request: 0.001sec 1250B 200 "GET /_matrix/client/versions HTTP/1.1" "curl/8.7.1"
Synapse is running on pure asyncio + aiohttp, without Twisted, responding to Matrix client API requests.
This commit is contained in:
@@ -475,6 +475,13 @@ def start_reactor(
|
||||
def main() -> None:
|
||||
homeserver_config = load_or_generate_config(sys.argv[1:])
|
||||
|
||||
# Create an asyncio event loop early so that NativeClock.call_later()
|
||||
# and other asyncio primitives work during homeserver setup (before
|
||||
# the loop is actually running).
|
||||
import asyncio
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
# Create a logging context as soon as possible so we can start associating
|
||||
# everything with this homeserver.
|
||||
with LoggingContext(name="main", server_name=homeserver_config.server.server_name):
|
||||
|
||||
+40
-10
@@ -632,21 +632,51 @@ except ImportError:
|
||||
from synapse.http.resource import Resource as _ResourceBase
|
||||
|
||||
|
||||
class StaticResource(_StaticBase):
|
||||
"""
|
||||
A resource that represents a plain non-interpreted file or directory.
|
||||
class StaticResource(_ResourceBase):
|
||||
"""Serve static files from a directory.
|
||||
|
||||
Differs from the File resource by adding clickjacking protection.
|
||||
Pure-Python replacement for Twisted's ``twisted.web.static.File``.
|
||||
Adds clickjacking protection headers.
|
||||
"""
|
||||
|
||||
def render_GET(self, request: Any) -> bytes:
|
||||
isLeaf = True
|
||||
|
||||
def __init__(self, path: str) -> None:
|
||||
super().__init__()
|
||||
self._path = path
|
||||
|
||||
def render_GET(self, request: "SynapseRequest") -> None:
|
||||
import mimetypes
|
||||
import os
|
||||
|
||||
set_clickjacking_protection_headers(request)
|
||||
return super().render_GET(request)
|
||||
|
||||
def directoryListing(self) -> Any:
|
||||
if notFound is not None:
|
||||
return notFound()
|
||||
return None
|
||||
# Build the file path from the request URI
|
||||
uri = request.path
|
||||
if isinstance(uri, bytes):
|
||||
uri = uri.decode("utf-8")
|
||||
|
||||
# Strip the prefix to get the relative file path
|
||||
# The URI will be like /prefix/file.css — we need just the filename
|
||||
parts = uri.rstrip("/").split("/")
|
||||
filename = parts[-1] if parts else "index.html"
|
||||
|
||||
filepath = os.path.join(self._path, filename)
|
||||
if not os.path.isfile(filepath):
|
||||
request.setResponseCode(404)
|
||||
request.write(b"Not Found")
|
||||
request.finish()
|
||||
return
|
||||
|
||||
content_type, _ = mimetypes.guess_type(filepath)
|
||||
if content_type:
|
||||
request.setHeader(b"Content-Type", content_type.encode("ascii"))
|
||||
|
||||
with open(filepath, "rb") as f:
|
||||
data = f.read()
|
||||
request.setHeader(b"Content-Length", str(len(data)).encode("ascii"))
|
||||
request.write(data)
|
||||
request.finish()
|
||||
|
||||
|
||||
class UnrecognizedRequestResource(_ResourceBase):
|
||||
|
||||
@@ -3,7 +3,7 @@ import time
|
||||
from logging import Handler, LogRecord
|
||||
from logging.handlers import MemoryHandler
|
||||
from threading import Thread
|
||||
from typing import Optional, cast
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class PeriodicallyFlushingMemoryHandler(MemoryHandler):
|
||||
@@ -24,21 +24,20 @@ class PeriodicallyFlushingMemoryHandler(MemoryHandler):
|
||||
target: Handler | None = None,
|
||||
flushOnClose: bool = True,
|
||||
period: float = 5.0,
|
||||
reactor: Optional[IReactorCore] = None,
|
||||
reactor: Any = None,
|
||||
) -> None:
|
||||
"""
|
||||
period: the period between automatic flushes
|
||||
|
||||
reactor: if specified, a custom reactor to use. If not specifies,
|
||||
defaults to the globally-installed reactor.
|
||||
Log entries will be flushed immediately until this reactor has
|
||||
started.
|
||||
reactor: legacy parameter, ignored. Kept for config compat.
|
||||
"""
|
||||
super().__init__(capacity, flushLevel, target, flushOnClose)
|
||||
|
||||
self._flush_period: float = period
|
||||
self._active: bool = True
|
||||
self._reactor_started = False
|
||||
# In the asyncio world there is no delayed reactor start —
|
||||
# the event loop is running by the time log messages are emitted.
|
||||
self._reactor_started = True
|
||||
|
||||
self._flushing_thread: Thread = Thread(
|
||||
name="PeriodicallyFlushingMemoryHandler flushing thread",
|
||||
@@ -47,28 +46,6 @@ class PeriodicallyFlushingMemoryHandler(MemoryHandler):
|
||||
)
|
||||
self._flushing_thread.start()
|
||||
|
||||
def on_reactor_running() -> None:
|
||||
self._reactor_started = True
|
||||
|
||||
reactor_to_use: IReactorCore
|
||||
if reactor is None:
|
||||
reactor_to_use = cast(IReactorCore, global_reactor)
|
||||
else:
|
||||
reactor_to_use = reactor
|
||||
|
||||
# Call our hook when the reactor start up
|
||||
#
|
||||
# type-ignore: Ideally, we'd use `Clock.call_when_running(...)`, but
|
||||
# `PeriodicallyFlushingMemoryHandler` is instantiated via Python logging
|
||||
# configuration, so it's not straightforward to pass in the homeserver's clock
|
||||
# (and we don't want to burden other peoples logging config with the details).
|
||||
#
|
||||
# The important reason why we want to use `Clock.call_when_running` is so that
|
||||
# the callback runs with a logcontext as we want to know which server the logs
|
||||
# came from. But since we don't log anything in the callback, it's safe to
|
||||
# ignore the lint here.
|
||||
reactor_to_use.callWhenRunning(on_reactor_running) # type: ignore[prefer-synapse-clock-call-when-running]
|
||||
|
||||
def shouldFlush(self, record: LogRecord) -> bool:
|
||||
"""
|
||||
Before reactor start-up, log everything immediately.
|
||||
|
||||
+4
-3
@@ -326,9 +326,10 @@ class HomeServer(metaclass=abc.ABCMeta):
|
||||
config: The full config for the homeserver.
|
||||
"""
|
||||
|
||||
if not reactor:
|
||||
reactor = cast(ISynapseReactor, _reactor)
|
||||
|
||||
# The "reactor" is a legacy concept from Twisted. In the asyncio
|
||||
# world it's just a handle that some code passes around. We accept
|
||||
# None and store it; code that actually needs an event loop should
|
||||
# use asyncio.get_running_loop() at call time.
|
||||
self._reactor = reactor
|
||||
self.hostname = hostname
|
||||
# the key we use to sign events and requests
|
||||
|
||||
Reference in New Issue
Block a user