cp fix api start

This commit is contained in:
johnpccd 2025-05-24 23:22:05 +02:00
parent d6cfb05b04
commit 6265ac534a
5 changed files with 1280 additions and 197 deletions

View File

@ -340,13 +340,54 @@ results = vector_db.search_similar_images(
## API Endpoints ## API Endpoints
The API provides the following main endpoints: The API provides the following main endpoints with their pagination support:
### Authentication & Authorization
- `/api/v1/auth/*` - Authentication and API key management - `/api/v1/auth/*` - Authentication and API key management
- `GET /api/v1/auth/api-keys` - List API keys (no pagination - returns all keys for user)
### Team Management
- `/api/v1/teams/*` - Team management - `/api/v1/teams/*` - Team management
- `GET /api/v1/teams` - List teams (no pagination - admin only, returns all teams)
### User Management
- `/api/v1/users/*` - User management - `/api/v1/users/*` - User management
- `GET /api/v1/users` - List users (no pagination - returns all users in team/organization)
### Image Management ✅ **Fully Paginated**
- `/api/v1/images/*` - **Image upload, download, and management (with async processing)** - `/api/v1/images/*` - **Image upload, download, and management (with async processing)**
- `GET /api/v1/images` - List images with **full pagination support**
- **Query Parameters:**
- `skip` (default: 0, min: 0) - Number of items to skip
- `limit` (default: 50, min: 1, max: 100) - Number of items per page
- `collection_id` (optional) - Filter by collection
- `tags` (optional) - Filter by comma-separated tags
- **Response includes:** `images`, `total`, `skip`, `limit`
### Search Functionality ✅ **Fully Paginated**
- `/api/v1/search/*` - **Image search functionality (semantic search via Qdrant)** - `/api/v1/search/*` - **Image search functionality (semantic search via Qdrant)**
- `GET /api/v1/search` - Search images with **pagination support**
- **Query Parameters:**
- `q` (required) - Search query
- `limit` (default: 10, min: 1, max: 50) - Number of results
- `threshold` (default: 0.7, min: 0.0, max: 1.0) - Similarity threshold
- `collection_id` (optional) - Filter by collection
- `tags` (optional) - Filter by comma-separated tags
- **Response includes:** `results`, `total`, `limit`, `threshold`, `query`
- `POST /api/v1/search` - Advanced search with same pagination
- `GET /api/v1/search/similar/{image_id}` - Find similar images with pagination
### Pagination Implementation Status
| Endpoint | Pagination Status | Notes |
|----------|------------------|-------|
| `GET /api/v1/images` | ✅ **Fully Implemented** | `skip`, `limit`, `total` with proper validation |
| `GET /api/v1/search` | ✅ **Fully Implemented** | `limit`, `total` with similarity scoring |
| `GET /api/v1/users` | ❌ **Not Implemented** | Returns all users (typically small datasets) |
| `GET /api/v1/teams` | ❌ **Not Implemented** | Returns all teams (typically small datasets) |
| `GET /api/v1/auth/api-keys` | ❌ **Not Implemented** | Returns all keys for user (typically small datasets) |
**Note:** The endpoints without pagination (users, teams, API keys) typically return small datasets and are designed for admin/management use cases where full data visibility is preferred.
### **Image Processing Status** ### **Image Processing Status**
@ -538,26 +579,31 @@ This modular architecture provides several benefits:
- **Reusability**: Common functionality is centralized for consistent implementation - **Reusability**: Common functionality is centralized for consistent implementation
- **Security**: Authentication and authorization are handled consistently - **Security**: Authentication and authorization are handled consistently
## TODO ## TODO
### High Priority ### High Priority
- [ ] Remove Pinecone integration and complete Qdrant migration - [ ] Remove Pinecone integration and complete Qdrant migration
- [ ] Test and validate vector search functionality with Qdrant - [ ] Test and validate vector search functionality with Qdrant
- [ ] Implement proper pagination for search results and all endpoints - [x] ~~Implement proper pagination for search results and all endpoints~~ **COMPLETED** - Images and Search APIs have full pagination
- [ ] Test Cloud Function image processing pipeline - [ ] Test Cloud Function image processing pipeline
- [ ] Validate VM setup for self-hosted Qdrant instance - [ ] Validate VM setup for self-hosted Qdrant instance
### Medium Priority ### Medium Priority
- [ ] Add comprehensive logging for vector search operations - [ ] Add comprehensive logging for vector search operations
- [ ] Implement caching layer for frequently accessed embeddings - [ ] Implement caching layer for frequently accessed embeddings
- [ ] Implement caching for frequently accessed data - [ ] Implement caching for frequently accessed data
- [ ] Add monitoring and alerting for vector database performance - [ ] Add monitoring and alerting for vector database performance
- [ ] Document vector search API endpoints - [ ] Document vector search API endpoints
- [ ] Set up Qdrant cluster with multiple nodes - [ ] Set up Qdrant cluster with multiple nodes
- [ ] Consider adding pagination to admin endpoints (users, teams, API keys) if datasets grow large
### Low Priority ### Low Priority
- [ ] Terraform dependencies
### Pagination Status ✅
- **✅ Images API**: Fully implemented with `skip`, `limit`, `total` parameters
- **✅ Search API**: Fully implemented with `limit`, `total`, similarity scoring
- ** Users/Teams/API Keys**: No pagination (small datasets, admin use cases)
## Recent Changes ## Recent Changes
- Migrated from Pinecone to self-hosted Qdrant - Migrated from Pinecone to self-hosted Qdrant

View File

@ -130,31 +130,31 @@ resource "google_cloud_run_service" "sereact" {
value = "INFO" value = "INFO"
} }
# CORS Configuration - These were missing! # # CORS Configuration - These were missing!
env { # env {
name = "CORS_ORIGINS" # name = "CORS_ORIGINS"
value = "*" # value = "[\"*\"]"
} # }
env { # env {
name = "CORS_METHODS" # name = "CORS_METHODS"
value = "GET,POST,PUT,DELETE,OPTIONS" # value = "GET,POST,PUT,DELETE,OPTIONS"
} # }
env { # env {
name = "CORS_HEADERS" # name = "CORS_HEADERS"
value = "Content-Type,Authorization,X-Requested-With" # value = "Content-Type,Authorization,X-Requested-With"
} # }
env { # env {
name = "CORS_EXPOSE_HEADERS" # name = "CORS_EXPOSE_HEADERS"
value = "Content-Length,Content-Range" # value = "Content-Length,Content-Range"
} # }
env { # env {
name = "CORS_MAX_AGE" # name = "CORS_MAX_AGE"
value = "3600" # value = "3600"
} # }
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{ {
"version": 4, "version": 4,
"terraform_version": "1.10.1", "terraform_version": "1.10.1",
"serial": 273, "serial": 363,
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5", "lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
"outputs": { "outputs": {
"cloud_run_qdrant_host": { "cloud_run_qdrant_host": {
@ -9,38 +9,13 @@
"type": "string" "type": "string"
}, },
"cloud_run_qdrant_host_internal": { "cloud_run_qdrant_host_internal": {
"value": "10.128.0.4", "value": "10.128.0.6",
"type": "string"
},
"cloud_run_url": {
"value": "https://sereact-p64zpdtkta-uc.a.run.app",
"type": "string" "type": "string"
}, },
"container_registry_url": { "container_registry_url": {
"value": "gcr.io/gen-lang-client-0424120530/sereact", "value": "gcr.io/gen-lang-client-0424120530/sereact",
"type": "string" "type": "string"
}, },
"deployment_summary": {
"value": {
"cloud_run_url": "https://sereact-p64zpdtkta-uc.a.run.app",
"firestore_database": "sereact-imagedb",
"qdrant_endpoint": "http://34.71.6.1:6333",
"qdrant_host_ip": "34.71.6.1",
"static_ip_enabled": false,
"storage_bucket": "sereact-images"
},
"type": [
"object",
{
"cloud_run_url": "string",
"firestore_database": "string",
"qdrant_endpoint": "string",
"qdrant_host_ip": "string",
"static_ip_enabled": "bool",
"storage_bucket": "string"
}
]
},
"firestore_database_id": { "firestore_database_id": {
"value": "projects/gen-lang-client-0424120530/databases/sereact-imagedb", "value": "projects/gen-lang-client-0424120530/databases/sereact-imagedb",
"type": "string" "type": "string"
@ -74,7 +49,7 @@
"type": "string" "type": "string"
}, },
"vector_db_vm_internal_ip": { "vector_db_vm_internal_ip": {
"value": "10.128.0.4", "value": "10.128.0.6",
"type": "string" "type": "string"
}, },
"vector_db_vm_name": { "vector_db_vm_name": {
@ -123,6 +98,7 @@
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]", "provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [ "instances": [
{ {
"status": "tainted",
"schema_version": 2, "schema_version": 2,
"attributes": { "attributes": {
"autogenerate_revision_name": false, "autogenerate_revision_name": false,
@ -134,67 +110,25 @@
"run.googleapis.com/ingress": "all" "run.googleapis.com/ingress": "all"
}, },
"effective_annotations": { "effective_annotations": {
"run.googleapis.com/ingress": "all", "run.googleapis.com/ingress": "all"
"run.googleapis.com/ingress-status": "all",
"run.googleapis.com/operation-id": "8e5e22cf-c77d-4cb8-8587-5cf9d409193c",
"run.googleapis.com/urls": "[\"https://sereact-761163285547.us-central1.run.app\",\"https://sereact-p64zpdtkta-uc.a.run.app\"]",
"serving.knative.dev/creator": "johnpccd3@gmail.com",
"serving.knative.dev/lastModifier": "johnpccd3@gmail.com"
}, },
"effective_labels": { "effective_labels": {
"cloud.googleapis.com/location": "us-central1",
"goog-terraform-provisioned": "true" "goog-terraform-provisioned": "true"
}, },
"generation": 5, "generation": 0,
"labels": {}, "labels": null,
"namespace": "gen-lang-client-0424120530", "namespace": "",
"resource_version": "AAY15+pAZzs", "resource_version": "",
"self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact", "self_link": "",
"terraform_labels": { "terraform_labels": {
"goog-terraform-provisioned": "true" "goog-terraform-provisioned": "true"
}, },
"uid": "f67eed78-59c9-4bb6-a118-fb940f206d09" "uid": ""
} }
], ],
"name": "sereact", "name": "sereact",
"project": "gen-lang-client-0424120530", "project": "gen-lang-client-0424120530",
"status": [ "status": null,
{
"conditions": [
{
"message": "Revision 'sereact-00005-5n6' is not ready and cannot serve traffic. The user-provided container failed the configured startup probe checks. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=gen-lang-client-0424120530\u0026resource=cloud_run_revision/service_name/sereact/revision_name/sereact-00005-5n6\u0026advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22sereact%22%0Aresource.labels.revision_name%3D%22sereact-00005-5n6%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start",
"reason": "HealthCheckContainerError",
"status": "False",
"type": "Ready"
},
{
"message": "The user-provided container failed the configured startup probe checks. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=gen-lang-client-0424120530\u0026resource=cloud_run_revision/service_name/sereact/revision_name/sereact-00005-5n6\u0026advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22sereact%22%0Aresource.labels.revision_name%3D%22sereact-00005-5n6%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start",
"reason": "",
"status": "True",
"type": "ConfigurationsReady"
},
{
"message": "Revision 'sereact-00005-5n6' is not ready and cannot serve traffic. The user-provided container failed the configured startup probe checks. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=gen-lang-client-0424120530\u0026resource=cloud_run_revision/service_name/sereact/revision_name/sereact-00005-5n6\u0026advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22sereact%22%0Aresource.labels.revision_name%3D%22sereact-00005-5n6%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start",
"reason": "HealthCheckContainerError",
"status": "False",
"type": "RoutesReady"
}
],
"latest_created_revision_name": "sereact-00005-5n6",
"latest_ready_revision_name": "sereact-00001-rsq",
"observed_generation": 5,
"traffic": [
{
"latest_revision": true,
"percent": 100,
"revision_name": "sereact-00001-rsq",
"tag": "",
"url": ""
}
],
"url": "https://sereact-p64zpdtkta-uc.a.run.app"
}
],
"template": [ "template": [
{ {
"metadata": [ "metadata": [
@ -203,9 +137,7 @@
"autoscaling.knative.dev/maxScale": "10" "autoscaling.knative.dev/maxScale": "10"
}, },
"generation": 0, "generation": 0,
"labels": { "labels": {},
"run.googleapis.com/startupProbeType": "Custom"
},
"name": "", "name": "",
"namespace": "", "namespace": "",
"resource_version": "", "resource_version": "",
@ -215,11 +147,11 @@
], ],
"spec": [ "spec": [
{ {
"container_concurrency": 80, "container_concurrency": 0,
"containers": [ "containers": [
{ {
"args": [], "args": null,
"command": [], "command": null,
"env": [ "env": [
{ {
"name": "CORS_EXPOSE_HEADERS", "name": "CORS_EXPOSE_HEADERS",
@ -241,11 +173,6 @@
"value": "GET,POST,PUT,DELETE,OPTIONS", "value": "GET,POST,PUT,DELETE,OPTIONS",
"value_from": [] "value_from": []
}, },
{
"name": "CORS_ORIGINS",
"value": "*",
"value_from": []
},
{ {
"name": "FIRESTORE_DATABASE_NAME", "name": "FIRESTORE_DATABASE_NAME",
"value": "sereact-imagedb", "value": "sereact-imagedb",
@ -309,7 +236,7 @@
"ports": [ "ports": [
{ {
"container_port": 8000, "container_port": 8000,
"name": "http1", "name": "",
"protocol": "" "protocol": ""
} }
], ],
@ -319,34 +246,18 @@
"cpu": "1", "cpu": "1",
"memory": "1Gi" "memory": "1Gi"
}, },
"requests": {} "requests": null
}
],
"startup_probe": [
{
"failure_threshold": 6,
"grpc": [],
"http_get": [
{
"http_headers": [],
"path": "/health",
"port": 8000
}
],
"initial_delay_seconds": 30,
"period_seconds": 10,
"tcp_socket": [],
"timeout_seconds": 5
} }
], ],
"startup_probe": [],
"volume_mounts": [], "volume_mounts": [],
"working_dir": "" "working_dir": ""
} }
], ],
"node_selector": {}, "node_selector": null,
"service_account_name": "761163285547-compute@developer.gserviceaccount.com", "service_account_name": "",
"serving_state": "", "serving_state": "",
"timeout_seconds": 300, "timeout_seconds": 0,
"volumes": [] "volumes": []
} }
] ]
@ -416,33 +327,10 @@
}, },
{ {
"mode": "managed", "mode": "managed",
"type": "google_cloud_run_service_iam_member", "type": "google_compute_address",
"name": "public_access", "name": "vector_db_static_ip",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]", "provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [ "instances": []
{
"schema_version": 0,
"attributes": {
"condition": [],
"etag": "BwY15bNaQMM=",
"id": "v1/projects/gen-lang-client-0424120530/locations/us-central1/services/sereact/roles/run.invoker/allUsers",
"location": "us-central1",
"member": "allUsers",
"project": "gen-lang-client-0424120530",
"role": "roles/run.invoker",
"service": "v1/projects/gen-lang-client-0424120530/locations/us-central1/services/sereact"
},
"sensitive_attributes": [],
"private": "bnVsbA==",
"dependencies": [
"google_cloud_run_service.sereact",
"google_compute_address.vector_db_static_ip",
"google_compute_instance.vector_db_vm",
"google_project_service.services",
"google_service_account.vector_db_sa"
]
}
]
}, },
{ {
"mode": "managed", "mode": "managed",
@ -462,7 +350,7 @@
"protocol": "tcp" "protocol": "tcp"
} }
], ],
"creation_timestamp": "2025-05-24T10:57:27.640-07:00", "creation_timestamp": "2025-05-24T14:09:17.159-07:00",
"deny": [], "deny": [],
"description": "", "description": "",
"destination_ranges": [], "destination_ranges": [],
@ -552,7 +440,7 @@
"can_ip_forward": false, "can_ip_forward": false,
"confidential_instance_config": [], "confidential_instance_config": [],
"cpu_platform": "Intel Broadwell", "cpu_platform": "Intel Broadwell",
"creation_timestamp": "2025-05-24T10:57:41.174-07:00", "creation_timestamp": "2025-05-24T14:09:30.477-07:00",
"current_status": "RUNNING", "current_status": "RUNNING",
"deletion_protection": false, "deletion_protection": false,
"description": "", "description": "",
@ -565,7 +453,7 @@
"hostname": "", "hostname": "",
"id": "projects/gen-lang-client-0424120530/zones/us-central1-a/instances/sereact-vector-db", "id": "projects/gen-lang-client-0424120530/zones/us-central1-a/instances/sereact-vector-db",
"instance_encryption_key": [], "instance_encryption_key": [],
"instance_id": "8076617322369889915", "instance_id": "1246596410843827045",
"key_revocation_action_type": "", "key_revocation_action_type": "",
"label_fingerprint": "vezUS-42LLM=", "label_fingerprint": "vezUS-42LLM=",
"labels": {}, "labels": {},
@ -592,7 +480,7 @@
"name": "nic0", "name": "nic0",
"network": "https://www.googleapis.com/compute/v1/projects/gen-lang-client-0424120530/global/networks/default", "network": "https://www.googleapis.com/compute/v1/projects/gen-lang-client-0424120530/global/networks/default",
"network_attachment": "", "network_attachment": "",
"network_ip": "10.128.0.4", "network_ip": "10.128.0.6",
"nic_type": "", "nic_type": "",
"queue_count": 0, "queue_count": 0,
"stack_type": "IPV4_ONLY", "stack_type": "IPV4_ONLY",
@ -653,7 +541,18 @@
[ [
{ {
"type": "get_attr", "type": "get_attr",
"value": "metadata_startup_script" "value": "boot_disk"
},
{
"type": "index",
"value": {
"value": 0,
"type": "number"
}
},
{
"type": "get_attr",
"value": "disk_encryption_key_rsa"
} }
], ],
[ [
@ -676,18 +575,7 @@
[ [
{ {
"type": "get_attr", "type": "get_attr",
"value": "boot_disk" "value": "metadata_startup_script"
},
{
"type": "index",
"value": {
"value": 0,
"type": "number"
}
},
{
"type": "get_attr",
"value": "disk_encryption_key_rsa"
} }
] ]
], ],
@ -716,8 +604,8 @@
"database_edition": "STANDARD", "database_edition": "STANDARD",
"delete_protection_state": "DELETE_PROTECTION_DISABLED", "delete_protection_state": "DELETE_PROTECTION_DISABLED",
"deletion_policy": "ABANDON", "deletion_policy": "ABANDON",
"earliest_version_time": "2025-05-24T19:55:31.455016Z", "earliest_version_time": "2025-05-24T21:09:24.677010Z",
"etag": "IM+J1/v+vI0DMLa2lbPIvI0D", "etag": "IOyxoJSEvY0DMJL7/oiCvY0D",
"id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb", "id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb",
"key_prefix": "", "key_prefix": "",
"location_id": "us-central1", "location_id": "us-central1",
@ -726,12 +614,12 @@
"project": "gen-lang-client-0424120530", "project": "gen-lang-client-0424120530",
"timeouts": null, "timeouts": null,
"type": "FIRESTORE_NATIVE", "type": "FIRESTORE_NATIVE",
"uid": "30634721-c8c7-4673-b605-c1a91dff3eab", "uid": "f4aa945b-2205-4f94-b903-57815519f2fc",
"update_time": "", "update_time": "",
"version_retention_period": "3600s" "version_retention_period": "3600s"
}, },
"sensitive_attributes": [], "sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH0sInNjaGVtYV92ZXJzaW9uIjoiMCJ9", "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19",
"dependencies": [ "dependencies": [
"google_project_service.services" "google_project_service.services"
] ]
@ -963,7 +851,7 @@
"schema_version": 0, "schema_version": 0,
"attributes": { "attributes": {
"condition": [], "condition": [],
"etag": "BwY15XOdN50=", "etag": "BwY16CF7/Zw=",
"id": "projects/gen-lang-client-0424120530/subscriptions/image-processing-topic-subscription/roles/pubsub.subscriber", "id": "projects/gen-lang-client-0424120530/subscriptions/image-processing-topic-subscription/roles/pubsub.subscriber",
"members": [ "members": [
"serviceAccount:761163285547-compute@developer.gserviceaccount.com" "serviceAccount:761163285547-compute@developer.gserviceaccount.com"
@ -1075,7 +963,7 @@
"schema_version": 0, "schema_version": 0,
"attributes": { "attributes": {
"condition": [], "condition": [],
"etag": "BwY15XMktMU=", "etag": "BwY16CEHGDA=",
"id": "projects/gen-lang-client-0424120530/topics/image-processing-topic/roles/pubsub.publisher", "id": "projects/gen-lang-client-0424120530/topics/image-processing-topic/roles/pubsub.publisher",
"members": [ "members": [
"serviceAccount:761163285547-compute@developer.gserviceaccount.com" "serviceAccount:761163285547-compute@developer.gserviceaccount.com"
@ -1113,7 +1001,7 @@
"name": "projects/gen-lang-client-0424120530/serviceAccounts/vector-db-sa@gen-lang-client-0424120530.iam.gserviceaccount.com", "name": "projects/gen-lang-client-0424120530/serviceAccounts/vector-db-sa@gen-lang-client-0424120530.iam.gserviceaccount.com",
"project": "gen-lang-client-0424120530", "project": "gen-lang-client-0424120530",
"timeouts": null, "timeouts": null,
"unique_id": "108486040628486621877" "unique_id": "115648202672357296665"
}, },
"sensitive_attributes": [], "sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjozMDAwMDAwMDAwMDB9fQ==" "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjozMDAwMDAwMDAwMDB9fQ=="
@ -1159,7 +1047,7 @@
"self_link": "https://www.googleapis.com/storage/v1/b/sereact-images", "self_link": "https://www.googleapis.com/storage/v1/b/sereact-images",
"soft_delete_policy": [ "soft_delete_policy": [
{ {
"effective_time": "2025-05-24T17:57:31.611Z", "effective_time": "2025-05-24T21:09:21.315Z",
"retention_duration_seconds": 604800 "retention_duration_seconds": 604800
} }
], ],
@ -1167,10 +1055,10 @@
"terraform_labels": { "terraform_labels": {
"goog-terraform-provisioned": "true" "goog-terraform-provisioned": "true"
}, },
"time_created": "2025-05-24T17:57:31.611Z", "time_created": "2025-05-24T21:09:21.315Z",
"timeouts": null, "timeouts": null,
"uniform_bucket_level_access": true, "uniform_bucket_level_access": true,
"updated": "2025-05-24T17:57:31.611Z", "updated": "2025-05-24T21:09:21.315Z",
"url": "gs://sereact-images", "url": "gs://sereact-images",
"versioning": [], "versioning": [],
"website": [] "website": []

View File

@ -23,9 +23,6 @@ class Settings(BaseSettings):
# Read from environment variable first # Read from environment variable first
env_origins = os.getenv("CORS_ORIGINS") env_origins = os.getenv("CORS_ORIGINS")
if env_origins: if env_origins:
# Handle wildcard case
if env_origins.strip() == "*":
return ["*"]
if env_origins.startswith("[") and env_origins.endswith("]"): if env_origins.startswith("[") and env_origins.endswith("]"):
# Handle list format like "['*']" # Handle list format like "['*']"
import ast import ast