99 lines
2.9 KiB
JavaScript
99 lines
2.9 KiB
JavaScript
import express from 'express';
|
|
import cors from 'cors';
|
|
|
|
const app = express();
|
|
const PORT = process.env.PROXY_PORT || 5374;
|
|
const DEBUG = process.env.REACT_APP_DEBUG_MODE === 'true';
|
|
|
|
function debugLog(...args) {
|
|
if (DEBUG) console.log(...args);
|
|
}
|
|
|
|
app.use(cors());
|
|
// Increase payload limit to 10MB (default is 100kb)
|
|
app.use(express.json({ limit: '10mb' }));
|
|
|
|
// Proxy endpoint for Claude API
|
|
app.post('/api/claude', async (req, res) => {
|
|
try {
|
|
const { messages, apiKey, model, maxTokens } = req.body;
|
|
|
|
debugLog('=== Proxy received request ===');
|
|
debugLog('Model:', model);
|
|
debugLog('Max tokens:', maxTokens);
|
|
debugLog('Messages count:', messages?.length);
|
|
|
|
const requestBody = {
|
|
model: model,
|
|
max_tokens: maxTokens,
|
|
messages: messages,
|
|
...(req.body.tools && { tools: req.body.tools })
|
|
};
|
|
|
|
debugLog('Request body:', JSON.stringify(requestBody, null, 2));
|
|
|
|
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'x-api-key': apiKey,
|
|
'anthropic-version': '2023-06-01'
|
|
},
|
|
body: JSON.stringify(requestBody)
|
|
});
|
|
|
|
debugLog('Claude API response status:', response.status);
|
|
|
|
if (!response.ok) {
|
|
const error = await response.text();
|
|
console.error('Claude API error:', error);
|
|
return res.status(response.status).json({ error });
|
|
}
|
|
|
|
const data = await response.json();
|
|
debugLog('Claude API success, response content length:', data.content?.[0]?.text?.length);
|
|
debugLog('Token usage:', data.usage);
|
|
res.json(data);
|
|
} catch (error) {
|
|
console.error('Proxy error:', error);
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
// Proxy endpoint for scraping web pages (avoids CORS issues)
|
|
app.get('/api/scrape', async (req, res) => {
|
|
try {
|
|
const { url } = req.query;
|
|
|
|
if (!url) {
|
|
return res.status(400).json({ error: 'Missing url query parameter' });
|
|
}
|
|
|
|
debugLog('=== Scrape proxy request ===');
|
|
debugLog('URL:', url);
|
|
|
|
const response = await fetch(url, {
|
|
headers: {
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
'Accept-Language': 'en-US,en;q=0.5',
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.error('Scrape failed:', response.status, response.statusText);
|
|
return res.status(response.status).json({ error: `Failed to fetch: ${response.status} ${response.statusText}` });
|
|
}
|
|
|
|
const html = await response.text();
|
|
debugLog('Scraped HTML length:', html.length);
|
|
res.type('text/html').send(html);
|
|
} catch (error) {
|
|
console.error('Scrape proxy error:', error);
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`Proxy server running on http://localhost:${PORT}`);
|
|
});
|