Skip to content

Commit 0171d24

Browse files
authored
Add API support for sending historical images (#218)
1 parent 6381862 commit 0171d24

4 files changed

Lines changed: 82 additions & 3 deletions

File tree

wavefront/server/modules/gold_module/gold_module/controllers/image_controller.py

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
from fastapi.responses import JSONResponse
1414
from gold_module.gold_container import GoldContainer
1515
from gold_module.services.image_service import ImageService
16-
from gold_module.models.gold_image_request import ImageAnalysisRequest
16+
from gold_module.models.gold_image_request import (
17+
ImageAnalysisRequest,
18+
AdhocImageUploadRequest,
19+
)
1720

1821
image_controller = APIRouter()
1922

@@ -88,3 +91,68 @@ async def process_image(
8891
status_code=status.HTTP_200_OK,
8992
content=response_formatter.buildSuccessResponse(result),
9093
)
94+
95+
96+
@image_controller.post('/historical_images')
97+
@inject
98+
async def upload_historical_images(
99+
request: AdhocImageUploadRequest,
100+
image_service: ImageService = Depends(Provide[GoldContainer.image_service]),
101+
response_formatter: ResponseFormatter = Depends(
102+
Provide[CommonContainer.response_formatter]
103+
),
104+
):
105+
image_str = request.image
106+
image_name = request.loan_id
107+
108+
gold_image = None
109+
# Check for data URL (base64 with MIME)
110+
data_url_pattern = r'^data:(image/\w+);base64,(.+)'
111+
match = re.match(data_url_pattern, image_str)
112+
if match:
113+
try:
114+
gold_image = base64.b64decode(match.group(2))
115+
except Exception:
116+
return JSONResponse(
117+
status_code=status.HTTP_400_BAD_REQUEST,
118+
content=response_formatter.buildErrorResponse(
119+
'Invalid base64 image encoding'
120+
),
121+
)
122+
elif image_str.startswith('http://') or image_str.startswith('https://'):
123+
# Download the image from the URL
124+
try:
125+
async with httpx.AsyncClient() as client:
126+
resp = await client.get(image_str)
127+
if resp.status_code != 200:
128+
return JSONResponse(
129+
status_code=status.HTTP_400_BAD_REQUEST,
130+
content=response_formatter.buildErrorResponse(
131+
'Failed to download image from URL'
132+
),
133+
)
134+
gold_image = resp.content
135+
except Exception:
136+
return JSONResponse(
137+
status_code=status.HTTP_400_BAD_REQUEST,
138+
content=response_formatter.buildErrorResponse(
139+
'Error downloading image from URL'
140+
),
141+
)
142+
else:
143+
return JSONResponse(
144+
status_code=status.HTTP_400_BAD_REQUEST,
145+
content=response_formatter.buildErrorResponse(
146+
'Image must be a data URL or a direct image URL'
147+
),
148+
)
149+
if not gold_image:
150+
return JSONResponse(
151+
status_code=status.HTTP_400_BAD_REQUEST,
152+
content=response_formatter.buildErrorResponse('Empty image file'),
153+
)
154+
result = await image_service.save_image(gold_image, image_name)
155+
return JSONResponse(
156+
status_code=status.HTTP_200_OK,
157+
content=response_formatter.buildSuccessResponse(result),
158+
)

wavefront/server/modules/gold_module/gold_module/models/gold_image_request.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,8 @@ def to_str_recursive(val):
8787
class ImageAnalysisRequest(BaseModel):
8888
image: str # data URL (base64 with MIME) or direct URL
8989
metadata: ImageMetadata
90+
91+
92+
class AdhocImageUploadRequest(BaseModel):
93+
image: str
94+
loan_id: str

wavefront/server/modules/gold_module/gold_module/services/cloud_image_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ async def send_message(self, message: Dict[str, Any]) -> str:
2020

2121
@abstractmethod
2222
async def upload_image_metadata(
23-
self, image_metadata: bytes, object_key: str
23+
self, image_metadata: bytes | str, object_key: str
2424
) -> Tuple[str, str]:
2525
"""Upload image metadata to the cloud storage"""
2626
pass

wavefront/server/modules/gold_module/gold_module/services/image_service.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ class ImageService:
1313
def __init__(self, cloud_service: CloudImageService):
1414
self.cloud_service = cloud_service
1515

16+
async def save_image(self, image_data: bytes, image_name: str):
17+
validated_image_data = await self._validate_image(image_data)
18+
19+
bucket_name, file_path = await self.cloud_service.upload_image(
20+
validated_image_data, f'historical_data/{image_name}'
21+
)
22+
1623
async def process_image(
1724
self, image_data: bytes, metadata: Dict[str, Any]
1825
) -> Dict[str, Any]:
@@ -61,7 +68,6 @@ async def _validate_image(self, image_data: bytes) -> bytes:
6168
img_format = img.format if img.format else 'JPEG'
6269
img.save(buffer, format=img_format, quality=85)
6370
return buffer.getvalue()
64-
6571
except Exception as e:
6672
logger.error(f'Error validating image: {str(e)}')
6773
raise ValueError(f'Invalid image data: {str(e)}')

0 commit comments

Comments
 (0)