저희 플랫폼의 리소스에 액세스하고 사용하는 방식에 영향을 미칠 수 있는 예정된 변경 사항에 대해 알려드립니다.
모든 생성된 아티팩트 URL에 CORS 정책을 적용할 예정입니다. 이는 저희 플랫폼에서 호스팅되는 모든 리소스가 교차 출처 요청에 대한 적절한 처리를 요구하게 되며, 다시 말해 Tripo API가 반환하는 링크를 사용하여 생성된 모델 파일을 직접 제공할 수 없게 됩니다.
이러한 변경은 보안을 강화하고 다른 출처 간의 리소스에 대한 무단 접근을 방지하려는 저희의 노력의 일환입니다. CORS(Cross-Origin Resource Sharing)는 서버가 어떤 외부 도메인이 리소스에 접근할 수 있는지 지정할 수 있도록 하는 메커니즘입니다.
CORS에 대한 자세한 정보는 MDN의 가이드를 참조하실 수 있습니다.
현재 저희는 아티팩트 URL에 대한 CORS 헤더를 제공하지 않습니다. 결과적으로, 브라우저에서 또는 외부 도메인에서 이러한 리소스를 직접 사용하거나 연결하는 경우 문제가 발생할 수 있습니다.
이러한 자산에 계속 액세스하려면 다음 조치 중 하나를 취해야 합니다.
실용적인 코드 예제가 필요하십니까? 시작하는 방법을 모르거나 구현이 어렵다고 느끼신다면, 시작하는 데 도움이 되는 실용적인 코드 스니펫을 제공해 드렸습니다. 자세한 내용은 부록을 참조하십시오.
생성된 파일이 손실됩니까?
아닙니다. 언제든지 API에서 새로운 URL을 검색할 수 있습니다.
귀사의 URL을 직접 반환하지는 않지만, 후처리 작업을 수행합니다. 우려해야 할까요?
사용자에게 저희 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>
이 코드 스니펫은 통합을 조정하는 방법을 보여주는 시연일 뿐입니다. 그러나 몇 가지 중요한 사항을 고려해야 합니다.
단일 페이지 애플리케이션(SPA) 또는 백엔드 포 프론트엔드(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.