Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -765,6 +765,89 @@ def generate_sozo_slides(project_id):
|
|
| 765 |
db.reference(f'sozo_projects/{project_id}').update({'status': 'failed_slides', 'error': str(e)})
|
| 766 |
return jsonify({'error': str(e)}), 500
|
| 767 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 768 |
@app.route('/api/sozo/projects/<string:project_id>/charts', methods=['POST'])
|
| 769 |
def regenerate_sozo_chart(project_id):
|
| 770 |
logger.info(f"Endpoint /charts POST for project {project_id}")
|
|
|
|
| 765 |
db.reference(f'sozo_projects/{project_id}').update({'status': 'failed_slides', 'error': str(e)})
|
| 766 |
return jsonify({'error': str(e)}), 500
|
| 767 |
|
| 768 |
+
@app.route('/api/image-proxy', methods=['GET'])
|
| 769 |
+
def image_proxy():
|
| 770 |
+
image_url = request.args.get('url')
|
| 771 |
+
logger.info(f"[IMAGE PROXY] Received URL: {image_url}")
|
| 772 |
+
|
| 773 |
+
if not image_url:
|
| 774 |
+
logger.error("[IMAGE PROXY] ERROR: URL parameter is missing")
|
| 775 |
+
return jsonify({'error': 'URL parameter is missing.'}), 400
|
| 776 |
+
|
| 777 |
+
try:
|
| 778 |
+
# Parse Firebase Storage URL
|
| 779 |
+
# Expected format: https://storage.googleapis.com/bucket-name/path/to/file.ext
|
| 780 |
+
if 'storage.googleapis.com' not in image_url:
|
| 781 |
+
logger.error(f"[IMAGE PROXY] ERROR: Invalid Firebase Storage URL: {image_url}")
|
| 782 |
+
return jsonify({'error': 'Invalid Firebase Storage URL.'}), 400
|
| 783 |
+
|
| 784 |
+
logger.info(f"[IMAGE PROXY] Parsing URL: {image_url}")
|
| 785 |
+
|
| 786 |
+
# Extract bucket name and blob path from the URL
|
| 787 |
+
url_parts = image_url.split('storage.googleapis.com/')[1]
|
| 788 |
+
logger.info(f"[IMAGE PROXY] URL parts after split: {url_parts}")
|
| 789 |
+
|
| 790 |
+
# Remove query parameters if present
|
| 791 |
+
url_parts = url_parts.split('?')[0]
|
| 792 |
+
logger.info(f"[IMAGE PROXY] URL parts after removing query params: {url_parts}")
|
| 793 |
+
|
| 794 |
+
# Split into bucket name and blob path
|
| 795 |
+
path_components = url_parts.split('/', 1)
|
| 796 |
+
logger.info(f"[IMAGE PROXY] Path components: {path_components}")
|
| 797 |
+
|
| 798 |
+
if len(path_components) < 2:
|
| 799 |
+
logger.error(f"[IMAGE PROXY] ERROR: Invalid URL format - path_components: {path_components}")
|
| 800 |
+
return jsonify({'error': 'Invalid URL format.'}), 400
|
| 801 |
+
|
| 802 |
+
url_bucket_name = path_components[0]
|
| 803 |
+
blob_path = path_components[1]
|
| 804 |
+
|
| 805 |
+
logger.info(f"[IMAGE PROXY] Extracted bucket name: {url_bucket_name}")
|
| 806 |
+
logger.info(f"[IMAGE PROXY] Extracted blob path: {blob_path}")
|
| 807 |
+
|
| 808 |
+
# Verify bucket name matches (optional security check)
|
| 809 |
+
expected_bucket_name = bucket.name
|
| 810 |
+
logger.info(f"[IMAGE PROXY] Expected bucket name: {expected_bucket_name}")
|
| 811 |
+
|
| 812 |
+
if url_bucket_name != expected_bucket_name:
|
| 813 |
+
logger.error(f"[IMAGE PROXY] ERROR: Bucket name mismatch - URL: {url_bucket_name}, Expected: {expected_bucket_name}")
|
| 814 |
+
return jsonify({'error': 'Bucket name mismatch.'}), 403
|
| 815 |
+
|
| 816 |
+
logger.info(f"[IMAGE PROXY] Creating blob object for path: {blob_path}")
|
| 817 |
+
|
| 818 |
+
# Get the blob
|
| 819 |
+
blob = bucket.blob(blob_path)
|
| 820 |
+
|
| 821 |
+
logger.info(f"[IMAGE PROXY] Checking if blob exists...")
|
| 822 |
+
if not blob.exists():
|
| 823 |
+
logger.error(f"[IMAGE PROXY] ERROR: Image not found at path: {blob_path}")
|
| 824 |
+
return jsonify({'error': 'Image not found.'}), 404
|
| 825 |
+
|
| 826 |
+
logger.info(f"[IMAGE PROXY] Downloading blob...")
|
| 827 |
+
# Download and return the image
|
| 828 |
+
image_bytes = blob.download_as_bytes()
|
| 829 |
+
content_type = blob.content_type or 'application/octet-stream'
|
| 830 |
+
|
| 831 |
+
logger.info(f"[IMAGE PROXY] Successfully downloaded {len(image_bytes)} bytes, content-type: {content_type}")
|
| 832 |
+
|
| 833 |
+
# Add cache headers for better performance
|
| 834 |
+
response = Response(image_bytes, content_type=content_type)
|
| 835 |
+
response.headers['Cache-Control'] = 'public, max-age=3600' # Cache for 1 hour
|
| 836 |
+
return response
|
| 837 |
+
|
| 838 |
+
except IndexError as e:
|
| 839 |
+
logger.error(f"[IMAGE PROXY] URL parsing IndexError: {e}")
|
| 840 |
+
logger.error(f"[IMAGE PROXY] URL was: {image_url}")
|
| 841 |
+
return jsonify({'error': 'Invalid URL format.'}), 400
|
| 842 |
+
except Exception as e:
|
| 843 |
+
# This will catch parsing errors or other unexpected issues.
|
| 844 |
+
logger.error(f"[IMAGE PROXY] Unexpected error: {e}")
|
| 845 |
+
logger.error(f"[IMAGE PROXY] Error type: {type(e).__name__}")
|
| 846 |
+
logger.error(f"[IMAGE PROXY] URL was: {image_url}")
|
| 847 |
+
import traceback
|
| 848 |
+
logger.error(f"[IMAGE PROXY] Full traceback: {traceback.format_exc()}")
|
| 849 |
+
return jsonify({'error': 'Internal server error processing the image request.'}), 500
|
| 850 |
+
|
| 851 |
@app.route('/api/sozo/projects/<string:project_id>/charts', methods=['POST'])
|
| 852 |
def regenerate_sozo_chart(project_id):
|
| 853 |
logger.info(f"Endpoint /charts POST for project {project_id}")
|