broadfield-dev commited on
Commit
29de23f
Β·
verified Β·
1 Parent(s): b2bb8dd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -42
app.py CHANGED
@@ -4,33 +4,31 @@ import base64
4
  import json
5
  from PIL import Image
6
  import io
 
7
 
8
- # ==============================================================================
9
- # CONFIGURATION
10
- # ==============================================================================
11
-
12
- # This is the full URL to the MCP (base64) endpoint of your SERVER Space.
13
- # Replace this with the URL of your deployed Python API server.
14
- DECODER_API_ENDPOINT = "https://https://broadfield-dev-keylock-auth.hf.space/run/mcp_decode"
15
- # Example: "https://broadfield-dev-keylock-api-python.hf.space/run/mcp_decode"
16
-
17
- # Link to the server space for user reference
18
- SERVER_SPACE_URL = "https://huggingface.co/spaces/broadfield-dev/keylock-auth"
19
- # Example: "https://huggingface.co/spaces/broadfield-dev/KeyLock-API-Python"
20
-
21
 
22
  # ==============================================================================
23
  # API CALL LOGIC
24
  # ==============================================================================
25
 
26
- def call_decoder_api(image: Image.Image) -> dict:
27
  """
28
- Takes a PIL image, converts it to base64, sends it to the decoder API,
29
  and returns the decrypted JSON data.
30
  """
 
 
 
31
  if image is None:
32
  raise gr.Error("Please upload an encrypted image.")
33
 
 
 
 
 
34
  try:
35
  # 1. Convert the PIL Image to a base64 string
36
  buffer = io.BytesIO()
@@ -39,7 +37,7 @@ def call_decoder_api(image: Image.Image) -> dict:
39
  image_base64 = base64.b64encode(image_bytes).decode('utf-8')
40
 
41
  # 2. Prepare the JSON payload for the Gradio API
