Важное обновление: как использовать ссылки для скачивания сгенерированных файлов

Уважаемые пользователи Tripo,

Мы пишем, чтобы проинформировать вас о предстоящем изменении, которое может повлиять на то, как вы получаете доступ к ресурсам нашей платформы и используете их.

Что меняется?

Мы будем принудительно применять политику CORS ко всем URL-адресам сгенерированных артефактов. Это означает, что все ресурсы, размещенные на нашей платформе, потребуют соответствующей обработки для междоменных запросов, или, другими словами, вы не сможете напрямую обслуживать сгенерированные файлы моделей, используя ссылку, которую возвращает API Tripo.

Почему это внедряется?

Это изменение является частью нашего стремления улучшить безопасность и предотвратить несанкционированный доступ к ресурсам из разных источников. CORS (Cross-Origin Resource Sharing) — это механизм, который позволяет серверам указывать, какие внешние домены могут получать доступ к ресурсам.
Для получения дополнительной информации о том, что такое CORS, вы можете обратиться к руководству MDN.

Влияние на ваш рабочий процесс

В настоящее время мы не предоставляем заголовки CORS для URL-адресов артефактов. В результате, если вы используете или ссылаетесь на эти ресурсы напрямую в браузере или из внешних доменов, у вас могут возникнуть проблемы.
Чтобы обеспечить постоянный доступ к этим активам, вам необходимо предпринять одно из следующих действий:

  1. Скачайте и сохраните артефакты локально: Вы можете скачать артефакты и хранить их на своем бэкенде. После сохранения локально вы сможете обслуживать эти активы со своего сервера без ограничений CORS.
  2. Используйте граничный прокси (например, Next.js API Route, Cloudflare Workers): Вы можете использовать граничный прокси для получения и обслуживания артефактов, добавляя необходимые заголовки CORS к ответам. Например:
    • Next.js API Route: Настройте API-маршрут для получения ресурсов с нашей платформы и пересылки их с соответствующими заголовками CORS.
    • Cloudflare Workers: Используйте Cloudflare Workers для добавления заголовков CORS при обслуживании наших активов с вашего сервера.

Как подготовиться:

  • Просмотрите свою интеграцию: Убедитесь, что ваша система способна обрабатывать CORS для URL-адресов артефактов.
  • Скачайте и сохраните артефакты: Если вы не используете граничный прокси, рассмотрите возможность скачивания и хранения артефактов на своем бэкенде.
  • Настройте граничный прокси: Если вы используете такие решения, как Next.js или Cloudflare Workers, обновите свою конфигурацию, чтобы убедиться, что активы обслуживаются с соответствующими заголовками CORS.
  • Протестируйте свою систему: Убедитесь, что все междоменные запросы к нашей платформе работают должным образом.

Нужны практические примеры кода? Если вы не знаете, как начать, или процесс кажется сложным в реализации, мы предоставили практические фрагменты кода, которые помогут вам начать работу. Более подробную информацию см. в Приложении.

Часто задаваемые вопросы

  • Потерян ли мой сгенерированный файл?

    Нет. Вы всегда можете получить новый URL-адрес из API в любое время.

  • Я не возвращаю ваш URL-адрес напрямую, но выполняю некоторую постобработку. Стоит ли мне беспокоиться?

    Если вы не возвращаете наш URL-адрес напрямую своим пользователям, вы можете пропустить это изменение. Однако мы рекомендуем отслеживать ваше использование, особенно если вы заметите какие-либо всплески ошибок или аномальное поведение в вашей системе.

Нужна помощь?

Мы понимаем, что это изменение может потребовать обновлений вашего рабочего процесса. Если вам нужна помощь в настройке граничного прокси или у вас есть какие-либо вопросы по этому переходу, пожалуйста, свяжитесь с нашей службой поддержки по адресу support@tripo3d.ai.
Мы ценим ваше сотрудничество, поскольку мы работаем над повышением безопасности нашей платформы! Будьте в безопасности и продуктивны!
С наилучшими пожеланиями,
Команда Tripo

Приложение А: Подход к повторному сохранению на бэкенде

Если вы используете FastAPI (который легко портировать или перевести на любой другой фреймворк или язык), вот как вы можете настроить свой существующий код для обработки CORS и сохранения артефакта локально:

Текущий код:

@app.post("/")
def generate(prompt: str) -> str:
    resp = ...  # API works
    return resp.json()['url']

Вы можете легко изменить его на:

import httpx
import uuid
import os

from fastapi.responses import FileResponse
from fastapi import HTTPException

@app.post("/")
def generate(prompt: str) -> str:
    resp = ...  # same as above
    url = resp.json()['url'] # assuming url is extracted from resp

    # Add the code below
    file_id = str(uuid.uuid4())
    # Ensure the directory exists
    os.makedirs("./downloaded", exist_ok=True)
    with httpx.Client() as client:
        # Download the artifact
        response = client.get(url)

        # Check if the request was successful
        if response.status_code == 200:
            # Then resave it
            with open(f"./downloaded/{file_id}.glb", "wb") as file:
                file.write(response.content)
        else:
            raise HTTPException(status_code=response.status_code, detail="Failed to download artifact")

    return file_id

