assafvayner HF Staff Claude Sonnet 4.5 commited on
Commit
cd93ea5
·
1 Parent(s): 275d5a1

Restructure to create FastAPI app first, then mount Gradio

Browse files

- Create FastAPI app and add webhook routes FIRST
- Then create Gradio interface
- Mount Gradio on FastAPI using gr.mount_gradio_app()
- This ensures webhook routes have priority over Gradio routes
- Add uvicorn and fastapi back to requirements

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Files changed (2) hide show
  1. app.py +65 -59
  2. requirements.txt +2 -0
app.py CHANGED
@@ -1,5 +1,5 @@
1
  import gradio as gr
2
- from fastapi import Request, HTTPException
3
  from fastapi.responses import JSONResponse
4
  import os
5
  import json
@@ -108,6 +108,65 @@ def process_webhook(payload: dict, event_type: str):
108
  return True
109
 
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  # Create Gradio interface
112
  with gr.Blocks(title="HuggingFace Webhook Processor") as demo:
113
  gr.Markdown("""
@@ -215,65 +274,12 @@ with gr.Blocks(title="HuggingFace Webhook Processor") as demo:
215
  outputs=[status_text, message_count, batch_count, latest_batch]
216
  )
217
 
218
- # Get the FastAPI app instance
219
- app = demo.app
220
-
221
-
222
- # Add webhook endpoints to FastAPI app
223
- @app.post("/webhooks/hub")
224
- async def webhook_endpoint(request: Request):
225
- """
226
- Webhook endpoint for HuggingFace Hub events.
227
-
228
- Supports all webhook events documented at:
229
- https://huggingface.co/docs/hub/webhooks
230
- """
231
- try:
232
- # Get the event type from headers
233
- event_type = request.headers.get("X-Event-Type", "unknown")
234
-
235
- # Parse JSON payload
236
- payload = await request.json()
237
-
238
- # Process the webhook
239
- processed = process_webhook(payload, event_type)
240
-
241
- if processed:
242
- return JSONResponse(
243
- content={
244
- "status": "success",
245
- "message": "Webhook received and queued",
246
- "scope": payload.get("event", {}).get("scope")
247
- },
248
- status_code=200
249
- )
250
- else:
251
- return JSONResponse(
252
- content={
253
- "status": "ignored",
254
- "message": "Webhook scope not in allowed list",
255
- "scope": payload.get("event", {}).get("scope")
256
- },
257
- status_code=200
258
- )
259
-
260
- except Exception as e:
261
- print(f"Error processing webhook: {str(e)}")
262
- raise HTTPException(status_code=500, detail=str(e))
263
 
264
-
265
- @app.get("/webhooks/health")
266
- async def health_check():
267
- """Health check endpoint."""
268
- with message_lock:
269
- return {
270
- "status": "healthy",
271
- "messages_in_memory": len(webhook_messages),
272
- "batches_saved": batch_counter,
273
- "allowed_scopes": list(ALLOWED_SCOPES)
274
- }
275
 
276
 
277
- # Launch the Gradio app
278
  if __name__ == "__main__":
279
- demo.queue().launch(server_name="0.0.0.0", server_port=7860)
 
 
1
  import gradio as gr
2
+ from fastapi import FastAPI, Request, HTTPException
3
  from fastapi.responses import JSONResponse
4
  import os
5
  import json
 
108
  return True
109
 
110
 
111
+ # Create FastAPI app first
112
+ app = FastAPI()
113
+
114
+
115
+ # Add webhook endpoints BEFORE mounting Gradio
116
+ @app.post("/webhooks/hub")
117
+ async def webhook_endpoint(request: Request):
118
+ """
119
+ Webhook endpoint for HuggingFace Hub events.
120
+
121
+ Supports all webhook events documented at:
122
+ https://huggingface.co/docs/hub/webhooks
123
+ """
124
+ try:
125
+ # Get the event type from headers
126
+ event_type = request.headers.get("X-Event-Type", "unknown")
127
+
128
+ # Parse JSON payload
129
+ payload = await request.json()
130
+
131
+ # Process the webhook
132
+ processed = process_webhook(payload, event_type)
133
+
134
+ if processed:
135
+ return JSONResponse(
136
+ content={
137
+ "status": "success",
138
+ "message": "Webhook received and queued",
139
+ "scope": payload.get("event", {}).get("scope")
140
+ },
141
+ status_code=200
142
+ )
143
+ else:
144
+ return JSONResponse(
145
+ content={
146
+ "status": "ignored",
147
+ "message": "Webhook scope not in allowed list",
148
+ "scope": payload.get("event", {}).get("scope")
149
+ },
150
+ status_code=200
151
+ )
152
+
153
+ except Exception as e:
154
+ print(f"Error processing webhook: {str(e)}")
155
+ raise HTTPException(status_code=500, detail=str(e))
156
+
157
+
158
+ @app.get("/webhooks/health")
159
+ async def health_check():
160
+ """Health check endpoint."""
161
+ with message_lock:
162
+ return {
163
+ "status": "healthy",
164
+ "messages_in_memory": len(webhook_messages),
165
+ "batches_saved": batch_counter,
166
+ "allowed_scopes": list(ALLOWED_SCOPES)
167
+ }
168
+
169
+
170
  # Create Gradio interface
171
  with gr.Blocks(title="HuggingFace Webhook Processor") as demo:
172
  gr.Markdown("""
 
274
  outputs=[status_text, message_count, batch_count, latest_batch]
275
  )
276
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
 
278
+ # Mount Gradio on our FastAPI app
279
+ app = gr.mount_gradio_app(app, demo, path="/")
 
 
 
 
 
 
 
 
 
280
 
281
 
282
+ # Launch the app
283
  if __name__ == "__main__":
284
+ import uvicorn
285
+ uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt CHANGED
@@ -3,3 +3,5 @@ huggingface-hub
3
  datasets
4
  pandas
5
  pyarrow
 
 
 
3
  datasets
4
  pandas
5
  pyarrow
6
+ uvicorn
7
+ fastapi