この度、当社のプラットフォームからのリソースへのアクセスおよび使用方法に影響を与える可能性のある変更についてお知らせいたします。
2025/04/09より、生成されたすべての成果物URLに対してCORSポリシーを適用します。これは、当社のプラットフォームでホストされているすべてのリソースが、クロスオリジンリクエストに対して適切な処理を必要とすることを意味します。つまり、TripoのAPIが返すリンクを使用して生成されたモデルファイルを直接提供することはできません。
この変更は、セキュリティを向上させ、異なるオリジンからのリソースへの不正アクセスを防ぐという当社のコミットメントの一環です。CORS(Cross-Origin Resource Sharing)は、サーバーがどの外部ドメインがリソースにアクセスできるかを指定するためのメカニズムです。
CORSの詳細については、MDNのガイドを参照してください。
現在、成果物URLにCORSヘッダーは提供されていません。そのため、これらのリソースをブラウザで直接使用したり、外部ドメインからリンクしたりしている場合、問題が発生する可能性があります。
これらのアセットへの継続的なアクセスを確保するためには、次のいずれかの措置を講じる必要があります。
適用は2025/04/09に開始されます。
具体的なコード例が必要ですか? 開始方法がわからない場合や実装が難しいと感じる場合は、開始に役立つ実用的なコードスニペットを提供しています。詳細については、付録を参照してください。
生成されたファイルは失われますか?
**いいえ。**いつでもAPIから新しいURLを取得できます。
TripoのURLを直接返していませんが、後処理を行っています。それでも懸念すべきですか?
TripoのURLを直接ユーザーに返していない場合は、この変更をスキップできます。ただし、特にシステムでエラーの急増や異常な動作に気づいた場合は、使用状況を監視することをお勧めします。
FastAPI(他のフレームワークや言語に簡単に移植または翻訳できます)を使用している場合、CORSを処理し、成果物をローカルに保存するように既存のコードを調整する方法を以下に示します。
現在のコード:
@app.post("/")
def generate(prompt: str) -> str:
resp = ... # API works
return resp.json()['url']
次のように簡単に変更できます。
import httpx
import uuid
from fastapi.responses import FileResponse
from fastapi import HTTPException
@app.post("/")
def generate(prompt: str) -> str:
resp = ... # same as above
# Add the code below
file_id = str(uuid.uuid4())
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)
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")
ファイルをローカルにダウンロードして保存した後、新しいURLをユーザーに提供する必要があります。たとえば、アプリケーションがhttps://app.example.comでホストされている場合、提供すべきURLは次のようになります。
https://app.example.com/artifact/<file_id>
このコードスニペットは、統合を調整する方法のデモンストレーションにすぎません。ただし、考慮すべき重要な点がいくつかあります。
Single Page Application (SPA) または Backend for Frontend (BFF) サーバーを開発しており、サーバーでファイルのダウンロードと保存を直接処理したくない場合は、エッジプロキシアプローチを使用できます。これにより、当社のサーバーからファイルを取得し、必要なCORSヘッダーを適用して、ユーザーに提供することができます。
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が設定されたら、次のJavaScriptコードを使用してファイルをフェッチすることで、SPAに統合できます。
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));
このソリューションは、CORS制限をバイパスしながらファイルをダウンロードしてエンドユーザーに提供する必要があるSPAまたはBFFサーバーに最適です。ファイルはターゲットURLからフェッチされ、エッジプロキシを介して渡され、必要なCORSヘッダーとともに提供されます。
簡単なCORSプロキシを設定したい場合は、Cloudflareが提供するこの例を参照してください:Cloudflare Workers - CORS Header Proxy
これにより、CORSポリシーに準拠しながら、クロスオリジンリクエストをより簡単に処理できるようになります。
moving at the speed of creativity, achieving the depths of imagination.