export default { async fetch(request, env) { // 1. Get the requested path from the URL const url = new URL(request.url); const cleanPath = decodeURIComponent(url.pathname).replace(/^\/+|\/+$/g, ''); // 2. Query GitHub Contents API for this path // (Replace these with your actual GitHub username and repository name) const GITHUB_OWNER = 'Doume-20'; const GITHUB_REPO = 'dl.20.doume.be'; const GITHUB_BRANCH = 'main'; const apiUrl = `https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents/${cleanPath}?ref=${GITHUB_BRANCH}`; const headers = { 'User-Agent': 'Cloudflare-Worker-Dir-Listing', 'Accept': 'application/vnd.github.v3+json', }; // If your repo is private, add your token via: npx wrangler secret put GITHUB_TOKEN if (env && env.GITHUB_TOKEN) { headers['Authorization'] = `Bearer ${env.GITHUB_TOKEN}`; } const ghRes = await fetch(apiUrl, { headers, cf: { cacheTtl: 60, cacheEverything: true } }); if (!ghRes.ok) { return new Response(`Not Found (${ghRes.status})`, { status: ghRes.status }); } const data = await ghRes.json(); // 3. If it's a file, stream its raw content directly from GitHub (bypassing 25MB limits) if (!Array.isArray(data)) { if (data.download_url) { const fileRes = await fetch(data.download_url, { headers }); const respHeaders = new Headers(fileRes.headers); respHeaders.delete('content-security-policy'); return new Response(fileRes.body, { status: fileRes.status, headers: respHeaders }); } return new Response('Unable to download file', { status: 400 }); } // 4. If it's a directory, sort and build the WordPress-style HTML list data.sort((a, b) => (a.type === b.type ? a.name.localeCompare(b.name) : a.type === 'dir' ? -1 : 1)); const displayPath = '/' + cleanPath; const rows = data.map(item => { const isDir = item.type === 'dir'; const href = `/${cleanPath ? cleanPath + '/' : ''}${encodeURIComponent(item.name)}${isDir ? '/' : ''}`; return `
  • ${item.name}${isDir ? '/' : ''}
  • `; }).join(''); const html = ` Index of ${displayPath}

    Index of ${displayPath}

    `; return new Response(html, { headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } };