LogicGoInfotechSpaces commited on
Commit
2ae242d
·
1 Parent(s): 62db9e6

feat(auth): accept Firebase Auth id_token (Authorization Bearer) in addition to App Check; add Postman collection and test script; default MODEL_ID to ControlNet color

Browse files
API_DOCUMENTATION.md ADDED
@@ -0,0 +1,494 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Colorize API Documentation
2
+
3
+ ## Base URL
4
+
5
+ ```
6
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space
7
+ ```
8
+
9
+ For local development:
10
+ ```
11
+ http://localhost:7860
12
+ ```
13
+
14
+ ## Authentication
15
+
16
+ All endpoints (except `/health` and public result endpoints) require Firebase App Check authentication.
17
+
18
+ Include the App Check token in the request header:
19
+ ```
20
+ X-Firebase-AppCheck: <your-app-check-token>
21
+ ```
22
+
23
+ ## Endpoints
24
+
25
+ ### 1. Health Check
26
+
27
+ Check the health status of the API and model.
28
+
29
+ **Endpoint:** `GET /health`
30
+
31
+ **Authentication:** Not required
32
+
33
+ **Response:**
34
+ ```json
35
+ {
36
+ "status": "healthy",
37
+ "model_loaded": true
38
+ }
39
+ ```
40
+
41
+ **Example:**
42
+ ```bash
43
+ curl https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/health
44
+ ```
45
+
46
+ **Response Codes:**
47
+ - `200 OK` - API is healthy
48
+ - `503 Service Unavailable` - Model not loaded
49
+
50
+ ---
51
+
52
+ ### 2. Upload Image
53
+
54
+ Upload an image and get the uploaded image URL.
55
+
56
+ **Endpoint:** `POST /upload`
57
+
58
+ **Authentication:** Required (Firebase App Check token)
59
+
60
+ **Request:**
61
+ - **Method:** `POST`
62
+ - **Content-Type:** `multipart/form-data`
63
+ - **Headers:**
64
+ - `X-Firebase-AppCheck: <token>`
65
+ - **Body:**
66
+ - `file`: Image file (JPEG, PNG, etc.)
67
+
68
+ **Response:**
69
+ ```json
70
+ {
71
+ "success": true,
72
+ "image_id": "550e8400-e29b-41d4-a716-446655440000",
73
+ "image_url": "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/uploads/550e8400-e29b-41d4-a716-446655440000.jpg",
74
+ "filename": "550e8400-e29b-41d4-a716-446655440000.jpg"
75
+ }
76
+ ```
77
+
78
+ **Example using cURL:**
79
+ ```bash
80
+ curl -X POST \
81
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/upload \
82
+ -H "X-Firebase-AppCheck: YOUR_APP_CHECK_TOKEN" \
83
+ -F "file=@/path/to/image.jpg"
84
+ ```
85
+
86
+ **Example using JavaScript:**
87
+ ```javascript
88
+ const formData = new FormData();
89
+ formData.append('file', imageFile);
90
+
91
+ const response = await fetch('https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/upload', {
92
+ method: 'POST',
93
+ headers: {
94
+ 'X-Firebase-AppCheck': appCheckToken
95
+ },
96
+ body: formData
97
+ });
98
+
99
+ const result = await response.json();
100
+ console.log(result.image_url);
101
+ ```
102
+
103
+ **Response Codes:**
104
+ - `200 OK` - Image uploaded successfully
105
+ - `400 Bad Request` - Invalid file type or missing file
106
+ - `401 Unauthorized` - Missing or invalid App Check token
107
+ - `500 Internal Server Error` - Server error during upload
108
+
109
+ ---
110
+
111
+ ### 3. Colorize Image
112
+
113
+ Colorize a grayscale or low-color image using ColorizeNet model.
114
+
115
+ **Endpoint:** `POST /colorize`
116
+
117
+ **Authentication:** Required (Firebase App Check token)
118
+
119
+ **Request:**
120
+ - **Method:** `POST`
121
+ - **Content-Type:** `multipart/form-data`
122
+ - **Headers:**
123
+ - `X-Firebase-AppCheck: <token>`
124
+ - **Body:**
125
+ - `file`: Image file (JPEG, PNG, etc.)
126
+
127
+ **Response:**
128
+ ```json
129
+ {
130
+ "success": true,
131
+ "result_id": "550e8400-e29b-41d4-a716-446655440000",
132
+ "download_url": "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/results/550e8400-e29b-41d4-a716-446655440000.jpg",
133
+ "api_download_url": "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/download/550e8400-e29b-41d4-a716-446655440000",
134
+ "filename": "550e8400-e29b-41d4-a716-446655440000.jpg"
135
+ }
136
+ ```
137
+
138
+ **Example using cURL:**
139
+ ```bash
140
+ curl -X POST \
141
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize \
142
+ -H "X-Firebase-AppCheck: YOUR_APP_CHECK_TOKEN" \
143
+ -F "file=@/path/to/grayscale_image.jpg"
144
+ ```
145
+
146
+ **Example using JavaScript:**
147
+ ```javascript
148
+ const formData = new FormData();
149
+ formData.append('file', imageFile);
150
+
151
+ const response = await fetch('https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize', {
152
+ method: 'POST',
153
+ headers: {
154
+ 'X-Firebase-AppCheck': appCheckToken
155
+ },
156
+ body: formData
157
+ });
158
+
159
+ const result = await response.json();
160
+ console.log('Colorized image:', result.download_url);
161
+ // Open in browser: window.open(result.download_url);
162
+ ```
163
+
164
+ **Response Codes:**
165
+ - `200 OK` - Image colorized successfully
166
+ - `400 Bad Request` - Invalid file type or missing file
167
+ - `401 Unauthorized` - Missing or invalid App Check token
168
+ - `503 Service Unavailable` - Colorization model not loaded
169
+ - `500 Internal Server Error` - Error during colorization
170
+
171
+ **Processing Time:**
172
+ - CPU: ~15-30 seconds
173
+ - GPU: ~5-15 seconds
174
+
175
+ ---
176
+
177
+ ### 4. Download Result (API)
178
+
179
+ Download the colorized image by file ID using the API endpoint.
180
+
181
+ **Endpoint:** `GET /download/{file_id}`
182
+
183
+ **Authentication:** Required (Firebase App Check token)
184
+
185
+ **Parameters:**
186
+ - `file_id` (path parameter): The result ID returned from `/colorize` endpoint
187
+
188
+ **Response:**
189
+ - **Content-Type:** `image/jpeg`
190
+ - **Body:** Image file binary data
191
+
192
+ **Example using cURL:**
193
+ ```bash
194
+ curl -X GET \
195
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/download/550e8400-e29b-41d4-a716-446655440000 \
196
+ -H "X-Firebase-AppCheck: YOUR_APP_CHECK_TOKEN" \
197
+ -o colorized_image.jpg
198
+ ```
199
+
200
+ **Example using JavaScript:**
201
+ ```javascript
202
+ const response = await fetch(
203
+ `https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/download/${fileId}`,
204
+ {
205
+ headers: {
206
+ 'X-Firebase-AppCheck': appCheckToken
207
+ }
208
+ }
209
+ );
210
+
211
+ const blob = await response.blob();
212
+ const url = URL.createObjectURL(blob);
213
+ // Use the URL to display or download the image
214
+ ```
215
+
216
+ **Response Codes:**
217
+ - `200 OK` - Image downloaded successfully
218
+ - `401 Unauthorized` - Missing or invalid App Check token
219
+ - `404 Not Found` - Result not found
220
+
221
+ ---
222
+
223
+ ### 5. Get Result (Public)
224
+
225
+ Get the colorized image directly (public endpoint, no authentication required).
226
+
227
+ **Endpoint:** `GET /results/{filename}`
228
+
229
+ **Authentication:** Not required
230
+
231
+ **Parameters:**
232
+ - `filename` (path parameter): The filename returned from `/colorize` endpoint
233
+
234
+ **Response:**
235
+ - **Content-Type:** `image/jpeg`
236
+ - **Body:** Image file binary data
237
+
238
+ **Example:**
239
+ ```bash
240
+ # Direct browser access
241
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/results/550e8400-e29b-41d4-a716-446655440000.jpg
242
+ ```
243
+
244
+ **Example using HTML:**
245
+ ```html
246
+ <img src="https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/results/550e8400-e29b-41d4-a716-446655440000.jpg" alt="Colorized Image">
247
+ ```
248
+
249
+ **Example using JavaScript:**
250
+ ```javascript
251
+ // Direct URL - can be opened in browser or used in img tag
252
+ const imageUrl = `https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/results/${filename}`;
253
+ window.open(imageUrl); // Opens in new tab
254
+ ```
255
+
256
+ **Response Codes:**
257
+ - `200 OK` - Image retrieved successfully
258
+ - `404 Not Found` - File not found
259
+
260
+ ---
261
+
262
+ ### 6. Get Uploaded File (Public)
263
+
264
+ Get an uploaded image directly (public endpoint, no authentication required).
265
+
266
+ **Endpoint:** `GET /uploads/{filename}`
267
+
268
+ **Authentication:** Not required
269
+
270
+ **Parameters:**
271
+ - `filename` (path parameter): The filename returned from `/upload` endpoint
272
+
273
+ **Response:**
274
+ - **Content-Type:** `image/jpeg`
275
+ - **Body:** Image file binary data
276
+
277
+ **Example:**
278
+ ```bash
279
+ # Direct browser access
280
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/uploads/550e8400-e29b-41d4-a716-446655440000.jpg
281
+ ```
282
+
283
+ **Response Codes:**
284
+ - `200 OK` - Image retrieved successfully
285
+ - `404 Not Found` - File not found
286
+
287
+ ---
288
+
289
+ ## Firebase App Check Integration
290
+
291
+ ### Frontend Setup
292
+
293
+ ```javascript
294
+ import { initializeApp } from "firebase/app";
295
+ import { initializeAppCheck, ReCaptchaEnterpriseProvider } from "firebase/app-check";
296
+
297
+ const firebaseConfig = {
298
+ apiKey: "AIzaSyBIB6rcfyyqy5niERTXWvVD714Ter4Vx68",
299
+ authDomain: "colorize-662df.firebaseapp.com",
300
+ projectId: "colorize-662df",
301
+ storageBucket: "colorize-662df.firebasestorage.app",
302
+ messagingSenderId: "69166278311",
303
+ appId: "1:69166278311:web:0e8c50b8dd8627aaeadd82",
304
+ measurementId: "G-58CC2J8XKX"
305
+ };
306
+
307
+ const app = initializeApp(firebaseConfig);
308
+
309
+ // Initialize App Check
310
+ const appCheck = initializeAppCheck(app, {
311
+ provider: new ReCaptchaEnterpriseProvider('YOUR_RECAPTCHA_SITE_KEY'),
312
+ isTokenAutoRefreshEnabled: true
313
+ });
314
+
315
+ // Get token for API requests
316
+ async function getAppCheckToken() {
317
+ const { getToken } = await import('firebase/app-check');
318
+ try {
319
+ const token = await getToken(appCheck);
320
+ return token.token;
321
+ } catch (error) {
322
+ console.error('Error getting App Check token:', error);
323
+ return null;
324
+ }
325
+ }
326
+ ```
327
+
328
+ ### Using the Token
329
+
330
+ ```javascript
331
+ async function colorizeImage(imageFile) {
332
+ const token = await getAppCheckToken();
333
+
334
+ if (!token) {
335
+ throw new Error('Failed to get App Check token');
336
+ }
337
+
338
+ const formData = new FormData();
339
+ formData.append('file', imageFile);
340
+
341
+ const response = await fetch(
342
+ 'https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize',
343
+ {
344
+ method: 'POST',
345
+ headers: {
346
+ 'X-Firebase-AppCheck': token
347
+ },
348
+ body: formData
349
+ }
350
+ );
351
+
352
+ if (!response.ok) {
353
+ const error = await response.json();
354
+ throw new Error(error.detail || 'Colorization failed');
355
+ }
356
+
357
+ return await response.json();
358
+ }
359
+ ```
360
+
361
+ ---
362
+
363
+ ## Error Responses
364
+
365
+ All error responses follow this format:
366
+
367
+ ```json
368
+ {
369
+ "detail": "Error message description"
370
+ }
371
+ ```
372
+
373
+ ### Common Error Codes
374
+
375
+ - `400 Bad Request` - Invalid request (missing file, wrong file type, etc.)
376
+ - `401 Unauthorized` - Missing or invalid Firebase App Check token
377
+ - `404 Not Found` - Resource not found (file, result, etc.)
378
+ - `500 Internal Server Error` - Server error during processing
379
+ - `503 Service Unavailable` - Model not loaded or service unavailable
380
+
381
+ ---
382
+
383
+ ## Complete Example: Colorize Image Workflow
384
+
385
+ ### Step 1: Get App Check Token
386
+
387
+ ```javascript
388
+ const token = await getAppCheckToken();
389
+ ```
390
+
391
+ ### Step 2: Upload and Colorize
392
+
393
+ ```javascript
394
+ const formData = new FormData();
395
+ formData.append('file', imageFile);
396
+
397
+ const response = await fetch(
398
+ 'https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize',
399
+ {
400
+ method: 'POST',
401
+ headers: {
402
+ 'X-Firebase-AppCheck': token
403
+ },
404
+ body: formData
405
+ }
406
+ );
407
+
408
+ const result = await response.json();
409
+ ```
410
+
411
+ ### Step 3: Display Result
412
+
413
+ ```javascript
414
+ // Option 1: Use the public URL (no auth needed)
415
+ const imageUrl = result.download_url;
416
+ document.getElementById('result-image').src = imageUrl;
417
+
418
+ // Option 2: Download via API (requires auth)
419
+ const downloadResponse = await fetch(
420
+ `https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/download/${result.result_id}`,
421
+ {
422
+ headers: {
423
+ 'X-Firebase-AppCheck': token
424
+ }
425
+ }
426
+ );
427
+ const blob = await downloadResponse.blob();
428
+ const url = URL.createObjectURL(blob);
429
+ document.getElementById('result-image').src = url;
430
+ ```
431
+
432
+ ---
433
+
434
+ ## Rate Limits
435
+
436
+ - No explicit rate limits set
437
+ - Processing time: 15-30 seconds (CPU) or 5-15 seconds (GPU)
438
+ - Concurrent requests may be queued
439
+
440
+ ## Supported Image Formats
441
+
442
+ - JPEG (.jpg, .jpeg)
443
+ - PNG (.png)
444
+ - Other formats supported by PIL/Pillow
445
+
446
+ ## Image Size Recommendations
447
+
448
+ - Maximum recommended: 2048x2048 pixels
449
+ - Images are automatically resized to 512x512 for processing
450
+ - Original aspect ratio is preserved in the output
451
+
452
+ ---
453
+
454
+ ## Testing
455
+
456
+ ### Test Health Endpoint
457
+
458
+ ```bash
459
+ curl https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/health
460
+ ```
461
+
462
+ ### Test Colorize Endpoint (with token)
463
+
464
+ ```bash
465
+ curl -X POST \
466
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize \
467
+ -H "X-Firebase-AppCheck: YOUR_TOKEN" \
468
+ -F "file=@test_image.jpg" \
469
+ -o response.json
470
+
471
+ cat response.json
472
+ ```
473
+
474
+ ---
475
+
476
+ ## Support
477
+
478
+ For issues or questions:
479
+ 1. Check the health endpoint to verify API status
480
+ 2. Verify your Firebase App Check token is valid
481
+ 3. Check the build logs in Hugging Face Spaces
482
+ 4. Ensure the model is loaded (check `/health` endpoint)
483
+
484
+ ---
485
+
486
+ ## Changelog
487
+
488
+ ### Version 1.0.0
489
+ - Initial release
490
+ - Image upload endpoint
491
+ - Image colorization endpoint
492
+ - Firebase App Check integration
493
+ - Public result URLs
494
+
API_EXAMPLES.md ADDED
@@ -0,0 +1,541 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # API Usage Examples
2
+
3
+ ## Python Examples
4
+
5
+ ### Example 1: Colorize Image with Requests
6
+
7
+ ```python
8
+ import requests
9
+
10
+ # Your Firebase App Check token
11
+ APP_CHECK_TOKEN = "your-app-check-token-here"
12
+ API_BASE_URL = "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space"
13
+
14
+ # Colorize an image
15
+ def colorize_image(image_path):
16
+ url = f"{API_BASE_URL}/colorize"
17
+ headers = {
18
+ "X-Firebase-AppCheck": APP_CHECK_TOKEN
19
+ }
20
+
21
+ with open(image_path, "rb") as f:
22
+ files = {"file": f}
23
+ response = requests.post(url, headers=headers, files=files)
24
+
25
+ if response.status_code == 200:
26
+ result = response.json()
27
+ print(f"Success! Download URL: {result['download_url']}")
28
+ return result
29
+ else:
30
+ print(f"Error: {response.status_code} - {response.text}")
31
+ return None
32
+
33
+ # Usage
34
+ result = colorize_image("grayscale_image.jpg")
35
+ if result:
36
+ print(f"Colorized image available at: {result['download_url']}")
37
+ ```
38
+
39
+ ### Example 2: Upload and Colorize
40
+
41
+ ```python
42
+ import requests
43
+
44
+ APP_CHECK_TOKEN = "your-app-check-token-here"
45
+ API_BASE_URL = "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space"
46
+
47
+ def upload_and_colorize(image_path):
48
+ headers = {"X-Firebase-AppCheck": APP_CHECK_TOKEN}
49
+
50
+ # Step 1: Upload image
51
+ with open(image_path, "rb") as f:
52
+ files = {"file": f}
53
+ upload_response = requests.post(
54
+ f"{API_BASE_URL}/upload",
55
+ headers=headers,
56
+ files=files
57
+ )
58
+
59
+ if upload_response.status_code != 200:
60
+ print(f"Upload failed: {upload_response.text}")
61
+ return None
62
+
63
+ upload_result = upload_response.json()
64
+ print(f"Image uploaded: {upload_result['image_url']}")
65
+
66
+ # Step 2: Colorize the uploaded image
67
+ with open(image_path, "rb") as f:
68
+ files = {"file": f}
69
+ colorize_response = requests.post(
70
+ f"{API_BASE_URL}/colorize",
71
+ headers=headers,
72
+ files=files
73
+ )
74
+
75
+ if colorize_response.status_code == 200:
76
+ result = colorize_response.json()
77
+ print(f"Colorized image: {result['download_url']}")
78
+ return result
79
+ else:
80
+ print(f"Colorization failed: {colorize_response.text}")
81
+ return None
82
+
83
+ # Usage
84
+ result = upload_and_colorize("my_image.jpg")
85
+ ```
86
+
87
+ ### Example 3: Download Result
88
+
89
+ ```python
90
+ import requests
91
+
92
+ APP_CHECK_TOKEN = "your-app-check-token-here"
93
+ API_BASE_URL = "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space"
94
+
95
+ def download_colorized_image(result_id, output_path):
96
+ url = f"{API_BASE_URL}/download/{result_id}"
97
+ headers = {"X-Firebase-AppCheck": APP_CHECK_TOKEN}
98
+
99
+ response = requests.get(url, headers=headers)
100
+
101
+ if response.status_code == 200:
102
+ with open(output_path, "wb") as f:
103
+ f.write(response.content)
104
+ print(f"Image saved to: {output_path}")
105
+ return True
106
+ else:
107
+ print(f"Download failed: {response.status_code}")
108
+ return False
109
+
110
+ # Usage
111
+ result = colorize_image("input.jpg")
112
+ if result:
113
+ download_colorized_image(result["result_id"], "colorized_output.jpg")
114
+ ```
115
+
116
+ ---
117
+
118
+ ## JavaScript/TypeScript Examples
119
+
120
+ ### Example 1: Colorize Image with Fetch
121
+
122
+ ```javascript
123
+ const API_BASE_URL = 'https://logicgoinfotechspaces-text-guided-image-colorization.hf.space';
124
+
125
+ async function colorizeImage(imageFile, appCheckToken) {
126
+ const formData = new FormData();
127
+ formData.append('file', imageFile);
128
+
129
+ try {
130
+ const response = await fetch(`${API_BASE_URL}/colorize`, {
131
+ method: 'POST',
132
+ headers: {
133
+ 'X-Firebase-AppCheck': appCheckToken
134
+ },
135
+ body: formData
136
+ });
137
+
138
+ if (!response.ok) {
139
+ const error = await response.json();
140
+ throw new Error(error.detail || 'Colorization failed');
141
+ }
142
+
143
+ const result = await response.json();
144
+ console.log('Colorized image URL:', result.download_url);
145
+ return result;
146
+ } catch (error) {
147
+ console.error('Error:', error);
148
+ throw error;
149
+ }
150
+ }
151
+
152
+ // Usage
153
+ const fileInput = document.getElementById('image-input');
154
+ const file = fileInput.files[0];
155
+
156
+ colorizeImage(file, appCheckToken)
157
+ .then(result => {
158
+ // Display the image
159
+ const img = document.createElement('img');
160
+ img.src = result.download_url;
161
+ document.body.appendChild(img);
162
+ })
163
+ .catch(error => {
164
+ console.error('Failed to colorize:', error);
165
+ });
166
+ ```
167
+
168
+ ### Example 2: Complete Workflow with Firebase App Check
169
+
170
+ ```javascript
171
+ import { initializeApp } from "firebase/app";
172
+ import { initializeAppCheck, ReCaptchaEnterpriseProvider } from "firebase/app-check";
173
+
174
+ // Initialize Firebase
175
+ const firebaseConfig = {
176
+ apiKey: "AIzaSyBIB6rcfyyqy5niERTXWvVD714Ter4Vx68",
177
+ authDomain: "colorize-662df.firebaseapp.com",
178
+ projectId: "colorize-662df",
179
+ storageBucket: "colorize-662df.firebasestorage.app",
180
+ messagingSenderId: "69166278311",
181
+ appId: "1:69166278311:web:0e8c50b8dd8627aaeadd82",
182
+ measurementId: "G-58CC2J8XKX"
183
+ };
184
+
185
+ const app = initializeApp(firebaseConfig);
186
+ const appCheck = initializeAppCheck(app, {
187
+ provider: new ReCaptchaEnterpriseProvider('YOUR_RECAPTCHA_SITE_KEY'),
188
+ isTokenAutoRefreshEnabled: true
189
+ });
190
+
191
+ // Get App Check token
192
+ async function getAppCheckToken() {
193
+ const { getToken } = await import('firebase/app-check');
194
+ try {
195
+ const token = await getToken(appCheck);
196
+ return token.token;
197
+ } catch (error) {
198
+ console.error('Error getting App Check token:', error);
199
+ return null;
200
+ }
201
+ }
202
+
203
+ // Colorize image function
204
+ async function colorizeImageWithAppCheck(imageFile) {
205
+ const token = await getAppCheckToken();
206
+
207
+ if (!token) {
208
+ throw new Error('Failed to get App Check token');
209
+ }
210
+
211
+ const formData = new FormData();
212
+ formData.append('file', imageFile);
213
+
214
+ const response = await fetch(
215
+ 'https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize',
216
+ {
217
+ method: 'POST',
218
+ headers: {
219
+ 'X-Firebase-AppCheck': token
220
+ },
221
+ body: formData
222
+ }
223
+ );
224
+
225
+ if (!response.ok) {
226
+ const error = await response.json();
227
+ throw new Error(error.detail || 'Colorization failed');
228
+ }
229
+
230
+ return await response.json();
231
+ }
232
+
233
+ // Usage in HTML form
234
+ document.getElementById('colorize-form').addEventListener('submit', async (e) => {
235
+ e.preventDefault();
236
+
237
+ const fileInput = document.getElementById('image-input');
238
+ const file = fileInput.files[0];
239
+
240
+ if (!file) {
241
+ alert('Please select an image');
242
+ return;
243
+ }
244
+
245
+ try {
246
+ const result = await colorizeImageWithAppCheck(file);
247
+
248
+ // Display result
249
+ const resultImg = document.getElementById('result-image');
250
+ resultImg.src = result.download_url;
251
+ resultImg.style.display = 'block';
252
+
253
+ console.log('Colorized image:', result.download_url);
254
+ } catch (error) {
255
+ console.error('Error:', error);
256
+ alert('Failed to colorize image: ' + error.message);
257
+ }
258
+ });
259
+ ```
260
+
261
+ ### Example 3: React Component
262
+
263
+ ```jsx
264
+ import React, { useState } from 'react';
265
+ import { getToken } from 'firebase/app-check';
266
+
267
+ function ColorizeImage() {
268
+ const [file, setFile] = useState(null);
269
+ const [loading, setLoading] = useState(false);
270
+ const [result, setResult] = useState(null);
271
+ const [error, setError] = useState(null);
272
+
273
+ const handleFileChange = (e) => {
274
+ setFile(e.target.files[0]);
275
+ setResult(null);
276
+ setError(null);
277
+ };
278
+
279
+ const handleColorize = async () => {
280
+ if (!file) {
281
+ setError('Please select an image');
282
+ return;
283
+ }
284
+
285
+ setLoading(true);
286
+ setError(null);
287
+
288
+ try {
289
+ // Get App Check token
290
+ const token = await getToken(appCheck);
291
+
292
+ const formData = new FormData();
293
+ formData.append('file', file);
294
+
295
+ const response = await fetch(
296
+ 'https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize',
297
+ {
298
+ method: 'POST',
299
+ headers: {
300
+ 'X-Firebase-AppCheck': token.token
301
+ },
302
+ body: formData
303
+ }
304
+ );
305
+
306
+ if (!response.ok) {
307
+ const errorData = await response.json();
308
+ throw new Error(errorData.detail || 'Colorization failed');
309
+ }
310
+
311
+ const data = await response.json();
312
+ setResult(data);
313
+ } catch (err) {
314
+ setError(err.message);
315
+ } finally {
316
+ setLoading(false);
317
+ }
318
+ };
319
+
320
+ return (
321
+ <div>
322
+ <input type="file" accept="image/*" onChange={handleFileChange} />
323
+ <button onClick={handleColorize} disabled={loading || !file}>
324
+ {loading ? 'Colorizing...' : 'Colorize Image'}
325
+ </button>
326
+
327
+ {error && <div className="error">{error}</div>}
328
+
329
+ {result && (
330
+ <div>
331
+ <h3>Colorized Image:</h3>
332
+ <img src={result.download_url} alt="Colorized" />
333
+ <a href={result.download_url} download>Download</a>
334
+ </div>
335
+ )}
336
+ </div>
337
+ );
338
+ }
339
+
340
+ export default ColorizeImage;
341
+ ```
342
+
343
+ ---
344
+
345
+ ## cURL Examples
346
+
347
+ ### Health Check
348
+
349
+ ```bash
350
+ curl https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/health
351
+ ```
352
+
353
+ ### Upload Image
354
+
355
+ ```bash
356
+ curl -X POST \
357
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/upload \
358
+ -H "X-Firebase-AppCheck: YOUR_TOKEN" \
359
+ -F "file=@image.jpg"
360
+ ```
361
+
362
+ ### Colorize Image
363
+
364
+ ```bash
365
+ curl -X POST \
366
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize \
367
+ -H "X-Firebase-AppCheck: YOUR_TOKEN" \
368
+ -F "file=@grayscale_image.jpg" \
369
+ -o response.json
370
+ ```
371
+
372
+ ### Download Result
373
+
374
+ ```bash
375
+ # Get result ID from colorize response first
376
+ RESULT_ID="550e8400-e29b-41d4-a716-446655440000"
377
+
378
+ curl -X GET \
379
+ https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/download/${RESULT_ID} \
380
+ -H "X-Firebase-AppCheck: YOUR_TOKEN" \
381
+ -o colorized_image.jpg
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Postman Collection
387
+
388
+ ### Collection JSON
389
+
390
+ ```json
391
+ {
392
+ "info": {
393
+ "name": "Colorize API",
394
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
395
+ },
396
+ "item": [
397
+ {
398
+ "name": "Health Check",
399
+ "request": {
400
+ "method": "GET",
401
+ "header": [],
402
+ "url": {
403
+ "raw": "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/health",
404
+ "protocol": "https",
405
+ "host": ["logicgoinfotechspaces-text-guided-image-colorization", "hf", "space"],
406
+ "path": ["health"]
407
+ }
408
+ }
409
+ },
410
+ {
411
+ "name": "Colorize Image",
412
+ "request": {
413
+ "method": "POST",
414
+ "header": [
415
+ {
416
+ "key": "X-Firebase-AppCheck",
417
+ "value": "{{app_check_token}}",
418
+ "type": "text"
419
+ }
420
+ ],
421
+ "body": {
422
+ "mode": "formdata",
423
+ "formdata": [
424
+ {
425
+ "key": "file",
426
+ "type": "file",
427
+ "src": []
428
+ }
429
+ ]
430
+ },
431
+ "url": {
432
+ "raw": "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize",
433
+ "protocol": "https",
434
+ "host": ["logicgoinfotechspaces-text-guided-image-colorization", "hf", "space"],
435
+ "path": ["colorize"]
436
+ }
437
+ }
438
+ }
439
+ ],
440
+ "variable": [
441
+ {
442
+ "key": "app_check_token",
443
+ "value": "your-token-here"
444
+ }
445
+ ]
446
+ }
447
+ ```
448
+
449
+ ---
450
+
451
+ ## Error Handling Examples
452
+
453
+ ### Python
454
+
455
+ ```python
456
+ import requests
457
+
458
+ def colorize_with_error_handling(image_path, token):
459
+ url = "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize"
460
+ headers = {"X-Firebase-AppCheck": token}
461
+
462
+ try:
463
+ with open(image_path, "rb") as f:
464
+ files = {"file": f}
465
+ response = requests.post(url, headers=headers, files=files, timeout=120)
466
+
467
+ if response.status_code == 200:
468
+ return response.json()
469
+ elif response.status_code == 401:
470
+ raise Exception("Invalid or missing App Check token")
471
+ elif response.status_code == 400:
472
+ raise Exception("Invalid file or request")
473
+ elif response.status_code == 503:
474
+ raise Exception("Model not loaded, please try again later")
475
+ else:
476
+ error = response.json()
477
+ raise Exception(f"Error {response.status_code}: {error.get('detail', 'Unknown error')}")
478
+
479
+ except requests.exceptions.Timeout:
480
+ raise Exception("Request timed out. Image processing may take 30-60 seconds.")
481
+ except requests.exceptions.RequestException as e:
482
+ raise Exception(f"Network error: {str(e)}")
483
+ ```
484
+
485
+ ### JavaScript
486
+
487
+ ```javascript
488
+ async function colorizeWithErrorHandling(imageFile, token) {
489
+ try {
490
+ const formData = new FormData();
491
+ formData.append('file', imageFile);
492
+
493
+ const response = await fetch(
494
+ 'https://logicgoinfotechspaces-text-guided-image-colorization.hf.space/colorize',
495
+ {
496
+ method: 'POST',
497
+ headers: {
498
+ 'X-Firebase-AppCheck': token
499
+ },
500
+ body: formData,
501
+ signal: AbortSignal.timeout(120000) // 120 second timeout
502
+ }
503
+ );
504
+
505
+ if (!response.ok) {
506
+ const error = await response.json();
507
+
508
+ switch (response.status) {
509
+ case 401:
510
+ throw new Error('Invalid or missing App Check token');
511
+ case 400:
512
+ throw new Error('Invalid file or request');
513
+ case 503:
514
+ throw new Error('Model not loaded, please try again later');
515
+ default:
516
+ throw new Error(error.detail || `Error ${response.status}: ${response.statusText}`);
517
+ }
518
+ }
519
+
520
+ return await response.json();
521
+ } catch (error) {
522
+ if (error.name === 'AbortError') {
523
+ throw new Error('Request timed out. Image processing may take 30-60 seconds.');
524
+ }
525
+ throw error;
526
+ }
527
+ }
528
+ ```
529
+
530
+ ---
531
+
532
+ ## Best Practices
533
+
534
+ 1. **Always check health endpoint first** before making requests
535
+ 2. **Handle timeouts** - Processing can take 30-60 seconds on CPU
536
+ 3. **Cache App Check tokens** - They auto-refresh, but cache them to avoid unnecessary requests
537
+ 4. **Use public URLs** for displaying images (no auth needed)
538
+ 5. **Handle errors gracefully** - Show user-friendly error messages
539
+ 6. **Validate file types** before uploading
540
+ 7. **Show loading indicators** during processing
541
+
app/colorize_model.py CHANGED
@@ -5,24 +5,26 @@ import logging
5
  import torch
6
  import numpy as np
7
  from PIL import Image
8
- import cv2
9
  from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, StableDiffusionXLControlNetPipeline
10
  from diffusers.utils import load_image
11
  from transformers import pipeline
12
  from huggingface_hub import hf_hub_download
 
13
 
14
  logger = logging.getLogger(__name__)
15
 
16
  class ColorizeModel:
17
  """Wrapper for ColorizeNet model"""
18
 
19
- def __init__(self, model_id: str = "rsortino/ColorizeNet"):
20
  """
21
  Initialize the ColorizeNet model
22
 
23
  Args:
24
  model_id: Hugging Face model ID for ColorizeNet
25
  """
 
 
26
  self.model_id = model_id
27
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
28
  logger.info("Using device: %s", self.device)
@@ -30,11 +32,11 @@ class ColorizeModel:
30
 
31
  try:
32
  # Try loading as ControlNet with Stable Diffusion
33
- logger.info("Attempting to load ColorizeNet as ControlNet...")
34
  try:
35
  # Load ControlNet model
36
  self.controlnet = ControlNetModel.from_pretrained(
37
- model_id,
38
  torch_dtype=self.dtype
39
  )
40
 
@@ -77,7 +79,7 @@ class ColorizeModel:
77
  logger.info("Trying to load as image-to-image pipeline...")
78
  self.pipe = pipeline(
79
  "image-to-image",
80
- model=model_id,
81
  device=0 if self.device == "cuda" else -1,
82
  torch_dtype=self.dtype
83
  )
 
5
  import torch
6
  import numpy as np
7
  from PIL import Image
 
8
  from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, StableDiffusionXLControlNetPipeline
9
  from diffusers.utils import load_image
10
  from transformers import pipeline
11
  from huggingface_hub import hf_hub_download
12
+ from app.config import settings
13
 
14
  logger = logging.getLogger(__name__)
15
 
16
  class ColorizeModel:
17
  """Wrapper for ColorizeNet model"""
18
 
19
+ def __init__(self, model_id: str | None = None):
20
  """
21
  Initialize the ColorizeNet model
22
 
23
  Args:
24
  model_id: Hugging Face model ID for ColorizeNet
25
  """
26
+ if model_id is None:
27
+ model_id = settings.MODEL_ID
28
  self.model_id = model_id
29
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
30
  logger.info("Using device: %s", self.device)
 
32
 
33
  try:
34
  # Try loading as ControlNet with Stable Diffusion
35
+ logger.info("Attempting to load model as ControlNet: %s", self.model_id)
36
  try:
37
  # Load ControlNet model
38
  self.controlnet = ControlNetModel.from_pretrained(
39
+ self.model_id,
40
  torch_dtype=self.dtype
41
  )
42
 
 
79
  logger.info("Trying to load as image-to-image pipeline...")
80
  self.pipe = pipeline(
81
  "image-to-image",
82
+ model=self.model_id,
83
  device=0 if self.device == "cuda" else -1,
84
  torch_dtype=self.dtype
85
  )
app/config.py CHANGED
@@ -18,7 +18,7 @@ class Settings(BaseSettings):
18
  BASE_URL: str = os.getenv("BASE_URL", "http://localhost:8000")
19
 
20
  # Model settings
21
- MODEL_ID: str = os.getenv("MODEL_ID", "rsortino/ColorizeNet")
22
  NUM_INFERENCE_STEPS: int = int(os.getenv("NUM_INFERENCE_STEPS", "20"))
23
 
24
  # Storage settings
 
18
  BASE_URL: str = os.getenv("BASE_URL", "http://localhost:8000")
19
 
20
  # Model settings
21
+ MODEL_ID: str = os.getenv("MODEL_ID", "lllyasviel/control_v11f1e_sd15_color")
22
  NUM_INFERENCE_STEPS: int = int(os.getenv("NUM_INFERENCE_STEPS", "20"))
23
 
24
  # Storage settings
app/main.py CHANGED
@@ -12,7 +12,7 @@ from fastapi.responses import FileResponse, JSONResponse
12
  from fastapi.middleware.cors import CORSMiddleware
13
  from fastapi.staticfiles import StaticFiles
14
  import firebase_admin
15
- from firebase_admin import credentials, app_check
16
  import numpy as np
17
  import torch
18
  from PIL import Image
@@ -80,7 +80,7 @@ async def startup_event():
80
  global colorize_model
81
  try:
82
  logger.info("Loading ColorizeNet model...")
83
- colorize_model = ColorizeModel()
84
  logger.info("ColorizeNet model loaded successfully")
85
  except Exception as e:
86
  logger.error("Failed to load ColorizeNet model: %s", str(e))
@@ -94,30 +94,48 @@ async def shutdown_event():
94
  del colorize_model
95
  logger.info("Application shutdown")
96
 
97
- # Firebase App Check verification
98
- async def verify_app_check(request: Request):
99
- """Verify Firebase App Check token"""
100
- if not settings.ENABLE_APP_CHECK:
101
- return True
102
-
103
- app_check_token = request.headers.get("X-Firebase-AppCheck")
104
- if not app_check_token:
105
- raise HTTPException(
106
- status_code=401,
107
- detail="Missing App Check token"
108
- )
109
-
110
- try:
111
- # Verify the App Check token
112
- app_check_claims = app_check.verify_token(app_check_token)
113
- logger.info("App Check token verified for: %s", app_check_claims.get("app_id"))
114
- return True
115
- except Exception as e:
116
- logger.warning("App Check token verification failed: %s", str(e))
117
- raise HTTPException(
118
- status_code=401,
119
- detail="Invalid App Check token"
120
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  @app.get("/health")
123
  async def health_check():
@@ -130,7 +148,7 @@ async def health_check():
130
  @app.post("/upload")
131
  async def upload_image(
132
  file: UploadFile = File(...),
133
- verified: bool = Depends(verify_app_check)
134
  ):
135
  """
136
  Upload an image and return the uploaded image URL
@@ -168,7 +186,7 @@ async def upload_image(
168
  @app.post("/colorize")
169
  async def colorize_image(
170
  file: UploadFile = File(...),
171
- verified: bool = Depends(verify_app_check)
172
  ):
173
  """
174
  Colorize an uploaded grayscale image using ColorizeNet
@@ -220,7 +238,7 @@ async def colorize_image(
220
  @app.get("/download/{file_id}")
221
  async def download_result(
222
  file_id: str,
223
- verified: bool = Depends(verify_app_check)
224
  ):
225
  """
226
  Download the colorized image by file ID
 
12
  from fastapi.middleware.cors import CORSMiddleware
13
  from fastapi.staticfiles import StaticFiles
14
  import firebase_admin
15
+ from firebase_admin import credentials, app_check, auth as firebase_auth
16
  import numpy as np
17
  import torch
18
  from PIL import Image
 
80
  global colorize_model
81
  try:
82
  logger.info("Loading ColorizeNet model...")
83
+ colorize_model = ColorizeModel(settings.MODEL_ID)
84
  logger.info("ColorizeNet model loaded successfully")
85
  except Exception as e:
86
  logger.error("Failed to load ColorizeNet model: %s", str(e))
 
94
  del colorize_model
95
  logger.info("Application shutdown")
96
 
97
+ def _extract_bearer_token(authorization_header: str | None) -> str | None:
98
+ if not authorization_header:
99
+ return None
100
+ parts = authorization_header.split(" ", 1)
101
+ if len(parts) == 2 and parts[0].lower() == "bearer":
102
+ return parts[1].strip()
103
+ return None
104
+
105
+
106
+ async def verify_request(request: Request):
107
+ """
108
+ Accept either:
109
+ - Firebase Auth id_token via Authorization: Bearer <id_token>
110
+ - Firebase App Check token via X-Firebase-AppCheck (when ENABLE_APP_CHECK=true)
111
+ """
112
+ # Try Firebase Auth id_token first if present
113
+ bearer = _extract_bearer_token(request.headers.get("Authorization"))
114
+ if bearer:
115
+ try:
116
+ decoded = firebase_auth.verify_id_token(bearer)
117
+ request.state.user = decoded # make claims available if needed
118
+ logger.info("Firebase Auth id_token verified for uid: %s", decoded.get("uid"))
119
+ return True
120
+ except Exception as e:
121
+ logger.warning("Auth token verification failed: %s", str(e))
122
+ # fall through to App Check if enabled
123
+
124
+ # If App Check is enabled, require valid App Check token
125
+ if settings.ENABLE_APP_CHECK:
126
+ app_check_token = request.headers.get("X-Firebase-AppCheck")
127
+ if not app_check_token:
128
+ raise HTTPException(status_code=401, detail="Missing App Check token")
129
+ try:
130
+ app_check_claims = app_check.verify_token(app_check_token)
131
+ logger.info("App Check token verified for: %s", app_check_claims.get("app_id"))
132
+ return True
133
+ except Exception as e:
134
+ logger.warning("App Check token verification failed: %s", str(e))
135
+ raise HTTPException(status_code=401, detail="Invalid App Check token")
136
+
137
+ # Neither token required nor provided → allow (App Check disabled)
138
+ return True
139
 
140
  @app.get("/health")
141
  async def health_check():
 
148
  @app.post("/upload")
149
  async def upload_image(
150
  file: UploadFile = File(...),
151
+ verified: bool = Depends(verify_request)
152
  ):
153
  """
154
  Upload an image and return the uploaded image URL
 
186
  @app.post("/colorize")
187
  async def colorize_image(
188
  file: UploadFile = File(...),
189
+ verified: bool = Depends(verify_request)
190
  ):
191
  """
192
  Colorize an uploaded grayscale image using ColorizeNet
 
238
  @app.get("/download/{file_id}")
239
  async def download_result(
240
  file_id: str,
241
+ verified: bool = Depends(verify_request)
242
  ):
243
  """
244
  Download the colorized image by file ID
colorize-662df-firebase-adminsdk-fbsvc-bfd21c77c6.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "colorize-662df",
4
+ "private_key_id": "bfd21c77c6a80346288f28b68da364de7dbc3dc2",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5DYGbqOMFKGrO\n1MToTx/5H2mtT1QxPV+tKbcg9hfmwa+HMun6bk4ME1+ZXfrXaWZ6JQ/q6JhX0SqB\nc7H7Bns2kyUNH7E6IiBSa03izNFJiEW9OSCn613cKh/XtKqNFm5GrSBo++o0aSWw\nEWX2ABeJ1vQBOaMbkjktXJP24XThHV9UotwyTmGiVBXld/K084NdCknknUMNuXaN\nEGogcZ+FGoTPenfft81COOIIao1d4Q3PxUCVYqPzRd/PECjhTxbba9qdg6bd2p12\n4PSy4OKUgkeIYutnF/W6BtMszIuNM5F85bttGPUMog4Kr3HAXKk0ZYRXHJtD7EOo\nnG7BTk/5AgMBAAECggEACw5TBYVIFvlMtFHC9+wuSViGnEumiJCVpEdfQRFi6S7+\nOTIiB4vKju8jYYrbXz5VWIvZURwXafu9seFDK2++McsFxix0DriWPMZbb2b0RBPn\nsr/0gwPNZkeAAoexPt+ts/xI+OzAF+SGU2gest1biqk0h9Q1OgL49oxW7MOYk5Bv\nKNwhlfWD00O2IGOSbn+2aPl3qpCC5U9sTd3xHC2yI0MqD5qSvwn/bnrJoahGFS5W\nO3I7chJqcv3UVffvvuFsR0aaAuJagUkhSzlnbEPTCm5DL+oUHkbsP5t1T6jJ0a0P\n6o185AbjjdDE9ckWKCIUT5FXfxuZOnHOgtt9grT49wKBgQDhlQ3QVsQr9qmpcGHG\n3IdNLvJJ+jybV1EW+dQ9DtOt2plPVKRsiVsUPs+BlAB9tpVVI9y0BPe9B3ABFgwz\n6yX/l1OUZ4NomjjjdcVrCk2HB5mtic33M3zfJuZNtqtWwz33Dg95J0jiIqjYGRaS\n/ZfNCMi8SyjPmVHSjoFzuvWLnwKBgQDSAWbsZ0C8PUzFsjR8t5/mwyu8Ty8IjcCh\nZSAQSxEoXDDmUYGloSzM26VCODRVtl8UcrwhMDfe4qnx9T8UhRr9qAFOg+lVmJ5S\nUb4IdEmFtGEGpXuNGts5txK7MnQkxdkfrBr6ava1eIx2u583RccFcu7tvgMB5bSh\nPpaG5Rn9ZwKBgHuC7BRVXYWgwZZnVPHYDzDgcoK0w3heX6TP1zgzJQ18shJwirJu\npnK4TU9qZLZwQOVkBFSAn9BdASNnGflXV+/QwE9yOc4NGvbXpecMthQnwin1WNNv\n2oAoQVLtoHSZ5BSgGzK/orVGOuJPIkALH5GArMAD+u1nyhgaNKDUDduLAoGBAMW6\nwDfSOCeE6CY0VisfkZTrKuDRBY3eOgM8feYZZ/xCYWBaWeGjUdVI8d7ZoJ0ba4aL\nSQtOpSxc6nqA2XXupa0zZJeSqD4JxvfnMzAunZMgdUKWyS/gm41KDH7pUGXXS0oA\n+B3UXJoc+NRKb+zQ7ET7JHAAukAtEdfIYF5+k+v9AoGAQKJuKD9+yEWjHnEgQkjM\nuSQno7dELoZ6zqVjtQIGz167xvlbRxewPREy2U1xWe9OEUu1EqhdDaiKAXJoQVpx\nEa8wDj1B9eLIR2uO29fIUVtwvFPW+zJJnnhP8S5+XDG8ukrP/FkmX3J4Af9i6ENY\nARf26WMuj3nc6Meclk4fbK0=\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "firebase-adminsdk-fbsvc@colorize-662df.iam.gserviceaccount.com",
7
+ "client_id": "107752682517402248855",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40colorize-662df.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
postman_collection.json ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "info": {
3
+ "name": "Colorize API",
4
+ "_postman_id": "f3f5d3cc-6a2b-4d2e-9b1e-collection-colorize",
5
+ "description": "Postman collection for the Colorize Image API (FastAPI). Import this file into Postman.",
6
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
7
+ },
8
+ "item": [
9
+ {
10
+ "name": "Health",
11
+ "request": {
12
+ "method": "GET",
13
+ "header": [],
14
+ "url": {
15
+ "raw": "{{base_url}}/health",
16
+ "host": [
17
+ "{{base_url}}"
18
+ ],
19
+ "path": [
20
+ "health"
21
+ ]
22
+ }
23
+ }
24
+ },
25
+ {
26
+ "name": "Upload Image",
27
+ "request": {
28
+ "method": "POST",
29
+ "header": [
30
+ {
31
+ "key": "X-Firebase-AppCheck",
32
+ "value": "{{app_check_token}}",
33
+ "type": "text"
34
+ }
35
+ ],
36
+ "body": {
37
+ "mode": "formdata",
38
+ "formdata": [
39
+ {
40
+ "key": "file",
41
+ "type": "file",
42
+ "src": []
43
+ }
44
+ ]
45
+ },
46
+ "url": {
47
+ "raw": "{{base_url}}/upload",
48
+ "host": [
49
+ "{{base_url}}"
50
+ ],
51
+ "path": [
52
+ "upload"
53
+ ]
54
+ },
55
+ "description": "Choose an image file in form-data 'file'. Returns image_url and filename."
56
+ }
57
+ },
58
+ {
59
+ "name": "Colorize Image",
60
+ "request": {
61
+ "method": "POST",
62
+ "header": [
63
+ {
64
+ "key": "X-Firebase-AppCheck",
65
+ "value": "{{app_check_token}}",
66
+ "type": "text"
67
+ }
68
+ ],
69
+ "body": {
70
+ "mode": "formdata",
71
+ "formdata": [
72
+ {
73
+ "key": "file",
74
+ "type": "file",
75
+ "src": []
76
+ }
77
+ ]
78
+ },
79
+ "url": {
80
+ "raw": "{{base_url}}/colorize",
81
+ "host": [
82
+ "{{base_url}}"
83
+ ],
84
+ "path": [
85
+ "colorize"
86
+ ]
87
+ },
88
+ "description": "Choose a grayscale (or any) image file in form-data 'file'. Returns download_url and result_id."
89
+ }
90
+ },
91
+ {
92
+ "name": "Download Result (by result_id)",
93
+ "request": {
94
+ "method": "GET",
95
+ "header": [
96
+ {
97
+ "key": "X-Firebase-AppCheck",
98
+ "value": "{{app_check_token}}",
99
+ "type": "text"
100
+ }
101
+ ],
102
+ "url": {
103
+ "raw": "{{base_url}}/download/{{result_id}}",
104
+ "host": [
105
+ "{{base_url}}"
106
+ ],
107
+ "path": [
108
+ "download",
109
+ "{{result_id}}"
110
+ ]
111
+ },
112
+ "description": "Uses the result_id returned by the Colorize Image request."
113
+ }
114
+ },
115
+ {
116
+ "name": "Get Result (public by filename)",
117
+ "request": {
118
+ "method": "GET",
119
+ "header": [],
120
+ "url": {
121
+ "raw": "{{base_url}}/results/{{filename}}",
122
+ "host": [
123
+ "{{base_url}}"
124
+ ],
125
+ "path": [
126
+ "results",
127
+ "{{filename}}"
128
+ ]
129
+ },
130
+ "description": "Direct public URL to image file; no auth required."
131
+ }
132
+ }
133
+ ,
134
+ {
135
+ "name": "Get Uploaded (public by filename)",
136
+ "request": {
137
+ "method": "GET",
138
+ "header": [],
139
+ "url": {
140
+ "raw": "{{base_url}}/uploads/{{filename}}",
141
+ "host": [
142
+ "{{base_url}}"
143
+ ],
144
+ "path": [
145
+ "uploads",
146
+ "{{filename}}"
147
+ ]
148
+ },
149
+ "description": "Direct public URL to uploaded image file; no auth required."
150
+ }
151
+ }
152
+ ],
153
+ "variable": [
154
+ {
155
+ "key": "base_url",
156
+ "value": "https://logicgoinfotechspaces-text-guided-image-colorization.hf.space"
157
+ },
158
+ {
159
+ "key": "app_check_token",
160
+ "value": ""
161
+ },
162
+ {
163
+ "key": "result_id",
164
+ "value": ""
165
+ },
166
+ {
167
+ "key": "filename",
168
+ "value": ""
169
+ }
170
+ ]
171
+ }
172
+
test.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import argparse
4
+ import logging
5
+ from pathlib import Path
6
+
7
+ import requests
8
+
9
+
10
+ logging.basicConfig(
11
+ level=logging.INFO,
12
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
13
+ )
14
+ logger = logging.getLogger("colorize_test")
15
+
16
+
17
+ def normalize_space_url(url: str) -> str:
18
+ """
19
+ Accept either a runtime URL (https://<owner>-<space>.hf.space)
20
+ or a repo URL (https://huggingface.co/spaces/<Owner>/<Space>?logs=container)
21
+ and return a runtime base URL suitable for API calls.
22
+ """
23
+ if not url:
24
+ return url
25
+ url = url.strip()
26
+ # Strip query params
27
+ if "?" in url:
28
+ url = url.split("?", 1)[0]
29
+ # Already runtime URL
30
+ if ".hf.space" in url:
31
+ return url.rstrip("/")
32
+ # Convert repo URL to runtime URL
33
+ marker = "/spaces/"
34
+ if "huggingface.co" in url and marker in url:
35
+ try:
36
+ _, rest = url.split(marker, 1)
37
+ owner, space = rest.split("/", 1)
38
+ runtime = f"https://{owner.lower()}-{space.lower()}.hf.space"
39
+ return runtime.rstrip("/")
40
+ except Exception:
41
+ return url.rstrip("/")
42
+ return url.rstrip("/")
43
+
44
+
45
+ def main() -> None:
46
+ parser = argparse.ArgumentParser(description="Test Colorize API")
47
+ parser.add_argument(
48
+ "--image",
49
+ "-i",
50
+ type=str,
51
+ required=False,
52
+ default=r"C:\projects\colorize_text\pexels-andrey-grushnikov-223358-707676.jpg",
53
+ help="Path to input image file",
54
+ )
55
+ parser.add_argument(
56
+ "--timeout",
57
+ type=int,
58
+ default=180,
59
+ help="Request timeout in seconds (default: 180)",
60
+ )
61
+ args = parser.parse_args()
62
+
63
+ base_url = os.getenv(
64
+ "BASE_URL",
65
+ os.getenv(
66
+ "SPACE_HOST",
67
+ "http://localhost:7860",
68
+ ),
69
+ )
70
+ base_url = normalize_space_url(base_url)
71
+ app_check_token = os.getenv("APP_CHECK_TOKEN", "").strip()
72
+
73
+ image_path = Path(args.image)
74
+ if not image_path.exists():
75
+ logger.error("Image file not found at: %s", str(image_path))
76
+ sys.exit(1)
77
+
78
+ # Health check
79
+ try:
80
+ logger.info("Using BASE_URL: %s", base_url)
81
+ health = requests.get(f"{base_url}/health", timeout=15)
82
+ logger.info("Health check %s: %s", health.status_code, health.text)
83
+ except Exception as e:
84
+ logger.warning("Health check failed: %s", str(e))
85
+
86
+ headers = {}
87
+ if app_check_token:
88
+ headers["X-Firebase-AppCheck"] = app_check_token
89
+
90
+ files = {"file": (image_path.name, open(image_path, "rb"), "application/octet-stream")}
91
+
92
+ logger.info("Sending request to %s", f"{base_url}/colorize")
93
+ try:
94
+ resp = requests.post(
95
+ f"{base_url}/colorize",
96
+ headers=headers,
97
+ files=files,
98
+ timeout=args.timeout,
99
+ )
100
+ finally:
101
+ files["file"][1].close()
102
+
103
+ logger.info("Response status: %s", resp.status_code)
104
+ if not resp.ok:
105
+ logger.error("Error response: %s", resp.text)
106
+ sys.exit(2)
107
+
108
+ data = resp.json()
109
+ download_url = data.get("download_url")
110
+ api_download_url = data.get("api_download_url")
111
+ filename = data.get("filename")
112
+
113
+ logger.info("Colorization success: %s", data.get("success"))
114
+ logger.info("Download URL: %s", download_url)
115
+ logger.info("API Download URL: %s", api_download_url)
116
+ logger.info("Filename: %s", filename)
117
+
118
+ # Optionally download the result locally
119
+ if download_url:
120
+ try:
121
+ out_path = Path("colorized_result.jpg")
122
+ r = requests.get(download_url, timeout=60)
123
+ if r.ok:
124
+ out_path.write_bytes(r.content)
125
+ logger.info("Saved colorized image to: %s", str(out_path.resolve()))
126
+ else:
127
+ logger.warning("Could not download from public URL, status: %s", r.status_code)
128
+ except Exception as e:
129
+ logger.warning("Download via public URL failed: %s", str(e))
130
+
131
+
132
+ if __name__ == "__main__":
133
+ main()
134
+