def respond_404(request): respond_with_json( request, 404, cs_error("Not found %r" % (request.postpath,), code=Codes.NOT_FOUND), send_cors=True, )
def _async_render_POST(self, request): requester = yield self.auth.get_user_by_req(request) # TODO: The checks here are a bit late. The content will have # already been uploaded to a tmp file at this point content_length = request.getHeader(b"Content-Length").decode('ascii') if content_length is None: raise SynapseError( msg="Request must specify a Content-Length", code=400 ) if int(content_length) > self.max_upload_size: raise SynapseError( msg="Upload request body is too large", code=413, ) upload_name = parse_string(request, b"filename", encoding=None) if upload_name: try: upload_name = upload_name.decode('utf8') except UnicodeDecodeError: raise SynapseError( msg="Invalid UTF-8 filename parameter: %r" % (upload_name), code=400, ) headers = request.requestHeaders if headers.hasHeader(b"Content-Type"): media_type = headers.getRawHeaders(b"Content-Type")[0].decode('ascii') else: raise SynapseError( msg="Upload request missing 'Content-Type'", code=400, ) # if headers.hasHeader(b"Content-Disposition"): # disposition = headers.getRawHeaders(b"Content-Disposition")[0] # TODO(markjh): parse content-dispostion content_uri = yield self.media_repo.create_content( media_type, upload_name, request.content, content_length, requester.user ) logger.info("Uploaded content with URI %r", content_uri) respond_with_json( request, 200, {"content_uri": content_uri}, send_cors=True )
def _async_render_POST(self, request): requester = yield self.auth.get_user_by_req(request) # TODO: The checks here are a bit late. The content will have # already been uploaded to a tmp file at this point content_length = request.getHeader("Content-Length") if content_length is None: raise SynapseError(msg="Request must specify a Content-Length", code=400) if int(content_length) > self.max_upload_size: raise SynapseError( msg="Upload request body is too large", code=413, ) upload_name = parse_string(request, "filename") if upload_name: try: upload_name = upload_name.decode('UTF-8') except UnicodeDecodeError: raise SynapseError( msg="Invalid UTF-8 filename parameter: %r" % (upload_name), code=400, ) headers = request.requestHeaders if headers.hasHeader("Content-Type"): media_type = headers.getRawHeaders(b"Content-Type")[0] else: raise SynapseError( msg="Upload request missing 'Content-Type'", code=400, ) # if headers.hasHeader(b"Content-Disposition"): # disposition = headers.getRawHeaders(b"Content-Disposition")[0] # TODO(markjh): parse content-dispostion content_uri = yield self.media_repo.create_content( media_type, upload_name, request.content, content_length, requester.user) logger.info("Uploaded content with URI %r", content_uri) respond_with_json(request, 200, {"content_uri": content_uri}, send_cors=True)
def wrapped_request_handler(self, request): try: yield request_handler(self, request) except CodeMessageException as e: logger.exception(e) respond_with_json(request, e.code, cs_exception(e), send_cors=True) except: logger.exception( "Failed handle request %s.%s on %r", request_handler.__module__, request_handler.__name__, self, ) respond_with_json(request, 500, {"error": "Internal server error"}, send_cors=True)
def wrapped_request_handler(self, request): try: yield request_handler(self, request) except CodeMessageException as e: logger.exception(e) respond_with_json( request, e.code, cs_exception(e), send_cors=True ) except: logger.exception( "Failed handle request %s.%s on %r", request_handler.__module__, request_handler.__name__, self, ) respond_with_json( request, 500, {"error": "Internal server error"}, send_cors=True )
def _async_render_POST(self, request): auth_user, client = yield self.auth.get_user_by_req(request) # TODO: The checks here are a bit late. The content will have # already been uploaded to a tmp file at this point content_length = request.getHeader("Content-Length") if content_length is None: raise SynapseError( msg="Request must specify a Content-Length", code=400 ) if int(content_length) > self.max_upload_size: raise SynapseError( msg="Upload request body is too large", code=413, ) headers = request.requestHeaders if headers.hasHeader("Content-Type"): media_type = headers.getRawHeaders("Content-Type")[0] else: raise SynapseError( msg="Upload request missing 'Content-Type'", code=400, ) # if headers.hasHeader("Content-Disposition"): # disposition = headers.getRawHeaders("Content-Disposition")[0] # TODO(markjh): parse content-dispostion content_uri = yield self.create_content( media_type, None, request.content.read(), content_length, auth_user ) respond_with_json( request, 200, {"content_uri": content_uri}, send_cors=True )
def _async_render_POST(self, request): try: auth_user, client = yield self.auth.get_user_by_req(request) # TODO: The checks here are a bit late. The content will have # already been uploaded to a tmp file at this point content_length = request.getHeader("Content-Length") if content_length is None: raise SynapseError(msg="Request must specify a Content-Length", code=400) if int(content_length) > self.max_upload_size: raise SynapseError( msg="Upload request body is too large", code=413, ) headers = request.requestHeaders if headers.hasHeader("Content-Type"): media_type = headers.getRawHeaders("Content-Type")[0] else: raise SynapseError( msg="Upload request missing 'Content-Type'", code=400, ) # if headers.hasHeader("Content-Disposition"): # disposition = headers.getRawHeaders("Content-Disposition")[0] # TODO(markjh): parse content-dispostion content_uri = yield self.create_content(media_type, None, request.content.read(), content_length, auth_user) respond_with_json(request, 200, {"content_uri": content_uri}, send_cors=True) except CodeMessageException as e: logger.exception(e) respond_with_json(request, e.code, cs_exception(e), send_cors=True) except: logger.exception("Failed to store file") respond_with_json(request, 500, {"error": "Internal server error"}, send_cors=True)
async def _async_render_GET(self, request: SynapseRequest) -> None: await self.auth.get_user_by_req(request) respond_with_json(request, 200, self.limits_dict, send_cors=True)
def render_OPTIONS(self, request): request.setHeader(b"Allow", b"OPTIONS, GET") return respond_with_json(request, 200, {}, send_cors=True)
def _async_render_GET(self, request): yield self.auth.get_user_by_req(request) respond_with_json(request, 200, self.limits_dict)
def _async_render_POST(self, request): try: auth_user = yield self.auth.get_user_by_req(request) # TODO: The checks here are a bit late. The content will have # already been uploaded to a tmp file at this point content_length = request.getHeader("Content-Length") if content_length is None: raise SynapseError(msg="Request must specify a Content-Length", code=400) if int(content_length) > self.max_upload_size: raise SynapseError( msg="Upload request body is too large", code=413, ) headers = request.requestHeaders if headers.hasHeader("Content-Type"): media_type = headers.getRawHeaders("Content-Type")[0] else: raise SynapseError( msg="Upload request missing 'Content-Type'", code=400, ) #if headers.hasHeader("Content-Disposition"): # disposition = headers.getRawHeaders("Content-Disposition")[0] # TODO(markjh): parse content-dispostion media_id = random_string(24) fname = self.filepaths.local_media_filepath(media_id) self._makedirs(fname) # This shouldn't block for very long because the content will have # already been uploaded at this point. with open(fname, "wb") as f: f.write(request.content.read()) yield self.store.store_local_media( media_id=media_id, media_type=media_type, time_now_ms=self.clock.time_msec(), upload_name=None, media_length=content_length, user_id=auth_user, ) media_info = { "media_type": media_type, "media_length": content_length, } yield self._generate_local_thumbnails(media_id, media_info) content_uri = "mxc://%s/%s" % (self.server_name, media_id) respond_with_json(request, 200, {"content_uri": content_uri}, send_cors=True) except CodeMessageException as e: logger.exception(e) respond_with_json(request, e.code, cs_exception(e), send_cors=True) except: logger.exception("Failed to store file") respond_with_json(request, 500, {"error": "Internal server error"}, send_cors=True)
async def _async_render_OPTIONS(self, request): respond_with_json(request, 200, {}, send_cors=True)
async def _async_render_POST(self, request: SynapseRequest) -> None: requester = await self.auth.get_user_by_req(request) raw_content_length = request.getHeader("Content-Length") if raw_content_length is None: raise SynapseError(msg="Request must specify a Content-Length", code=400) try: content_length = int(raw_content_length) except ValueError: raise SynapseError(msg="Content-Length value is invalid", code=400) if content_length > self.max_upload_size: raise SynapseError( msg="Upload request body is too large", code=413, errcode=Codes.TOO_LARGE, ) args: Dict[bytes, List[bytes]] = request.args # type: ignore upload_name_bytes = parse_bytes_from_args(args, "filename") if upload_name_bytes: try: upload_name: Optional[str] = upload_name_bytes.decode("utf8") except UnicodeDecodeError: raise SynapseError( msg="Invalid UTF-8 filename parameter: %r" % (upload_name_bytes, ), code=400, ) # If the name is falsey (e.g. an empty byte string) ensure it is None. else: upload_name = None headers = request.requestHeaders if headers.hasHeader(b"Content-Type"): content_type_headers = headers.getRawHeaders(b"Content-Type") assert content_type_headers # for mypy media_type = content_type_headers[0].decode("ascii") else: media_type = "application/octet-stream" # if headers.hasHeader(b"Content-Disposition"): # disposition = headers.getRawHeaders(b"Content-Disposition")[0] # TODO(markjh): parse content-dispostion try: content: IO = request.content # type: ignore content_uri = await self.media_repo.create_content( media_type, upload_name, content, content_length, requester.user) except SpamMediaException: # For uploading of media we want to respond with a 400, instead of # the default 404, as that would just be confusing. raise SynapseError(400, "Bad content") logger.info("Uploaded content with URI %r", content_uri) respond_with_json(request, 200, {"content_uri": content_uri}, send_cors=True)
async def handle_request(self, request): respond_with_json(request, 200, {"some_key": "some_value_sync"})
async def _async_render_OPTIONS(self, request: SynapseRequest) -> None: respond_with_json(request, 200, {}, send_cors=True)
def render_OPTIONS(self, request): respond_with_json(request, 200, {}, send_cors=True) return NOT_DONE_YET
async def query_keys( self, request: SynapseRequest, query: JsonDict, query_remote_on_cache_miss: bool = False, ) -> None: logger.info("Handling query for keys %r", query) store_queries = [] for server_name, key_ids in query.items(): if (self.federation_domain_whitelist is not None and server_name not in self.federation_domain_whitelist): logger.debug("Federation denied with %s", server_name) continue if not key_ids: key_ids = (None, ) for key_id in key_ids: store_queries.append((server_name, key_id, None)) cached = await self.store.get_server_keys_json(store_queries) json_results: Set[bytes] = set() time_now_ms = self.clock.time_msec() # Note that the value is unused. cache_misses: Dict[str, Dict[str, int]] = {} for (server_name, key_id, _), key_results in cached.items(): results = [(result["ts_added_ms"], result) for result in key_results] if not results and key_id is not None: cache_misses.setdefault(server_name, {})[key_id] = 0 continue if key_id is not None: ts_added_ms, most_recent_result = max(results) ts_valid_until_ms = most_recent_result["ts_valid_until_ms"] req_key = query.get(server_name, {}).get(key_id, {}) req_valid_until = req_key.get("minimum_valid_until_ts") miss = False if req_valid_until is not None: if ts_valid_until_ms < req_valid_until: logger.debug( "Cached response for %r/%r is older than requested" ": valid_until (%r) < minimum_valid_until (%r)", server_name, key_id, ts_valid_until_ms, req_valid_until, ) miss = True else: logger.debug( "Cached response for %r/%r is newer than requested" ": valid_until (%r) >= minimum_valid_until (%r)", server_name, key_id, ts_valid_until_ms, req_valid_until, ) elif (ts_added_ms + ts_valid_until_ms) / 2 < time_now_ms: logger.debug( "Cached response for %r/%r is too old" ": (added (%r) + valid_until (%r)) / 2 < now (%r)", server_name, key_id, ts_added_ms, ts_valid_until_ms, time_now_ms, ) # We more than half way through the lifetime of the # response. We should fetch a fresh copy. miss = True else: logger.debug( "Cached response for %r/%r is still valid" ": (added (%r) + valid_until (%r)) / 2 < now (%r)", server_name, key_id, ts_added_ms, ts_valid_until_ms, time_now_ms, ) if miss: cache_misses.setdefault(server_name, {})[key_id] = 0 # Cast to bytes since postgresql returns a memoryview. json_results.add(bytes(most_recent_result["key_json"])) else: for _, result in results: # Cast to bytes since postgresql returns a memoryview. json_results.add(bytes(result["key_json"])) # If there is a cache miss, request the missing keys, then recurse (and # ensure the result is sent). if cache_misses and query_remote_on_cache_miss: await yieldable_gather_results( lambda t: self.fetcher.get_keys(*t), ((server_name, list(keys), 0) for server_name, keys in cache_misses.items()), ) await self.query_keys(request, query, query_remote_on_cache_miss=False) else: signed_keys = [] for key_json_raw in json_results: key_json = json_decoder.decode(key_json_raw.decode("utf-8")) for signing_key in self.config.key.key_server_signing_keys: key_json = sign_json(key_json, self.config.server.server_name, signing_key) signed_keys.append(key_json) response = {"server_keys": signed_keys} respond_with_json(request, 200, response, canonical_json=True)
async def _async_render_OPTIONS(self, request: SynapseRequest) -> None: request.setHeader(b"Allow", b"OPTIONS, GET") respond_with_json(request, 200, {}, send_cors=True)