The /vncproxy endpoint requires websocket: 0 (not -1) in the POST body. Co-Authored-By: Claude <noreply@anthropic.com>
46 lines
1.5 KiB
JavaScript
46 lines
1.5 KiB
JavaScript
import { NextResponse } from 'next/server';
|
|
import axios from 'axios';
|
|
|
|
const PROXMOX_API_URL = process.env.PROXMOX_API_URL;
|
|
const PROXMOX_WEB_URL = process.env.PROXMOX_WEB_URL || PROXMOX_API_URL?.replace('/api2/json', '');
|
|
|
|
/** @param {import('next').Request} req */
|
|
export async function GET(req) {
|
|
const url = new URL(req.url);
|
|
const node = url.searchParams.get('node');
|
|
const vmid = url.searchParams.get('vmid');
|
|
const type = url.searchParams.get('type');
|
|
|
|
if (!node || !vmid || !type) {
|
|
return NextResponse.json({ error: 'Missing node, vmid, or type' }, { status: 400 });
|
|
}
|
|
|
|
try {
|
|
const ticketRes = await axios({
|
|
url: `${PROXMOX_API_URL}/nodes/${node}/${type}/${vmid}/vncproxy`,
|
|
method: 'POST',
|
|
headers: {
|
|
Authorization: `PVEAPIToken=${process.env.PROXMOX_TOKEN_ID}=${process.env.PROXMOX_TOKEN_SECRET}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
data: JSON.stringify({ websocket: 0 }),
|
|
});
|
|
|
|
const ticket = ticketRes.data?.ticket;
|
|
|
|
if (!ticket) {
|
|
return NextResponse.json(
|
|
{ error: 'No VNC ticket returned from Proxmox API' },
|
|
{ status: 502 },
|
|
);
|
|
}
|
|
|
|
const consoleUrl = `${PROXMOX_WEB_URL}/?vncticket=${encodeURIComponent(ticket)}&novnc=1&node=${encodeURIComponent(node)}&vmid=${vmid}`;
|
|
|
|
return NextResponse.json({ consoleUrl });
|
|
} catch (err) {
|
|
const msg = err.response?.data?.message || err.response?.data || err.message;
|
|
return NextResponse.json({ error: msg }, { status: 502 });
|
|
}
|
|
}
|