42
- # Gradio's /run/predict endpoint expects this specific structure
43
  payload = {
44
  "data": [
45
  image_base64
@@ -48,28 +46,28 @@ def call_decoder_api(image: Image.Image) -> dict:
48
 
49
  # 3. Make the POST request to the server API
50
  headers = {"Content-Type": "application/json"}
51
- response = requests.post(DECODER_API_ENDPOINT, headers=headers, json=payload)
52
 
53
- # Raise an error for bad status codes (4xx or 5xx)
54
- response.raise_for_status()
55
-
56
  # 4. Process the response
57
- response_json = response.json()
58
-
59
- # Gradio API wraps results in a "data" list. The actual result is the first element.
60
- if "data" in response_json and len(response_json["data"]) > 0:
61
- return response_json["data"][0]
62
- elif "error" in response_json:
63
- # Handle application-level errors returned by the server
64
- raise gr.Error(f"API Error: {response_json['error']}")
 
65
  else:
66
- raise gr.Error(f"API returned an unexpected response format: {response_json}")
 
 
67
 
68
  except requests.exceptions.RequestException as e:
69
  logger.error(f"Network error calling API: {e}")
70
- raise gr.Error(f"Could not connect to the decoder API. Please check the URL and server status. Error: {e}")
71
  except Exception as e:
72
- logger.error(f"An unexpected error occurred: {e}")
73
  raise gr.Error(f"An unexpected error occurred: {e}")
74
 
75
  # ==============================================================================
@@ -77,33 +75,37 @@ def call_decoder_api(image: Image.Image) -> dict:
77
  # ==============================================================================
78
 
79
  with gr.Blocks(theme=gr.themes.Soft(), title="KeyLock API Client") as demo:
80
- gr.Markdown(f"""
81
- # πŸ”‘ KeyLock API Client
82
- This is a user interface for the [Secure Decoder API]({SERVER_SPACE_URL}).
83
-
84
- Upload an image that was encrypted with the service's public key, and this client will send it to the API for decryption.
85
- """)
86
 
87
  with gr.Row():
88
  with gr.Column(scale=1):
 
 
 
 
 
 
 
 
89
  image_input = gr.Image(
90
  type="pil",
91
  label="Upload Encrypted PNG Image",
92
  sources=["upload", "clipboard"]
93
  )
94
  submit_button = gr.Button("Decrypt via API", variant="primary")
95
-
96
- gr.Markdown("---")
97
- gr.Markdown(f"This client sends requests to the following API endpoint: `{DECODER_API_ENDPOINT}`")
98
 
99
  with gr.Column(scale=2):
100
- gr.Markdown("## Decrypted Data")
101
  json_output = gr.JSON(label="Result from Server")
102
 
103
  # Connect the UI components to the API call function
104
  submit_button.click(
105
  fn=call_decoder_api,
106
- inputs=[image_input],
107
  outputs=[json_output]
108
  )
109
 
 
4
  import json
5
  from PIL import Image
6
  import io
7
+ import logging
8
 
9
+ # --- Configure Logging ---
10
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
11
+ logger = logging.getLogger(__name__)
 
 
 
 
 
 
 
 
 
 
12
 
13
  # ==============================================================================
14
  # API CALL LOGIC
15
  # ==============================================================================
16
 
17
+ def call_decoder_api(server_base_url: str, image: Image.Image) -> dict:
18
  """
19
+ Takes a PIL image, converts it to base64, sends it to the specified server API,
20
  and returns the decrypted JSON data.
21
  """
22
+ # --- Input Validation ---
23
+ if not server_base_url or "hf.space" not in server_base_url:
24
+ raise gr.Error("Please provide a valid Hugging Face Space URL for the server API.")
25
  if image is None:
26
  raise gr.Error("Please upload an encrypted image.")
27
 
28
+ # The specific endpoint for our Gradio API
29
+ api_endpoint = f"{server_base_url.strip('/')}/run/mcp_decode"
30
+ logger.info(f"Attempting to call API at: {api_endpoint}")
31
+
32
  try:
33
  # 1. Convert the PIL Image to a base64 string
34
  buffer = io.BytesIO()
 
37
  image_base64 = base64.b64encode(image_bytes).decode('utf-8')
38
 
39
  # 2. Prepare the JSON payload for the Gradio API
40
+ # Gradio's /run/predict endpoint expects this specific structure: {"data": [input1, input2, ...]}
41
  payload = {
42
  "data": [
43
  image_base64
 
46
 
47
  # 3. Make the POST request to the server API
48
  headers = {"Content-Type": "application/json"}
49
+ response = requests.post(api_endpoint, headers=headers, json=payload, timeout=30)
50
 
 
 
 
51
  # 4. Process the response
52
+ if response.status_code == 200:
53
+ response_json = response.json()
54
+ if "data" in response_json and len(response_json["data"]) > 0:
55
+ # Gradio API wraps results in a "data" list. The actual result is the first element.
56
+ return response_json["data"][0]
57
+ elif "error" in response_json:
58
+ raise gr.Error(f"API returned an error: {response_json['error']}")
59
+ else:
60
+ raise gr.Error(f"API returned an unexpected response format: {response_json}")
61
  else:
62
+ # Handle non-200 responses with more detail
63
+ error_text = response.text
64
+ raise gr.Error(f"API Error (Status {response.status_code}): {error_text}")
65
 
66
  except requests.exceptions.RequestException as e:
67
  logger.error(f"Network error calling API: {e}")
68
+ raise gr.Error(f"Could not connect to the API. Check the URL and server status. Error: {e}")
69
  except Exception as e:
70
+ logger.error(f"An unexpected error occurred: {e}", exc_info=True)
71
  raise gr.Error(f"An unexpected error occurred: {e}")
72
 
73
  # ==============================================================================
 
75
  # ==============================================================================
76
 
77
  with gr.Blocks(theme=gr.themes.Soft(), title="KeyLock API Client") as demo:
78
+ gr.Markdown("# πŸ”‘ KeyLock API Client")
79
+ gr.Markdown(
80
+ "This is a user interface for the **Secure Decoder API**. It sends an encrypted image "
81
+ "to the server for decryption."
82
+ )
 
83
 
84
  with gr.Row():
85
  with gr.Column(scale=1):
86
+ gr.Markdown("### 1. Configure Server URL")
87
+ server_url_input = gr.Textbox(
88
+ label="Decoder API Server URL",
89
+ placeholder="Enter the direct URL of your Python server space...",
90
+ info="Example: https://your-name-keylock-api-python.hf.space"
91
+ )
92
+
93
+ gr.Markdown("### 2. Upload Encrypted Image")
94
  image_input = gr.Image(
95
  type="pil",
96
  label="Upload Encrypted PNG Image",
97
  sources=["upload", "clipboard"]
98
  )
99
  submit_button = gr.Button("Decrypt via API", variant="primary")
 
 
 
100
 
101
  with gr.Column(scale=2):
102
+ gr.Markdown("### 3. Decrypted Data")
103
  json_output = gr.JSON(label="Result from Server")
104
 
105
  # Connect the UI components to the API call function
106
  submit_button.click(
107
  fn=call_decoder_api,
108
+ inputs=[server_url_input, image_input],
109
  outputs=[json_output]
110
  )
111