broadfield-dev commited on
Commit
b2bb8dd
·
verified ·
1 Parent(s): aeb669f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -0
app.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ 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()
37
+ image.save(buffer, format="PNG")
38
+ image_bytes = buffer.getvalue()
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
46
+ ]
47
+ }
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
+ # ==============================================================================
76
+ # GRADIO INTERFACE
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
+
110
+ if __name__ == "__main__":
111
+ demo.launch()