corsbridge
v1.0.2
Published
Zero-Config CORS Proxy Client for Developers
Maintainers
Readme
📘 CorsBridge
Zero-Config CORS Proxy Client for Developers
CorsBridge is a lightweight, type-safe CORS proxy client that automatically routes requests through cors.syrins.tech backend.
⚡ Quick Start
Installation
npm install corsbridgeCLI Usage (NEW! 🚀)
You can also use CorsBridge directly from the command line:
# Install globally
npm install -g corsbridge
# Simple GET request
corsbridge https://api.github.com/users/github
# POST request with JSON body
corsbridge https://api.example.com/users -X POST -d '{"name":"John"}'
# With custom headers
corsbridge https://api.example.com/data -H "Authorization: Bearer TOKEN"
# Verbose output
corsbridge https://api.github.com/data -v
# Point to your own proxy
corsbridge https://api.example.com --proxy http://localhost:3000
# Show help
corsbridge --helpBasic Usage (Library)
import { corsFetch } from 'corsbridge';
// Simple GET request
const data = await corsFetch('https://api.github.com/users/github');
console.log(data);
// POST request with body
const response = await corsFetch('https://api.example.com/users', {
method: 'POST',
body: { name: 'John Doe' }
});
// With query parameters
const bitcoin = await corsFetch('https://api.coingecko.com/api/v3/simple/price', {
params: {
ids: 'bitcoin',
vs_currencies: 'usd'
}
});That's it! No configuration, no API keys, just install and use.
🎯 Features
- ✅ Zero Config - No setup required
- 🖥️ CLI Support - Use from command line
- ✅ Type Safe - Full TypeScript support
- ✅ Secure - SSRF protection on backend
- ✅ Fast - Cached responses & optimized
- ✅ Framework Agnostic - Works everywhere
- ✅ Error Handling - Structured error types
- ✅ Browser & Node.js - Universal support
📚 API Reference
corsFetch(url, options?)
Main function to make proxied requests.
interface CorsFetchOptions {
method?: string; // HTTP method (GET, POST, etc.)
headers?: Record<string, string>; // Request headers
body?: any; // Request body
params?: Record<string, any>; // Query parameters
timeout?: number; // Request timeout (ms)
responseType?: 'json' | 'text' | 'arrayBuffer' | 'blob';
proxyUrl?: string; // Override proxy endpoint for this call
}Convenience Methods
import { corsGet, corsPost, corsPut, corsPatch, corsDelete } from 'corsbridge';
// GET
const users = await corsGet('https://api.example.com/users');
// POST
const newUser = await corsPost('https://api.example.com/users', {
name: 'John',
email: '[email protected]'
});
// PUT
await corsPut('https://api.example.com/users/1', { name: 'Jane' });
// PATCH
await corsPatch('https://api.example.com/users/1', { email: '[email protected]' });
// DELETE
await corsDelete('https://api.example.com/users/1');🛡️ Error Handling
CorsBridge maps backend errors to typed error classes:
import {
corsFetch,
ValidationError,
HostBlockedError,
SSRFBlockedError,
InvalidURLError,
RateLimitError,
TimeoutError,
TargetError,
NetworkError
} from 'corsbridge';
try {
const data = await corsFetch('https://api.example.com/data');
} catch (error) {
if (error instanceof HostBlockedError) {
console.error('Host blocked (private IP/localhost):', error.message);
console.error('Request ID:', error.requestId);
} else if (error instanceof SSRFBlockedError) {
console.error('SSRF attempt blocked:', error.message);
} else if (error instanceof InvalidURLError) {
console.error('URL too long or invalid:', error.message);
} else if (error instanceof ValidationError) {
console.error('Validation error:', error.message);
console.error('Status:', error.statusCode); // 400, 403, 414
} else if (error instanceof RateLimitError) {
console.error('Rate limit exceeded (429)');
if (error.details?.retryAfter) {
console.error('Retry after:', error.details.retryAfter, 'seconds');
}
} else if (error instanceof TimeoutError) {
console.error('Request timeout (504)');
} else if (error instanceof TargetError) {
console.error('Target server error (502)');
} else if (error instanceof NetworkError) {
console.error('Network connection failed');
}
}Error Types
| Error Class | Status Code | Description |
|------------|-------------|-------------|
| ValidationError | 400, 403, 414 | Base validation error |
| HostBlockedError | 403 | Private IP, localhost, internal hosts |
| SSRFBlockedError | 403 | SSRF attempt detected |
| InvalidURLError | 414 | URL exceeds maximum length |
| PayloadTooLargeError | 413 | Request body too large |
| RateLimitError | 429 | Rate limit exceeded |
| TargetError | 502 | Target server error (alias: BadGatewayError) |
| TimeoutError | 504 | Request timeout (alias: GatewayTimeoutError) |
| NetworkError | - | Client-side network error |
Note: HostBlockedError, SSRFBlockedError, and InvalidURLError all extend ValidationError, so you can catch them individually or as ValidationError.
All errors expose requestId, traceId, and spanId fields when the backend provides them, making it straightforward to correlate failures with proxy logs.
⚙️ Advanced Usage
With Authentication
await corsFetch('https://api.example.com/protected', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
}
});With Timeout
await corsFetch('https://slow-api.com/data', {
timeout: 10000 // 10 seconds
});
### Custom Proxy Endpoint
Point the client to your self-hosted backend without touching global env vars:
```typescript
await corsFetch('https://api.example.com/data', {
proxyUrl: 'https://my-proxy.internal'
});Or set CORS_PROXY_URL once in your environment (works for both the library and CLI):
export CORS_PROXY_URL="https://proxy.example.com"
### Different Response Types
```typescript
// Text
const html = await corsFetch('https://example.com', {
responseType: 'text'
});
// Binary
const buffer = await corsFetch('https://example.com/file.pdf', {
responseType: 'arrayBuffer'
});
// Blob
const image = await corsFetch('https://example.com/image.png', {
responseType: 'blob'
});🎨 Framework Examples
React
import { useEffect, useState } from 'react';
import { corsFetch } from 'corsbridge';
function App() {
const [data, setData] = useState(null);
useEffect(() => {
corsFetch('https://api.github.com/users/github')
.then(setData)
.catch(console.error);
}, []);
return <div>{JSON.stringify(data)}</div>;
}Vue 3
<script setup>
import { ref, onMounted } from 'vue';
import { corsFetch } from 'corsbridge';
const data = ref(null);
onMounted(async () => {
data.value = await corsFetch('https://api.github.com/users/github');
});
</script>
<template>
<div>{{ data }}</div>
</template>Next.js
'use client';
import { useEffect, useState } from 'react';
import { corsFetch } from 'corsbridge';
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
corsFetch('https://api.example.com/data').then(setData);
}, []);
return <div>{JSON.stringify(data)}</div>;
}🔐 Security
CorsBridge backend includes:
- ✅ SSRF protection (blocks private IPs)
- ✅ URL validation & sanitization
- ✅ Rate limiting
- ✅ Header filtering
- ✅ Request size limits
- ✅ Timeout enforcement
All requests are validated server-side before proxying.
🌐 Backend Integration
This package works with the CorsBridge backend at cors.syrins.tech.
Backend features:
- Express.js + TypeScript
- Redis caching
- Rate limiting (per IP)
- Circuit breakers
- Health checks
- Prometheus metrics
- Comprehensive logging
📄 License
MIT License - see LICENSE file
🔗 Links
- 🌐 Service: https://cors.syrins.tech
- 📖 Full Docs: https://cors.syrins.tech/docs
- 📦 NPM Package: https://www.npmjs.com/package/corsbridge
- 💻 GitHub: https://github.com/syrins/corsbridge
- 📋 Changelog: CHANGELOG.md
- 🐛 Issues: GitHub Issues
💖 Support
If you find this useful, please ⭐ the repo!