@app.get("/artifact/{file_id}")
def download(file_id: str) -> FileResponse:
    file_path = f"./downloaded/{file_id}.glb"
    if os.path.exists(file_path):
      return FileResponse(file_path)
    raise HTTPException(status_code=404, detail="Item not found")

После загрузки и сохранения файла локально вы должны обслуживать своих пользователей с новым URL-адресом. Например, если ваше приложение размещено по адресу https://app.example.com, URL-адрес, который вы должны обслуживать, будет выглядеть следующим образом:

https://app.example.com/artifact/<file_id>

Этот фрагмент кода является лишь демонстрацией того, как настроить вашу интеграцию. Однако есть несколько важных моментов, которые следует учитывать:

  • Добавьте соответствующую аутентификацию: Убедитесь, что ссылки для скачивания защищены соответствующими методами аутентификации для предотвращения несанкционированного доступа.
  • Используйте надежное хранилище: Рекомендуется сохранять файлы в более надежных решениях для хранения, таких как выделенные серверы или облачные хранилища, такие как S3 buckets.
  • Храните метаданные: Ведите учет метаданных артефактов в вашей базе данных или другой системе хранения для будущего использования (например, для отслеживания или аудита).

Приложение B: Подход с граничным прокси

Если вы разрабатываете одностраничное приложение (SPA) или бэкенд для фронтенда (BFF) и предпочитаете не обрабатывать загрузку и хранение файлов непосредственно на своем сервере, вы можете использовать подход с граничным прокси. Это позволяет получать файл с нашего сервера, применять необходимые заголовки CORS, а затем передавать его вашим пользователям.

Решение 1: Загрузка и повторная отправка файла с использованием граничных функций

Ниже приведен пример того, как реализовать этот подход с использованием Cloudflare Workers. Это решение позволит решить проблемы CORS путем загрузки файла и его повторной отправки под вашим доменом.

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  // Parse the request URL
  const url = new URL(request.url);

  // Get the target URL from the 'url' query parameter
  const targetUrl = url.searchParams.get('url');

  // If no URL is provided, return an error
  if (!targetUrl) {
    return new Response('Please provide a URL parameter', {
      status: 400,
      headers: {
        'Content-Type': 'text/plain',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type'
      }
    });
  }

  // Handle preflight OPTIONS request
  if (request.method === 'OPTIONS') {
    return handleCORS();
  }

  try {
    // Fetch the file from the target URL
    const response = await fetch(targetUrl);

    // If the fetch failed, return the error
    if (!response.ok) {
      return new Response(`Failed to fetch from target URL: ${response.statusText}`, {
        status: response.status,
        headers: corsHeaders()
      });
    }

    // Get the content type from the response or default to octet-stream
    const contentType = response.headers.get('Content-Type') || 'application/octet-stream';

    // Get the content disposition or create one from the URL
    let contentDisposition = response.headers.get('Content-Disposition');
    if (!contentDisposition) {
      // Extract filename from the URL
      const fileName = targetUrl.split('/').pop().split('?')[0] || 'file';
      contentDisposition = `attachment; filename="${fileName}"`;
    }

    // Create a new response with CORS headers
    const newResponse = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: {
        'Content-Type': contentType,
        'Content-Disposition': contentDisposition,
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Cache-Control': 'public, max-age=3600' // Cache for 1 hour
      }
    });

    return newResponse;
  } catch (error) {
    return new Response(`Error fetching the file: ${error.message}`, {
      status: 500,
      headers: corsHeaders()
    });
  }
}

// Handle CORS preflight requests
function handleCORS() {
  return new Response(null, {
    status: 204, // No content
    headers: corsHeaders()
  });
}

// Create CORS headers object
function corsHeaders() {
  return {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
    'Access-Control-Max-Age': '86400' // 24 hours
  };
}

После настройки вашего Cloudflare Worker вы можете интегрировать его в свое SPA, используя следующий код JavaScript для получения файла:

fetch('https://your-worker-url.workers.dev/?url=<target_url>')
  .then(response => response.blob())
  .then(blob => {
    // Create a download link
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'downloaded-file.pdf';
    document.body.appendChild(a);
    a.click();
    a.remove();
  })
  .catch(error => console.error('Error:', error));

Это решение идеально подходит для SPA или BFF-серверов, которым необходимо обойти ограничения CORS при загрузке и обслуживании файлов для конечных пользователей. Файл извлекается из целевого URL-адреса, передается через граничный прокси и обслуживается с необходимыми заголовками CORS.

Решение 2: Настройка прокси-сервера заголовков CORS

Если вы предпочитаете настроить простой прокси-сервер CORS, вы можете обратиться к этому примеру, предоставленному Cloudflare: Cloudflare Workers - CORS Header Proxy
Это позволит вам легче обрабатывать междоменные запросы, по-прежнему соблюдая политики CORS.

Важные соображения:

  • Аутентификация: Убедитесь, что вы правильно защитили свои граничные функции с помощью методов аутентификации (например, API-ключей, OAuth и т. д.) для предотвращения несанкционированного доступа к вашим файлам.
  • Хранение: Хотя этот подход работает, мы по-прежнему рекомендуем сохранять артефакты на вашем сервере для будущего использования, особенно если вам необходимо управлять крупномасштабными загрузками или обеспечивать надежный доступ к ресурсам.

Advancing 3D generation to new heights

moving at the speed of creativity, achieving the depths of imagination.