Actualización Importante sobre el Uso de Enlaces de Descarga de Archivos Generados

Estimados usuarios de Tripo,

Les escribimos para informarles sobre un próximo cambio que puede afectar la forma en que acceden y utilizan los recursos de nuestra plataforma.

¿Qué está cambiando?

Implementaremos una política CORS obligatoria en todas las URL de artefactos generados. Esto significa que todos los recursos alojados en nuestra plataforma requerirán un manejo adecuado para las solicitudes de origen cruzado, o en otras palabras, no podrán servir directamente archivos de modelos generados utilizando el enlace que les devuelve la API de Tripo.

¿Por qué se implementa este cambio?

Este cambio forma parte de nuestro compromiso de mejorar la seguridad y prevenir el acceso no autorizado a los recursos en diferentes orígenes. CORS (Cross-Origin Resource Sharing) es un mecanismo que permite a los servidores especificar qué dominios externos pueden acceder a los recursos.
Para obtener más información sobre qué es CORS, pueden consultar la guía de MDN.

Impacto en su flujo de trabajo

Actualmente, no proporcionamos encabezados CORS para las URL de los artefactos. Como resultado, si están utilizando o enlazando directamente a estos recursos en un navegador o desde dominios externos, pueden experimentar problemas.
Para asegurar el acceso continuo a estos activos, deberán tomar una de las siguientes acciones:

  1. Descargar y Re-guardar Artefactos Localmente: Pueden descargar los artefactos y almacenarlos en su backend. Una vez guardados localmente, pueden servir estos activos desde su servidor sin restricciones CORS.
  2. Usar un Proxy Edge (por ejemplo, Next.js API Route, Cloudflare Workers): Pueden usar un proxy edge para obtener y servir los artefactos mientras añaden los encabezados CORS necesarios a las respuestas. Por ejemplo:
    • Next.js API Route: Configuren una ruta de API para obtener recursos de nuestra plataforma y reenviarlos con los encabezados CORS apropiados.
    • Cloudflare Workers: Utilicen Cloudflare Workers para añadir encabezados CORS al servir nuestros activos desde su servidor.

Cómo prepararse:

  • Revisen su integración: Asegúrense de que su sistema sea capaz de manejar CORS para las URL de los artefactos.
  • Descarguen y guarden los artefactos: Si no están utilizando un proxy edge, consideren descargar y almacenar los artefactos en su backend.
  • Configuren un proxy edge: Si están utilizando soluciones como Next.js o Cloudflare Workers, actualicen su configuración para asegurar que los activos se sirvan con los encabezados CORS apropiados.
  • Prueben su sistema: Verifiquen que todas las solicitudes de origen cruzado a nuestra plataforma funcionen como se espera.

¿Necesitan ejemplos de código prácticos? Si no están seguros de cómo empezar o el proceso les resulta difícil de implementar, hemos proporcionado fragmentos de código prácticos para ayudarles a comenzar. Por favor, consulten el Apéndice para más detalles.

Preguntas frecuentes

  • ¿Se ha perdido mi archivo generado?

    No. Siempre pueden recuperar una nueva URL de la API en cualquier momento.

  • No devuelvo su URL directamente, pero hago algún post-procesamiento. ¿Debería preocuparme?

    Si no están devolviendo nuestra URL directamente a sus usuarios, pueden omitir este cambio. Sin embargo, les recomendamos monitorear su uso, especialmente si notan picos de errores o comportamientos anormales en su sistema.

¿Necesitan ayuda?

Entendemos que este cambio puede requerir actualizaciones en su flujo de trabajo. Si necesitan ayuda para configurar un proxy edge o tienen alguna pregunta sobre esta transición, por favor, pónganse en contacto con nuestro equipo de soporte en support@tripo3d.ai.
¡Agradecemos su cooperación mientras trabajamos para mejorar la seguridad en nuestra plataforma! ¡Manténganse seguros y productivos!
Saludos cordiales,
El equipo de Tripo

Apéndice A: Enfoque de re-guardado en el backend

Si están utilizando FastAPI (que es fácil de portar o traducir a cualquier otro framework o lenguaje), así es como pueden ajustar su código existente para manejar CORS y guardar el artefacto localmente:

Código actual:

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

Pueden modificarlo fácilmente a:

import httpx
import uuid

from fastapi.responses import FileResponse
from fastapi import HTTPException
import os

@app.post("/")
def generate(prompt: str) -> str:
    resp = ...  # igual que arriba

    # Añadir el código de abajo
    file_id = str(uuid.uuid4())
    with httpx.Client() as client:
        # Descargar el artefacto
        url = resp.json()['url'] # Asegurarse de que 'url' está definido, asumiendo que viene de 'resp'
        response = client.get(url)

        # Comprobar si la solicitud fue exitosa
        if response.status_code == 200:
            # Luego re-guardarlo
            # Asegurarse de que el directorio './downloaded/' existe
            os.makedirs("./downloaded", exist_ok=True)
            with open(f"./downloaded/{file_id}.glb", "wb") as file:
                file.write(response.content)

    return file_id

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

