patharanor commited on
Commit
e76ee44
·
1 Parent(s): 9dc1c8f

fix: request body does not match the expected schema

Browse files
Files changed (5) hide show
  1. .dockerignore +2 -0
  2. .gitignore +2 -0
  3. apis/common.py +42 -0
  4. apis/s3.py +1 -1
  5. app.py +38 -21
.dockerignore CHANGED
@@ -1,2 +1,4 @@
1
  __pycache__
 
 
2
  .env
 
1
  __pycache__
2
+ env
3
+
4
  .env
.gitignore CHANGED
@@ -1,2 +1,4 @@
1
  __pycache__
 
 
2
  .env
 
1
  __pycache__
2
+ env
3
+
4
  .env
apis/common.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ from datetime import datetime
3
+ from io import BytesIO
4
+ import os
5
+ from typing import Union
6
+ from PIL import Image
7
+
8
+ class Common:
9
+ def __init__(self, is_debug=False) -> None:
10
+ self.is_debug = is_debug
11
+ self.image_color_mode = 'RGB'
12
+ self.image_format_png = 'PNG'
13
+ self.image_format_jpeg = 'JPEG'
14
+
15
+ def today(self):
16
+ return datetime.today().strftime('%Y%m%d%H%M%S')
17
+
18
+ def create_dir_not_exist(self, target_dir:str):
19
+ if not os.path.exists(target_dir):
20
+ os.mkdir(target_dir)
21
+
22
+ def base64str_to_image(self, content:Union[bytes, None]):
23
+ return Image.open(BytesIO(base64.b64decode(content))).convert(self.image_color_mode)
24
+
25
+ def base64str_to_bytes(self, content:str):
26
+ orig_image = Image.open(BytesIO(base64.b64decode(content))).convert('RGB')
27
+
28
+ img_bytes = BytesIO()
29
+ # image.save expects a file-like as a argument
30
+ orig_image.save(img_bytes, format=self.image_format_jpeg)
31
+ # Turn the BytesIO object back into a bytes object
32
+ img_bytes = img_bytes.getvalue()
33
+ return img_bytes
34
+
35
+ def imagearray_to_image(self, image_arr):
36
+ return Image.fromarray(image_arr)
37
+
38
+ def image_to_base64str(self, image:Image):
39
+ buffered = BytesIO()
40
+ image.save(buffered, format=self.image_format_png)
41
+ img_base64str = base64.b64encode(buffered.getvalue())
42
+ return img_base64str
apis/s3.py CHANGED
@@ -28,7 +28,6 @@ class S3:
28
 
29
  # Function to upload file to S3
30
  def upload_file(self, bucket_name, file, name):
31
- print(f'Uploading "{name}"...')
32
  return self.client.upload_fileobj(file, bucket_name, name)
33
 
34
  # Function to delete a file from S3
@@ -48,3 +47,4 @@ class S3:
48
  # Function to get image URLs
49
  def get_files_urls(self, bucket_name, file_keys):
