MyFSIO v0.2.6 Release #18
@@ -263,11 +263,37 @@ def create_app(
|
|||||||
|
|
||||||
@app.errorhandler(500)
|
@app.errorhandler(500)
|
||||||
def internal_error(error):
|
def internal_error(error):
|
||||||
return render_template('500.html'), 500
|
wants_html = request.accept_mimetypes.accept_html
|
||||||
|
path = request.path or ""
|
||||||
|
if include_ui and wants_html and (path.startswith("/ui") or path == "/"):
|
||||||
|
return render_template('500.html'), 500
|
||||||
|
error_xml = (
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?>'
|
||||||
|
'<Error>'
|
||||||
|
'<Code>InternalError</Code>'
|
||||||
|
'<Message>An internal server error occurred</Message>'
|
||||||
|
f'<Resource>{path}</Resource>'
|
||||||
|
f'<RequestId>{getattr(g, "request_id", "-")}</RequestId>'
|
||||||
|
'</Error>'
|
||||||
|
)
|
||||||
|
return error_xml, 500, {'Content-Type': 'application/xml'}
|
||||||
|
|
||||||
@app.errorhandler(CSRFError)
|
@app.errorhandler(CSRFError)
|
||||||
def handle_csrf_error(e):
|
def handle_csrf_error(e):
|
||||||
return render_template('csrf_error.html', reason=e.description), 400
|
wants_html = request.accept_mimetypes.accept_html
|
||||||
|
path = request.path or ""
|
||||||
|
if include_ui and wants_html and (path.startswith("/ui") or path == "/"):
|
||||||
|
return render_template('csrf_error.html', reason=e.description), 400
|
||||||
|
error_xml = (
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?>'
|
||||||
|
'<Error>'
|
||||||
|
'<Code>CSRFError</Code>'
|
||||||
|
f'<Message>{e.description}</Message>'
|
||||||
|
f'<Resource>{path}</Resource>'
|
||||||
|
f'<RequestId>{getattr(g, "request_id", "-")}</RequestId>'
|
||||||
|
'</Error>'
|
||||||
|
)
|
||||||
|
return error_xml, 400, {'Content-Type': 'application/xml'}
|
||||||
|
|
||||||
@app.template_filter("filesizeformat")
|
@app.template_filter("filesizeformat")
|
||||||
def filesizeformat(value: int) -> str:
|
def filesizeformat(value: int) -> str:
|
||||||
|
|||||||
@@ -2776,9 +2776,14 @@ def object_handler(bucket_name: str, object_key: str):
|
|||||||
except StorageError as exc:
|
except StorageError as exc:
|
||||||
return _error_response("InternalError", str(exc), 500)
|
return _error_response("InternalError", str(exc), 500)
|
||||||
else:
|
else:
|
||||||
stat = path.stat()
|
try:
|
||||||
file_size = stat.st_size
|
stat = path.stat()
|
||||||
etag = storage._compute_etag(path)
|
file_size = stat.st_size
|
||||||
|
etag = storage._compute_etag(path)
|
||||||
|
except PermissionError:
|
||||||
|
return _error_response("AccessDenied", "Permission denied accessing object", 403)
|
||||||
|
except OSError as exc:
|
||||||
|
return _error_response("InternalError", f"Failed to access object: {exc}", 500)
|
||||||
|
|
||||||
if range_header:
|
if range_header:
|
||||||
try:
|
try:
|
||||||
@@ -2819,13 +2824,22 @@ def object_handler(bucket_name: str, object_key: str):
|
|||||||
except StorageError as exc:
|
except StorageError as exc:
|
||||||
return _error_response("InternalError", str(exc), 500)
|
return _error_response("InternalError", str(exc), 500)
|
||||||
else:
|
else:
|
||||||
stat = path.stat()
|
try:
|
||||||
response = Response(status=200)
|
stat = path.stat()
|
||||||
etag = storage._compute_etag(path)
|
response = Response(status=200)
|
||||||
|
etag = storage._compute_etag(path)
|
||||||
|
except PermissionError:
|
||||||
|
return _error_response("AccessDenied", "Permission denied accessing object", 403)
|
||||||
|
except OSError as exc:
|
||||||
|
return _error_response("InternalError", f"Failed to access object: {exc}", 500)
|
||||||
response.headers["Content-Type"] = mimetype
|
response.headers["Content-Type"] = mimetype
|
||||||
logged_bytes = 0
|
logged_bytes = 0
|
||||||
|
|
||||||
_apply_object_headers(response, file_stat=path.stat() if not is_encrypted else None, metadata=metadata, etag=etag)
|
try:
|
||||||
|
file_stat = path.stat() if not is_encrypted else None
|
||||||
|
except (PermissionError, OSError):
|
||||||
|
file_stat = None
|
||||||
|
_apply_object_headers(response, file_stat=file_stat, metadata=metadata, etag=etag)
|
||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
response_overrides = {
|
response_overrides = {
|
||||||
|
|||||||
@@ -522,7 +522,7 @@ class ObjectStorage:
|
|||||||
|
|
||||||
def get_object_path(self, bucket_name: str, object_key: str) -> Path:
|
def get_object_path(self, bucket_name: str, object_key: str) -> Path:
|
||||||
path = self._object_path(bucket_name, object_key)
|
path = self._object_path(bucket_name, object_key)
|
||||||
if not path.exists():
|
if not path.is_file():
|
||||||
raise ObjectNotFoundError("Object not found")
|
raise ObjectNotFoundError("Object not found")
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ def list_bucket_objects(bucket_name: str):
|
|||||||
"etag": obj.etag,
|
"etag": obj.etag,
|
||||||
})
|
})
|
||||||
|
|
||||||
return jsonify({
|
response = jsonify({
|
||||||
"objects": objects_data,
|
"objects": objects_data,
|
||||||
"is_truncated": result.is_truncated,
|
"is_truncated": result.is_truncated,
|
||||||
"next_continuation_token": result.next_continuation_token,
|
"next_continuation_token": result.next_continuation_token,
|
||||||
@@ -613,6 +613,8 @@ def list_bucket_objects(bucket_name: str):
|
|||||||
"metadata": metadata_template,
|
"metadata": metadata_template,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
response.headers["Cache-Control"] = "no-store"
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
@ui_bp.get("/buckets/<bucket_name>/objects/stream")
|
@ui_bp.get("/buckets/<bucket_name>/objects/stream")
|
||||||
|
|||||||
Reference in New Issue
Block a user