forked from MirrorHub/synapse
Fix media repo breaking (#5593)
This commit is contained in:
parent
f8b52eb8c5
commit
0ee9076ffe
6 changed files with 60 additions and 26 deletions
1
changelog.d/5593.bugfix
Normal file
1
changelog.d/5593.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix regression in 1.1rc1 where OPTIONS requests to the media repo would fail.
|
|
@ -65,8 +65,8 @@ def wrap_json_request_handler(h):
|
||||||
The handler method must have a signature of "handle_foo(self, request)",
|
The handler method must have a signature of "handle_foo(self, request)",
|
||||||
where "request" must be a SynapseRequest.
|
where "request" must be a SynapseRequest.
|
||||||
|
|
||||||
The handler must return a deferred. If the deferred succeeds we assume that
|
The handler must return a deferred or a coroutine. If the deferred succeeds
|
||||||
a response has been sent. If the deferred fails with a SynapseError we use
|
we assume that a response has been sent. If the deferred fails with a SynapseError we use
|
||||||
it to send a JSON response with the appropriate HTTP reponse code. If the
|
it to send a JSON response with the appropriate HTTP reponse code. If the
|
||||||
deferred fails with any other type of error we send a 500 reponse.
|
deferred fails with any other type of error we send a 500 reponse.
|
||||||
"""
|
"""
|
||||||
|
@ -353,16 +353,22 @@ class DirectServeResource(resource.Resource):
|
||||||
"""
|
"""
|
||||||
Render the request, using an asynchronous render handler if it exists.
|
Render the request, using an asynchronous render handler if it exists.
|
||||||
"""
|
"""
|
||||||
render_callback_name = "_async_render_" + request.method.decode("ascii")
|
async_render_callback_name = "_async_render_" + request.method.decode("ascii")
|
||||||
|
|
||||||
if hasattr(self, render_callback_name):
|
# Try and get the async renderer
|
||||||
# Call the handler
|
callback = getattr(self, async_render_callback_name, None)
|
||||||
callback = getattr(self, render_callback_name)
|
|
||||||
defer.ensureDeferred(callback(request))
|
|
||||||
|
|
||||||
return NOT_DONE_YET
|
# No async renderer for this request method.
|
||||||
else:
|
if not callback:
|
||||||
super().render(request)
|
return super().render(request)
|
||||||
|
|
||||||
|
resp = callback(request)
|
||||||
|
|
||||||
|
# If it's a coroutine, turn it into a Deferred
|
||||||
|
if isinstance(resp, types.CoroutineType):
|
||||||
|
defer.ensureDeferred(resp)
|
||||||
|
|
||||||
|
return NOT_DONE_YET
|
||||||
|
|
||||||
|
|
||||||
def _options_handler(request):
|
def _options_handler(request):
|
||||||
|
|
|
@ -95,6 +95,7 @@ class PreviewUrlResource(DirectServeResource):
|
||||||
)
|
)
|
||||||
|
|
||||||
def render_OPTIONS(self, request):
|
def render_OPTIONS(self, request):
|
||||||
|
request.setHeader(b"Allow", b"OPTIONS, GET")
|
||||||
return respond_with_json(request, 200, {}, send_cors=True)
|
return respond_with_json(request, 200, {}, send_cors=True)
|
||||||
|
|
||||||
@wrap_json_request_handler
|
@wrap_json_request_handler
|
||||||
|
|
|
@ -24,6 +24,7 @@ See doc/log_contexts.rst for details on how this works.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
|
import types
|
||||||
|
|
||||||
from twisted.internet import defer, threads
|
from twisted.internet import defer, threads
|
||||||
|
|
||||||
|
@ -528,8 +529,9 @@ def run_in_background(f, *args, **kwargs):
|
||||||
return from the function, and that the sentinel context is set once the
|
return from the function, and that the sentinel context is set once the
|
||||||
deferred returned by the function completes.
|
deferred returned by the function completes.
|
||||||
|
|
||||||
Useful for wrapping functions that return a deferred which you don't yield
|
Useful for wrapping functions that return a deferred or coroutine, which you don't
|
||||||
on (for instance because you want to pass it to deferred.gatherResults()).
|
yield or await on (for instance because you want to pass it to
|
||||||
|
deferred.gatherResults()).
|
||||||
|
|
||||||
Note that if you completely discard the result, you should make sure that
|
Note that if you completely discard the result, you should make sure that
|
||||||
`f` doesn't raise any deferred exceptions, otherwise a scary-looking
|
`f` doesn't raise any deferred exceptions, otherwise a scary-looking
|
||||||
|
@ -544,6 +546,9 @@ def run_in_background(f, *args, **kwargs):
|
||||||
# by synchronous exceptions, so let's turn them into Failures.
|
# by synchronous exceptions, so let's turn them into Failures.
|
||||||
return defer.fail()
|
return defer.fail()
|
||||||
|
|
||||||
|
if isinstance(res, types.CoroutineType):
|
||||||
|
res = defer.ensureDeferred(res)
|
||||||
|
|
||||||
if not isinstance(res, defer.Deferred):
|
if not isinstance(res, defer.Deferred):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -460,3 +460,15 @@ class URLPreviewTests(unittest.HomeserverTestCase):
|
||||||
"error": "DNS resolution failure during URL preview generation",
|
"error": "DNS resolution failure during URL preview generation",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_OPTIONS(self):
|
||||||
|
"""
|
||||||
|
OPTIONS returns the OPTIONS.
|
||||||
|
"""
|
||||||
|
request, channel = self.make_request(
|
||||||
|
"OPTIONS", "url_preview?url=http://example.com", shorthand=False
|
||||||
|
)
|
||||||
|
request.render(self.preview_url)
|
||||||
|
self.pump()
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self.assertEqual(channel.json_body, {})
|
||||||
|
|
|
@ -39,24 +39,17 @@ class LoggingContextTestCase(unittest.TestCase):
|
||||||
|
|
||||||
callback_completed = [False]
|
callback_completed = [False]
|
||||||
|
|
||||||
def test():
|
|
||||||
context_one.request = "one"
|
|
||||||
d = function()
|
|
||||||
|
|
||||||
def cb(res):
|
|
||||||
self._check_test_key("one")
|
|
||||||
callback_completed[0] = True
|
|
||||||
return res
|
|
||||||
|
|
||||||
d.addCallback(cb)
|
|
||||||
|
|
||||||
return d
|
|
||||||
|
|
||||||
with LoggingContext() as context_one:
|
with LoggingContext() as context_one:
|
||||||
context_one.request = "one"
|
context_one.request = "one"
|
||||||
|
|
||||||
# fire off function, but don't wait on it.
|
# fire off function, but don't wait on it.
|
||||||
logcontext.run_in_background(test)
|
d2 = logcontext.run_in_background(function)
|
||||||
|
|
||||||
|
def cb(res):
|
||||||
|
callback_completed[0] = True
|
||||||
|
return res
|
||||||
|
|
||||||
|
d2.addCallback(cb)
|
||||||
|
|
||||||
self._check_test_key("one")
|
self._check_test_key("one")
|
||||||
|
|
||||||
|
@ -105,6 +98,22 @@ class LoggingContextTestCase(unittest.TestCase):
|
||||||
|
|
||||||
return self._test_run_in_background(testfunc)
|
return self._test_run_in_background(testfunc)
|
||||||
|
|
||||||
|
def test_run_in_background_with_coroutine(self):
|
||||||
|
async def testfunc():
|
||||||
|
self._check_test_key("one")
|
||||||
|
d = Clock(reactor).sleep(0)
|
||||||
|
self.assertIs(LoggingContext.current_context(), LoggingContext.sentinel)
|
||||||
|
await d
|
||||||
|
self._check_test_key("one")
|
||||||
|
|
||||||
|
return self._test_run_in_background(testfunc)
|
||||||
|
|
||||||
|
def test_run_in_background_with_nonblocking_coroutine(self):
|
||||||
|
async def testfunc():
|
||||||
|
self._check_test_key("one")
|
||||||
|
|
||||||
|
return self._test_run_in_background(testfunc)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def test_make_deferred_yieldable(self):
|
def test_make_deferred_yieldable(self):
|
||||||
# a function which retuns an incomplete deferred, but doesn't follow
|
# a function which retuns an incomplete deferred, but doesn't follow
|
||||||
|
|
Loading…
Reference in a new issue