Skip to content

Commit 4436cb2

Browse files
committed
Update proxy base routing and CLI output
1 parent c344b7a commit 4436cb2

9 files changed

Lines changed: 43 additions & 32 deletions

File tree

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
POE_API_KEY=your-poe-api-key-from-https://poe.com/api_key
22
TARGET_URL=https://api.poe.com
3+
TARGET_PORT=
34
PROXY_HOST=localhost
45
PROXY_PORT=8000

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Point your LLM client to the proxy instead of the API directly:
1818

1919
```bash
2020
# Instead of: https://api.openai.com/v1/chat/completions
21-
# Use: http://localhost:8000/proxy/v1/chat/completions
21+
# Use: http://localhost:8000/v1/chat/completions
2222
```
2323

2424
View logged requests at `http://localhost:8000/viewer`
@@ -27,7 +27,7 @@ View logged requests at `http://localhost:8000/viewer`
2727

2828
| Route | Description |
2929
|-------|-------------|
30-
| `/proxy/*` | Forwards requests to target API |
30+
| `/*` | Forwards requests to target API |
3131
| `/viewer` | Web UI to inspect logged requests |
3232

3333
## Configuration

scripts/verify-anthropic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const proxyUrl = `http://${proxyHost}:${proxyPort}`;
2727
async function main() {
2828
console.log(`Testing proxy at ${proxyUrl}\n`);
2929

30-
const response = await fetch(`${proxyUrl}/proxy/v1/messages`, {
30+
const response = await fetch(`${proxyUrl}/v1/messages`, {
3131
method: 'POST',
3232
headers: {
3333
'Content-Type': 'application/json',

scripts/verify-openai.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const proxyUrl = `http://${proxyHost}:${proxyPort}`;
2727
async function main() {
2828
console.log(`Testing proxy at ${proxyUrl}\n`);
2929

30-
const response = await fetch(`${proxyUrl}/proxy/v1/chat/completions`, {
30+
const response = await fetch(`${proxyUrl}/v1/chat/completions`, {
3131
method: 'POST',
3232
headers: {
3333
'Content-Type': 'application/json',

src/cli.js

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,39 +40,46 @@ async function main() {
4040
}
4141

4242
let providerLabel = 'unknown';
43+
let resolvedTargetUrl = targetUrl;
44+
let parsedTarget;
4345
try {
44-
const parsedTarget = new URL(targetUrl);
45-
providerLabel = parsedTarget.hostname || parsedTarget.host || 'unknown';
46+
parsedTarget = new URL(targetUrl);
4647
} catch {
4748
throw new Error('TARGET_URL must be a valid URL (e.g. https://api.openai.com)');
4849
}
4950

51+
if (process.env.TARGET_PORT) {
52+
const targetPort = parseInt(process.env.TARGET_PORT, 10);
53+
if (!Number.isFinite(targetPort) || targetPort <= 0 || targetPort > 65535) {
54+
throw new Error('TARGET_PORT must be a valid TCP port (1-65535)');
55+
}
56+
parsedTarget.port = String(targetPort);
57+
resolvedTargetUrl = parsedTarget.toString();
58+
}
59+
60+
providerLabel = parsedTarget.hostname || parsedTarget.host || 'unknown';
61+
5062
const config = {
5163
host: proxyHost,
5264
port: portNumber,
5365
outputDir: getLogsDir(),
54-
targetUrl,
66+
targetUrl: resolvedTargetUrl,
5567
provider: providerLabel,
5668
};
5769

5870
intro('llm-debugger');
59-
log.info(`Target: ${targetUrl}`);
71+
log.info(`Target: ${resolvedTargetUrl}`);
6072

6173
const endpointSummary = [
62-
`Proxy URL: http://${proxyHost}:${proxyPort}`,
63-
`Proxy Route: http://${proxyHost}:${proxyPort}/proxy/*`,
64-
`Viewer: http://${proxyHost}:${proxyPort}/viewer`,
65-
`Logs: ${config.outputDir}`,
66-
`Client Base: http://${proxyHost}:${proxyPort}`,
67-
`Target Host: ${providerLabel}`,
74+
`Proxy: http://${proxyHost}:${proxyPort}/* to ${resolvedTargetUrl}`,
6875
].join('\n');
6976

7077
const startSpinner = spinner();
7178
startSpinner.start('Starting server');
7279

7380
createServer(config, {
7481
onListen: () => {
75-
startSpinner.stop(`Server listening on ${proxyHost}:${proxyPort}`);
82+
startSpinner.stop(`Server listening on http://${proxyHost}:${proxyPort}/viewer`);
7683
note(endpointSummary, 'Endpoints');
7784
},
7885
});
@@ -88,6 +95,7 @@ Options:
8895
--proxy-host <host> Proxy host (default: localhost)
8996
--proxy-port <port> Proxy port (default: 8000)
9097
--target <url> Base target URL for proxying (required)
98+
--target-port <port> Override target URL port
9199
--home <dir> Base directory for config/logs
92100
--config <path> Path to config.yaml
93101
--logs <dir> Log output directory
@@ -139,6 +147,7 @@ function applyCliEnv(flags) {
139147
if (flags['proxy-host']) process.env.PROXY_HOST = String(flags['proxy-host']);
140148
if (flags['proxy-port']) process.env.PROXY_PORT = String(flags['proxy-port']);
141149
if (flags.target) process.env.TARGET_URL = String(flags.target);
150+
if (flags['target-port']) process.env.TARGET_PORT = String(flags['target-port']);
142151
}
143152

144153
function runInit(force) {

src/routes/viewer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ export function createViewerRouter(config) {
77

88
router.get('/', controller.index);
99
router.get('/:provider/:filename', controller.detail);
10+
router.all('*', (req, res) => {
11+
res.status(404).json({ error: 'Not found' });
12+
});
1013

1114
return router;
1215
}

src/server.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,18 @@ export function createServer(config, { onListen } = {}) {
4242
}
4343
};
4444

45-
app.all('/proxy', async (req, res) => {
46-
res.redirect(307, '/proxy/');
45+
app.all('/proxy', (req, res) => {
46+
res.redirect(307, '/');
4747
});
48-
app.all('/proxy/', handleProxy);
49-
app.all('/proxy/*', handleProxy);
50-
51-
// Catch-all for other routes
52-
app.all('*', async (req, res) => {
53-
if (shouldIgnoreRoute(req.path)) {
54-
res.status(404).json({ error: 'Not found' });
55-
return;
56-
}
57-
res.status(404).json({ error: 'Not found' });
48+
app.all('/proxy/*', (req, res) => {
49+
const originalUrl = req.originalUrl || req.url || '';
50+
const stripped = originalUrl.replace(/^\/proxy/, '') || '/';
51+
res.redirect(307, stripped.startsWith('/') ? stripped : `/${stripped}`);
5852
});
5953

54+
// Catch-all: proxy everything else
55+
app.all('*', handleProxy);
56+
6057
const server = app.listen(config.port, () => {
6158
if (typeof onListen === 'function') {
6259
onListen(server);
@@ -78,12 +75,10 @@ function isStreamingRequest(req) {
7875
}
7976

8077
function getProxyPath(req) {
81-
const prefix = '/proxy';
8278
const originalUrl = req.originalUrl || req.url || '';
83-
let stripped = originalUrl.startsWith(prefix) ? originalUrl.slice(prefix.length) : originalUrl;
84-
if (!stripped) stripped = '/';
85-
if (stripped.startsWith('?')) return `/${stripped}`;
86-
return stripped.startsWith('/') ? stripped : `/${stripped}`;
79+
if (!originalUrl) return '/';
80+
if (originalUrl.startsWith('?')) return `/${originalUrl}`;
81+
return originalUrl.startsWith('/') ? originalUrl : `/${originalUrl}`;
8782
}
8883

8984
function buildTargetUrl(baseUrl, path) {

src/templates/viewer-detail.ejs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@
160160
.url {
161161
font-family: "JetBrains Mono", monospace;
162162
font-size: 0.9rem;
163+
color: var(--ink);
164+
font-weight: 600;
163165
word-break: break-all;
164166
margin-top: 6px;
165167
}

src/templates/viewer.ejs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@
227227
font-family: "JetBrains Mono", monospace;
228228
font-size: 0.85rem;
229229
color: var(--ink);
230+
font-weight: 600;
230231
max-width: min(620px, 100%);
231232
overflow: hidden;
232233
text-overflow: ellipsis;

0 commit comments

Comments
 (0)