/**
* Cloudflare Worker — прокси для Qtickets API
*
* Деплой: https://dash.cloudflare.com → Workers → Create → вставь этот код
*
* Переменные окружения (Settings → Variables):
* QTICKETS_TOKEN — Bearer-токен из личного кабинета Qtickets
* ALLOWED_ORIGIN — домен дашборда, например https://yourdomain.github.io
* или * для разрешения любых источников
*/
const QTICKETS_BASE = 'https://qtickets.ru/api/rest/v1';
export default {
async fetch(request, env) {
const url = new URL(request.url);
// ── CORS preflight ──────────────────────────────────────────────────────
const origin = request.headers.get('Origin') || '*';
const allowed = env.ALLOWED_ORIGIN || '*';
const corsOk = allowed === '*' || origin === allowed;
const corsHeaders = {
'Access-Control-Allow-Origin': corsOk ? origin : allowed,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Accept, Cache-Control',
'Access-Control-Max-Age': '86400',
};
if (request.method === 'OPTIONS') {
return new Response(null, { status: 204, headers: corsHeaders });
}
// ── Auth check ──────────────────────────────────────────────────────────
if (!env.QTICKETS_TOKEN) {
return new Response(
JSON.stringify({ error: 'QTICKETS_TOKEN env variable not set' }),
{ status: 500, headers: { 'Content-Type': 'application/json', ...corsHeaders } }
);
}
// ── Build upstream URL ──────────────────────────────────────────────────
// Worker URL: /events/123 → qtickets.ru/api/rest/v1/events/123
const path = url.pathname + url.search; // e.g. /events or /shows/41/seats
const upstreamUrl = QTICKETS_BASE + path;
// ── Forward request ──────────────────────────────────────────────────────
const body = ['GET', 'HEAD'].includes(request.method) ? undefined : await request.text();
const upstreamResp = await fetch(upstreamUrl, {
method: request.method,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Authorization': `Bearer ${env.QTICKETS_TOKEN}`,
},
body: body || undefined,
});
const respBody = await upstreamResp.text();
return new Response(respBody, {
status: upstreamResp.status,
headers: {
'Content-Type': upstreamResp.headers.get('Content-Type') || 'application/json',
'Cache-Control': 'public, max-age=3600', // кэш на 1 час на CF edge
...corsHeaders,
},
});
},
};