Después de descargar y guardar el archivo localmente, deben servir a sus usuarios con la nueva URL. Por ejemplo, si su aplicación está alojada en https://app.example.com, la URL que deben servir se verá así:

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

Este fragmento de código es solo una demostración de cómo ajustar su integración. Sin embargo, hay algunas cosas importantes que deben considerar:

  • Añadir autenticación adecuada: Asegúrense de que los enlaces de descarga estén protegidos por los métodos de autenticación apropiados para evitar el acceso no autorizado.
  • Usar almacenamiento fiable: Se recomienda guardar los archivos en soluciones de almacenamiento más fiables, como servidores dedicados u opciones de almacenamiento en la nube como los buckets S3.
  • Almacenar metadatos: Mantengan un registro de los metadatos del artefacto en su base de datos u otro sistema de almacenamiento para uso futuro (como seguimiento o auditoría).

Apéndice B: Enfoque de Proxy Edge

Si están desarrollando una Single Page Application (SPA) o un servidor Backend for Frontend (BFF) y prefieren no manejar las descargas y el almacenamiento de archivos directamente en su servidor, pueden usar un enfoque de proxy edge. Esto les permite obtener el archivo de nuestro servidor, aplicar los encabezados CORS necesarios y luego servirlo a sus usuarios.

Solución 1: Descargar y reenviar el archivo usando Edge Functions

A continuación, se muestra un ejemplo de cómo implementar este enfoque utilizando Cloudflare Workers. Esta solución manejará los problemas de CORS descargando el archivo y reenviándolo bajo su dominio.

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

async function handleRequest(request) {
  // Analizar la URL de la solicitud
  const url = new URL(request.url);

  // Obtener la URL de destino del parámetro de consulta 'url'
  const targetUrl = url.searchParams.get('url');

  // Si no se proporciona ninguna URL, devolver un error
  if (!targetUrl) {
    return new Response('Por favor, proporcione un parámetro de URL', {
      status: 400,
      headers: {
        'Content-Type': 'text/plain',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type'
      }
    });
  }

  // Manejar la solicitud OPTIONS de pre-vuelo
  if (request.method === 'OPTIONS') {
    return handleCORS();
  }

  try {
    // Obtener el archivo de la URL de destino
    const response = await fetch(targetUrl);

    // Si la obtención falló, devolver el error
    if (!response.ok) {
      return new Response(`Error al obtener de la URL de destino: ${response.statusText}`, {
        status: response.status,
        headers: corsHeaders()
      });
    }

    // Obtener el tipo de contenido de la respuesta o usar octet-stream por defecto
    const contentType = response.headers.get('Content-Type') || 'application/octet-stream';

    // Obtener la disposición del contenido o crear una a partir de la URL
    let contentDisposition = response.headers.get('Content-Disposition');
    if (!contentDisposition) {
      // Extraer el nombre del archivo de la URL
      const fileName = targetUrl.split('/').pop().split('?')[0] || 'file';
      contentDisposition = `attachment; filename="${fileName}"`;
    }

    // Crear una nueva respuesta con encabezados CORS
    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' // Cachear durante 1 hora
      }
    });

    return newResponse;
  } catch (error) {
    return new Response(`Error al obtener el archivo: ${error.message}`, {
      status: 500,
      headers: corsHeaders()
    });
  }
}

// Manejar las solicitudes de pre-vuelo de CORS
function handleCORS() {
  return new Response(null, {
    status: 204, // Sin contenido
    headers: corsHeaders()
  });
}

// Crear objeto de encabezados CORS
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 horas
  };
}

Una vez que su Cloudflare Worker esté configurado, pueden integrarlo en su SPA utilizando el siguiente código JavaScript para obtener el archivo:

fetch('https://your-worker-url.workers.dev/?url=<target_url>')
  .then(response => response.blob())
  .then(blob => {
    // Crear un enlace de descarga
    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));

Esta solución es perfecta para SPAs o servidores BFF que necesitan evitar las restricciones CORS al descargar y servir archivos a los usuarios finales. El archivo se obtiene de la URL de destino, se pasa a través del proxy edge y se sirve con los encabezados CORS necesarios.

Solución 2: Configurar un proxy de encabezados CORS

Si prefieren configurar un proxy CORS simple, pueden consultar este ejemplo proporcionado por Cloudflare: Cloudflare Workers - CORS Header Proxy
Esto les permitirá manejar las solicitudes de origen cruzado más fácilmente, sin dejar de cumplir con las políticas de CORS.

Consideraciones importantes:

  • Autenticación: Asegúrense de proteger adecuadamente sus funciones edge con métodos de autenticación (por ejemplo, claves API, OAuth, etc.) para evitar el acceso no autorizado a sus archivos.
  • Almacenamiento: Aunque este enfoque funciona, todavía recomendamos guardar el artefacto en su servidor para uso futuro, especialmente si necesitan gestionar descargas a gran escala o asegurar un acceso fiable a los recursos.

Advancing 3D generation to new heights

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