Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2 of asyncjsonwrap #373

Merged
merged 12 commits into from Jun 29, 2021
2 changes: 1 addition & 1 deletion changelog.d/372.misc
@@ -1 +1 @@
Convert `inlineCallbacks` to async/await.
Convert `inlineCallbacks` to async/await.
1 change: 1 addition & 0 deletions changelog.d/373.misc
@@ -0,0 +1 @@
Convert `inlineCallbacks` to async/await.
50 changes: 14 additions & 36 deletions sydent/http/servlets/__init__.py
Expand Up @@ -19,7 +19,7 @@
from typing import Any, Dict, Iterable

from twisted.internet import defer
from twisted.python.failure import Failure
from twisted.python import failure
from twisted.web import server
from twisted.web.server import Request

Expand Down Expand Up @@ -163,45 +163,27 @@ def inner(self, request: Request, *args, **kwargs) -> bytes:


def asyncjsonwrap(f):
def reqDone(resp: Dict[str, Any], request: Request) -> None:
"""
Converts the given response content into JSON and encodes it to bytes, then
writes it as the response to the given request with the right headers.

:param resp: The response content to convert to JSON and encode.
:param request: The request to respond to.
"""
request.setHeader("Content-Type", "application/json")
request.write(dict_to_json_bytes(resp))
request.finish()

def reqErr(failure: Failure, request: Request) -> None:
"""
Logs the given failure. If the failure is a MatrixRestError, writes a response
using the info it contains, otherwise responds with 500 Internal Server Error.

:param failure: The failure to process.
:param request: The request to respond to.
"""
async def render(f, servlet, request, **kwargs):
clokep marked this conversation as resolved.
Show resolved Hide resolved
request.setHeader("Content-Type", "application/json")
if failure.check(MatrixRestError) is not None:
request.setResponseCode(failure.value.httpStatus)
try:
result = await f(servlet, request, **kwargs)
request.write(dict_to_json_bytes(result))
request.finish()
except MatrixRestError as e:
request.setResponseCode(e.value.httpStatus)
H-Shay marked this conversation as resolved.
Show resolved Hide resolved
request.write(
dict_to_json_bytes(
{"errcode": failure.value.errcode, "error": failure.value.error}
)
)
else:
logger.error(
"Request processing failed: %r, %s", failure, failure.getTraceback()
dict_to_json_bytes({"errcode": e.value.errcode, "error": e.value.error})
H-Shay marked this conversation as resolved.
Show resolved Hide resolved
)
except Exception:
f = failure.Failure()
logger.error("Request processing failed: %r, %s", f, f.getTraceback())
request.setResponseCode(500)
request.write(
dict_to_json_bytes(
{"errcode": "M_UNKNOWN", "error": "Internal Server Error"}
)
)
request.finish()
request.finish()
H-Shay marked this conversation as resolved.
Show resolved Hide resolved

def inner(*args, **kwargs) -> int:
"""
Expand All @@ -214,11 +196,7 @@ def inner(*args, **kwargs) -> int:
:return: A special code to tell the servlet that the response isn't ready yet
and will come later.
"""
request = args[1]

d = defer.ensureDeferred(f(*args, **kwargs))
d.addCallback(reqDone, request)
d.addErrback(reqErr, request)
defer.ensureDeferred(render(f, *args, **kwargs))
return server.NOT_DONE_YET

return inner
Expand Down