50
  return [self.client.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': key}) for key in file_keys]
 
 
28
 
29
  # Function to upload file to S3
30
  def upload_file(self, bucket_name, file, name):
 
31
  return self.client.upload_fileobj(file, bucket_name, name)
32
 
33
  # Function to delete a file from S3
 
47
  # Function to get image URLs
48
  def get_files_urls(self, bucket_name, file_keys):
49
  return [self.client.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': key}) for key in file_keys]
50
+
app.py CHANGED
@@ -1,11 +1,11 @@
1
- import os
2
  import uvicorn
3
- from typing import Annotated
4
  from fastapi import FastAPI, Header
5
  from apis.s3 import S3
6
  from dotenv import load_dotenv
7
  from models.image_object import ImageObject
8
- from models.common_headers import CommonHeaders
9
  from fastapi.openapi.docs import (
10
  get_redoc_html,
11
  get_swagger_ui_html,
@@ -15,11 +15,17 @@ from fastapi.openapi.docs import (
15
  load_dotenv()
16
  IS_DEV = os.environ.get('ENV', 'DEV') != 'PROD'
17
  AWS_S3_BUCKET_NAME = os.getenv('AWS_S3_BUCKET_NAME', '')
18
- USERNAME = os.environ.get('USERNAME')
19
- PASSWORD = os.environ.get('PASSWORD')
20
 
21
  s3client = S3()
 
22
  app = FastAPI(docs_url=None, redoc_url=None)
 
 
 
 
 
23
 
24
  @app.get("/docs", include_in_schema=False)
25
  async def custom_swagger_ui_html():
@@ -55,26 +61,37 @@ def healthcheck():
55
  @app.post("/image")
56
  async def upload(
57
  o: ImageObject,
58
- headers: Annotated[CommonHeaders, Header()]
 
59
  ):
60
  res = None
61
- if headers.x_request_user == USERNAME \
62
- and headers.x_api_key == PASSWORD:
 
63
  key = f'{o.key}/{o.job_no}/{o.name}'
64
- res = s3client.upload_file(AWS_S3_BUCKET_NAME, o.content, key)
65
- return res
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
- # # Create a Gradio interface
68
- # with gr.Blocks() as demo:
69
- # pass
70
-
71
- # def auth(username, password):
72
- # u = os.environ.get('USERNAME')
73
- # p = os.environ.get('PASSWORD')
74
- # return (username == u and password == p)
75
-
76
- # # Launch the Gradio app
77
- # demo.launch(auth=auth if not IS_DEV else None)
78
 
79
  if __name__=='__main__':
80
  uvicorn.run('app:app', host='0.0.0.0', port=7860, reload=True)
 
1
+ import os, io, base64
2
  import uvicorn
3
+ import logging
4
  from fastapi import FastAPI, Header
5
  from apis.s3 import S3
6
  from dotenv import load_dotenv
7
  from models.image_object import ImageObject
8
+ from apis.common import Common
9
  from fastapi.openapi.docs import (
10
  get_redoc_html,
11
  get_swagger_ui_html,
 
15
  load_dotenv()
16
  IS_DEV = os.environ.get('ENV', 'DEV') != 'PROD'
17
  AWS_S3_BUCKET_NAME = os.getenv('AWS_S3_BUCKET_NAME', '')
18
+ X_REQUEST_USER = os.environ.get('X_REQUEST_USER')
19
+ X_API_KEY = os.environ.get('X_API_KEY')
20
 
21
  s3client = S3()
22
+ common = Common()
23
  app = FastAPI(docs_url=None, redoc_url=None)
24
+ logging.basicConfig(
25
+ level=logging.DEBUG if IS_DEV else logging.INFO,
26
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
27
+ datefmt='%Y-%m-%d %H:%M:%S'
28
+ )
29
 
30
  @app.get("/docs", include_in_schema=False)
31
  async def custom_swagger_ui_html():
 
61
  @app.post("/image")
62
  async def upload(
63
  o: ImageObject,
64
+ x_request_user: str = Header(...),
65
+ x_api_key: str = Header(...)
66
  ):
67
  res = None
68
+ logging.info("--------------------------------")
69
+ logging.info("Received request to upload image")
70
+ if is_valid(x_request_user, x_api_key):
71
  key = f'{o.key}/{o.job_no}/{o.name}'
72
+ logging.info(f'Key for S3 upload: {key}')
73
+ if o.content is not None:
74
+ try:
75
+ # Decode base64 content
76
+ decoded_content = base64.b64decode(o.content)
77
+ logging.info(f'Decoded content length: {len(decoded_content)} bytes')
78
+
79
+ # Wrap bytes in BytesIO to create a file-like object
80
+ file_obj = io.BytesIO(decoded_content)
81
+
82
+ # Upload file object to S3
83
+ # logging.info(f"Uploading file to S3 bucket '{AWS_S3_BUCKET_NAME}' with key '{key}'")
84
+ res = s3client.upload_file(AWS_S3_BUCKET_NAME, file_obj, key)
85
+ logging.info("File uploaded successfully")
86
+
87
+ except Exception as e:
88
+ logging.warning(f"Error during upload: {e}")
89
+ return {"error": "Failed to upload content"}
90
+
91
+ return {"result": res}
92
 
93
+ def is_valid(u, p):
94
+ return u == X_REQUEST_USER and p == X_API_KEY
 
 
 
 
 
 
 
 
 
95
 
96
  if __name__=='__main__':
97
  uvicorn.run('app:app', host='0.0.0.0', port=7860, reload=True)