This allows API users to process document content, enabling the use of Docs as a headless CMS for instance, or any kind of document processing. Fixes #1206.
81 lines
2.5 KiB
Python
81 lines
2.5 KiB
Python
"""Y-Provider API services."""
|
|
|
|
import json
|
|
from base64 import b64encode
|
|
|
|
from django.conf import settings
|
|
|
|
import requests
|
|
|
|
|
|
class ConversionError(Exception):
|
|
"""Base exception for conversion-related errors."""
|
|
|
|
|
|
class ValidationError(ConversionError):
|
|
"""Raised when the input validation fails."""
|
|
|
|
|
|
class ServiceUnavailableError(ConversionError):
|
|
"""Raised when the conversion service is unavailable."""
|
|
|
|
|
|
class YProviderAPI:
|
|
"""Service class for Y-Provider API operations."""
|
|
|
|
@property
|
|
def auth_header(self):
|
|
"""Build microservice authentication header."""
|
|
# Note: Yprovider microservice accepts only raw token, which is not recommended
|
|
return f"Bearer {settings.Y_PROVIDER_API_KEY}"
|
|
|
|
def _request(self, url, data, content_type):
|
|
"""Make a request to the Y-Provider API."""
|
|
response = requests.post(
|
|
url,
|
|
data=data,
|
|
headers={
|
|
"Authorization": self.auth_header,
|
|
"Content-Type": content_type,
|
|
},
|
|
timeout=settings.CONVERSION_API_TIMEOUT,
|
|
verify=settings.CONVERSION_API_SECURE,
|
|
)
|
|
response.raise_for_status()
|
|
return response
|
|
|
|
def convert(self, text):
|
|
"""Convert a Markdown text into our internal format using an external microservice."""
|
|
|
|
if not text:
|
|
raise ValidationError("Input text cannot be empty")
|
|
|
|
try:
|
|
response = self._request(
|
|
f"{settings.Y_PROVIDER_API_BASE_URL}{settings.CONVERSION_API_ENDPOINT}/",
|
|
text,
|
|
"text/markdown",
|
|
)
|
|
return b64encode(response.content).decode("utf-8")
|
|
except requests.RequestException as err:
|
|
raise ServiceUnavailableError(
|
|
"Failed to connect to backend service",
|
|
) from err
|
|
|
|
def content(self, base64_content, format_type):
|
|
"""Convert base64 Yjs content to different formats using the y-provider service."""
|
|
|
|
if not base64_content:
|
|
raise ValidationError("Input content cannot be empty")
|
|
|
|
data = json.dumps({"content": base64_content, "format": format_type})
|
|
try:
|
|
response = self._request(
|
|
f"{settings.Y_PROVIDER_API_BASE_URL}content/", data, "application/json"
|
|
)
|
|
return response.json()
|
|
except requests.RequestException as err:
|
|
raise ServiceUnavailableError(
|
|
"Failed to connect to backend service",
|
|
) from err
|