Spaces:
Sleeping
Sleeping
Commit ·
91463a0
1
Parent(s): 1ce845b
ok
Browse files- api/server.py +6 -19
api/server.py
CHANGED
|
@@ -33,11 +33,10 @@ from typing import Annotated, Any, Dict, List, Optional
|
|
| 33 |
from urllib.parse import urlparse
|
| 34 |
|
| 35 |
import httpx
|
| 36 |
-
from fastapi import
|
| 37 |
from fastapi.middleware.cors import CORSMiddleware
|
| 38 |
from fastapi.middleware.gzip import GZipMiddleware
|
| 39 |
from fastapi.responses import PlainTextResponse
|
| 40 |
-
from fastapi.security import APIKeyHeader
|
| 41 |
from pydantic import BaseModel, field_validator
|
| 42 |
|
| 43 |
from core import ConversionError, ConversionResult, DocumentConverter, SUPPORTED_EXTENSIONS
|
|
@@ -57,19 +56,9 @@ _thread_pool = concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS)
|
|
| 57 |
|
| 58 |
_converter = DocumentConverter()
|
| 59 |
|
| 60 |
-
_X_API_KEY = os.environ.get("X_API_KEY", "")
|
| 61 |
-
|
| 62 |
logger.info("Thread pool initialised with %d workers", MAX_WORKERS)
|
| 63 |
|
| 64 |
|
| 65 |
-
def _validate_api_key(x_api_key: str = Security(APIKeyHeader(name="x-api-key", auto_error=False))) -> str:
|
| 66 |
-
if not _X_API_KEY:
|
| 67 |
-
return x_api_key
|
| 68 |
-
if x_api_key == _X_API_KEY:
|
| 69 |
-
return x_api_key
|
| 70 |
-
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid x-api-key")
|
| 71 |
-
|
| 72 |
-
|
| 73 |
# ---------------------------------------------------------------------------
|
| 74 |
# Self-ping
|
| 75 |
# ---------------------------------------------------------------------------
|
|
@@ -338,7 +327,7 @@ async def health():
|
|
| 338 |
|
| 339 |
|
| 340 |
@app.get("/info", tags=["System"], summary="Server and environment information")
|
| 341 |
-
async def info(
|
| 342 |
"""Return application version, platform details, and operational limits."""
|
| 343 |
import platform
|
| 344 |
|
|
@@ -356,7 +345,7 @@ async def info(_: str = Depends(_validate_api_key)):
|
|
| 356 |
|
| 357 |
|
| 358 |
@app.get("/formats", tags=["System"], summary="Supported file formats by category")
|
| 359 |
-
async def list_formats(
|
| 360 |
"""Return all supported file extensions, grouped by document category."""
|
| 361 |
by_category = {
|
| 362 |
"documents": [e for e in SUPPORTED_EXTENSIONS if e in {".pdf", ".docx", ".doc", ".epub"}],
|
|
@@ -377,7 +366,7 @@ async def list_formats(_: str = Depends(_validate_api_key)):
|
|
| 377 |
|
| 378 |
|
| 379 |
@app.get("/spacy-labels", tags=["System"], summary="Available spaCy NER labels for field extraction")
|
| 380 |
-
async def list_spacy_labels(
|
| 381 |
"""Return spaCy Named Entity Recognition labels available for structured extraction mappings."""
|
| 382 |
from extraction.spacy_extractor import VALID_SPACY_LABELS
|
| 383 |
|
|
@@ -421,7 +410,6 @@ async def convert_file(
|
|
| 421 |
"Example: {\"company\": {\"source_type\": \"entity\", \"label\": \"ORG\"}}"
|
| 422 |
),
|
| 423 |
),
|
| 424 |
-
_: str = Depends(_validate_api_key),
|
| 425 |
):
|
| 426 |
"""Convert a single uploaded file to Markdown.
|
| 427 |
|
|
@@ -493,7 +481,7 @@ async def convert_file(
|
|
| 493 |
tags=["Convert"],
|
| 494 |
summary="Convert a public URL to Markdown",
|
| 495 |
)
|
| 496 |
-
async def convert_url(body: UrlRequest
|
| 497 |
"""Convert a public HTTP/HTTPS URL to Markdown.
|
| 498 |
|
| 499 |
When ``return_json=true``, the URL content is fetched as raw bytes first
|
|
@@ -574,7 +562,6 @@ async def convert_url(body: UrlRequest, _: str = Depends(_validate_api_key)):
|
|
| 574 |
)
|
| 575 |
async def batch_files(
|
| 576 |
files: Annotated[List[UploadFile], File(description="Files to convert — maximum 10")],
|
| 577 |
-
_: str = Depends(_validate_api_key),
|
| 578 |
):
|
| 579 |
"""Convert up to 10 uploaded files in a single request.
|
| 580 |
|
|
@@ -639,7 +626,7 @@ async def batch_files(
|
|
| 639 |
tags=["Batch"],
|
| 640 |
summary="Convert multiple URLs (up to 20)",
|
| 641 |
)
|
| 642 |
-
async def batch_urls(body: BatchUrlRequest
|
| 643 |
"""Convert up to 20 public URLs in a single request.
|
| 644 |
|
| 645 |
URLs are processed concurrently. Per-item results include success/error
|
|
|
|
| 33 |
from urllib.parse import urlparse
|
| 34 |
|
| 35 |
import httpx
|
| 36 |
+
from fastapi import FastAPI, File, Form, HTTPException, UploadFile, status
|
| 37 |
from fastapi.middleware.cors import CORSMiddleware
|
| 38 |
from fastapi.middleware.gzip import GZipMiddleware
|
| 39 |
from fastapi.responses import PlainTextResponse
|
|
|
|
| 40 |
from pydantic import BaseModel, field_validator
|
| 41 |
|
| 42 |
from core import ConversionError, ConversionResult, DocumentConverter, SUPPORTED_EXTENSIONS
|
|
|
|
| 56 |
|
| 57 |
_converter = DocumentConverter()
|
| 58 |
|
|
|
|
|
|
|
| 59 |
logger.info("Thread pool initialised with %d workers", MAX_WORKERS)
|
| 60 |
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
# ---------------------------------------------------------------------------
|
| 63 |
# Self-ping
|
| 64 |
# ---------------------------------------------------------------------------
|
|
|
|
| 327 |
|
| 328 |
|
| 329 |
@app.get("/info", tags=["System"], summary="Server and environment information")
|
| 330 |
+
async def info():
|
| 331 |
"""Return application version, platform details, and operational limits."""
|
| 332 |
import platform
|
| 333 |
|
|
|
|
| 345 |
|
| 346 |
|
| 347 |
@app.get("/formats", tags=["System"], summary="Supported file formats by category")
|
| 348 |
+
async def list_formats():
|
| 349 |
"""Return all supported file extensions, grouped by document category."""
|
| 350 |
by_category = {
|
| 351 |
"documents": [e for e in SUPPORTED_EXTENSIONS if e in {".pdf", ".docx", ".doc", ".epub"}],
|
|
|
|
| 366 |
|
| 367 |
|
| 368 |
@app.get("/spacy-labels", tags=["System"], summary="Available spaCy NER labels for field extraction")
|
| 369 |
+
async def list_spacy_labels():
|
| 370 |
"""Return spaCy Named Entity Recognition labels available for structured extraction mappings."""
|
| 371 |
from extraction.spacy_extractor import VALID_SPACY_LABELS
|
| 372 |
|
|
|
|
| 410 |
"Example: {\"company\": {\"source_type\": \"entity\", \"label\": \"ORG\"}}"
|
| 411 |
),
|
| 412 |
),
|
|
|
|
| 413 |
):
|
| 414 |
"""Convert a single uploaded file to Markdown.
|
| 415 |
|
|
|
|
| 481 |
tags=["Convert"],
|
| 482 |
summary="Convert a public URL to Markdown",
|
| 483 |
)
|
| 484 |
+
async def convert_url(body: UrlRequest):
|
| 485 |
"""Convert a public HTTP/HTTPS URL to Markdown.
|
| 486 |
|
| 487 |
When ``return_json=true``, the URL content is fetched as raw bytes first
|
|
|
|
| 562 |
)
|
| 563 |
async def batch_files(
|
| 564 |
files: Annotated[List[UploadFile], File(description="Files to convert — maximum 10")],
|
|
|
|
| 565 |
):
|
| 566 |
"""Convert up to 10 uploaded files in a single request.
|
| 567 |
|
|
|
|
| 626 |
tags=["Batch"],
|
| 627 |
summary="Convert multiple URLs (up to 20)",
|
| 628 |
)
|
| 629 |
+
async def batch_urls(body: BatchUrlRequest):
|
| 630 |
"""Convert up to 20 public URLs in a single request.
|
| 631 |
|
| 632 |
URLs are processed concurrently. Per-item results include success/error
|