Understanding CORS in TelemetryOS Applications
Critical information about Cross-Origin Resource Sharing (CORS) and how it affects your applications running in browser contexts.
Understanding CORS in TelemetryOS Applications
Critical information about Cross-Origin Resource Sharing (CORS) and how it affects your applications.
What is CORS?
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls which websites can make requests to your application or API.
The Problem
Web browsers enforce the Same-Origin Policy for security:
Your App Origin: https://your-app.telemetryos.com
External API: https://api.weather.com
Without CORS approval: ❌ Browser blocks the request
With CORS approval: ✅ Browser allows the request
An "origin" consists of:
- Protocol (
https://) - Domain (
api.weather.com) - Port (
:443for HTTPS)
Requests to a different origin require CORS permission from the target server.
Why CORS Matters for TelemetryOS
TelemetryOS applications run in browser contexts:
- On Devices - Applications run in iframes on TVs, kiosks, displays
- In Studio - Settings mount points run in admin portal iframes
- Local Development - Applications run in your browser during
tos serve
All of these contexts enforce CORS.
Common CORS Error
Access to fetch at 'https://api.example.com/data' from origin
'https://your-app.telemetryos.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
This error means:
- The external API doesn't allow requests from your application's origin
- The browser blocked the request for security
- You cannot bypass this in client-side code
When CORS Blocks Your Requests
Scenario 1: Public API Without CORS
// This will likely fail with CORS error
const response = await fetch('https://api.publicdata.com/stats');Why: Many public APIs don't enable CORS because they expect server-side usage only.
Scenario 2: Private API Without CORS
// This will fail with CORS error
const response = await fetch('https://your-company-api.com/data');Why: Your own API might not have CORS configured if it was built for server-to-server communication.
Scenario 3: API with Restricted CORS
// API only allows requests from example.com
// Your telemetryos.com origin is blocked
const response = await fetch('https://partner-api.com/data');Why: API configured CORS to only allow specific domains.
The TelemetryOS Solution: Proxy API
TelemetryOS provides a Proxy API that bypasses CORS restrictions by routing requests through the TelemetryOS platform.
How It Works
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Your App │ (1) │ TelemetryOS │ (2) │ External │
│ (Browser) │───────▶│ Platform │───────▶│ API │
│ │ │ (Server) │ │ │
└──────────────┘ └──────────────┘ └──────────────┘
│ │
│◀────────────────────────┘
│ (3)
│
▼
┌──────────────┐
│ Your App │
│ (Response) │
└──────────────┘
Steps:
- Your app calls
proxy().fetch(url)- Request goes to TelemetryOS platform - Platform makes server-to-server request (no CORS restrictions)
- Platform returns response to your app
Key Point: Server-to-server requests don't have CORS restrictions. The Proxy API moves the request to the server side.
Using the Proxy API
Basic Usage
import { proxy } from '@telemetryos/sdk';
// Instead of direct fetch
// const response = await fetch('https://api.example.com/data');
// Use proxy
const response = await proxy().fetch('https://api.example.com/data');
const data = await response.json();With API Keys
async function fetchWeather(city: string) {
const apiKey = 'your-api-key-here';
const url = `https://api.weatherapi.com/v1/current.json?key=${apiKey}&q=${city}`;
// Proxy handles CORS
const response = await proxy().fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
}POST Requests
async function submitData(data: any) {
const response = await proxy().fetch('https://api.example.com/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return await response.json();
}Custom Headers
const response = await proxy().fetch('https://api.example.com/data', {
headers: {
'Authorization': 'Bearer your-token',
'X-Custom-Header': 'value'
}
});When Proxy API is NOT Needed
1. CORS-Enabled APIs
Some APIs explicitly enable CORS:
// This works because API allows all origins
const response = await fetch('https://api.coinbase.com/v2/exchange-rates');How to Check: Look for API documentation mentioning CORS support or "browser-friendly" APIs.
2. TelemetryOS Resources
TelemetryOS-hosted resources already allow your origin:
// Media API returns publicUrls that work directly
const media = await media().getAllByTag('featured');
const imageUrl = media[0].publicUrls[0];
// Direct usage works
<img src={imageUrl} />3. Public CDNs
Most CDNs enable CORS for asset delivery:
// Public CDN resources typically work
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/lib.js"></script>
<img src="https://images.unsplash.com/photo-123" />Best Practices
1. Default to Proxy for External APIs
// ✅ Safe - always works
const response = await proxy().fetch('https://api.example.com/data');
// ❌ Risky - may work in dev, fail in production
const response = await fetch('https://api.example.com/data');2. Test with Real APIs During Development
Local development may not enforce CORS the same way production does:
# Test with actual external APIs
tos serve
# Make real API calls, don't mock everything3. Handle Proxy Errors
try {
const response = await proxy().fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('API call failed:', error);
// Provide fallback or user-friendly error
return null;
}4. Cache Responses When Possible
The proxy benefits from platform-level caching, but you can add application-level caching:
async function fetchWithCache(url: string) {
// Check device storage cache
const cached = await store().device.get(`cache:${url}`);
if (cached) return cached;
// Fetch through proxy
const response = await proxy().fetch(url);
const data = await response.json();
// Cache for next time
await store().device.set(`cache:${url}`, data);
return data;
}Common CORS Scenarios
Scenario 1: Weather API Integration
// ❌ Without proxy - CORS error
async function getWeatherBad(city: string) {
const response = await fetch(
`https://api.weatherapi.com/v1/current.json?key=API_KEY&q=${city}`
);
return await response.json();
}
// ✅ With proxy - works perfectly
async function getWeatherGood(city: string) {
const response = await proxy().fetch(
`https://api.weatherapi.com/v1/current.json?key=API_KEY&q=${city}`
);
return await response.json();
}Scenario 2: Your Own Backend API
// If you have a backend API
// ❌ Without CORS configuration or proxy
const response = await fetch('https://your-backend.com/api/data');
// ✅ Option 1: Configure CORS on your backend
// Allow: https://*.telemetryos.com
// ✅ Option 2: Use proxy
const response = await proxy().fetch('https://your-backend.com/api/data');Scenario 3: GraphQL APIs
async function queryGraphQL(query: string) {
const response = await proxy().fetch('https://api.example.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ query })
});
return await response.json();
}Troubleshooting CORS Issues
Error: "blocked by CORS policy"
Solution: Use proxy().fetch() instead of fetch()
Error: "Failed to fetch"
Check:
- Is the URL correct?
- Is the API endpoint online?
- Are you using
proxy().fetch()for external APIs? - Check browser console for specific CORS error
Local Development Works, Production Fails
Cause: Local development may not enforce CORS the same way.
Solution: Always test with proxy().fetch() even in local development.
API Returns 403/401
Not CORS: This is an authentication/authorization error.
Solution: Check API keys, tokens, and authentication headers.
Additional Proxy Benefits
Beyond solving CORS, the Proxy API provides:
- Caching - Platform caches responses, reducing API calls
- Bandwidth Optimization - Shared quota across all devices
- Monitoring - Track API usage and performance
- Rate Limiting - Platform handles rate limits gracefully
- Error Recovery - Automatic retries for transient failures
Summary
Key Takeaways:
- ✅ TelemetryOS apps run in browser contexts with CORS enforcement
- ✅ Use
proxy().fetch()for all external API calls - ✅ Proxy API solves CORS + adds caching and optimization
- ✅ Test with real APIs during development
- ❌ Cannot disable CORS in browser environments
- ❌ Direct fetch to non-CORS APIs will fail
Quick Decision Guide:
// External APIs (weather, news, social media, etc.)
await proxy().fetch(url) // ✅ Always use proxy
// TelemetryOS resources (media, etc.)
await fetch(publicUrl) // ✅ Direct fetch is fine
// Your own backend
// Either enable CORS on backend OR use proxy
await proxy().fetch(url) // ✅ Safest optionNext Steps
- Proxy Methods Reference - Complete proxy().fetch() documentation
- Code Examples - See proxy usage in context
- Quick Start - Build your first application
Updated 5 days ago