/**
* CLOUDFLARE WORKER URL SHORTENER
* Features: UI, API, KV Storage, Anti-Bot, Auto-Detect Domain
*/
const htmlDisplay = `
Linknow.id - Shorten Your Links
Linknow.id
Secure. Fast. Untraceable.
...
`;
// Halaman Anti-Bot (Cloaking)
const cloakingHtml = (encodedUrl) => `
Loading...
`;
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const path = url.pathname;
// 1. TAMPILAN UTAMA (HOME)
if (path === '/' && request.method === 'GET') {
return new Response(htmlDisplay, {
headers: { 'Content-Type': 'text/html' },
});
}
// 2. API CREATE LINK
if (path === '/api/create' && request.method === 'POST') {
try {
const body = await request.json();
let alias = body.alias ? body.alias.trim() : '';
const longUrl = body.url;
// Validasi
if (!longUrl || !longUrl.startsWith('http')) {
return new Response(JSON.stringify({
status: 'error',
message: 'URL tidak valid'
}), {
headers: { 'Content-Type': 'application/json' }
});
}
// Generate Alias jika kosong
if (!alias) {
alias = Math.random().toString(36).substring(2, 8);
} else {
// Bersihkan alias - PERBAIKI REGEX INI
alias = alias.replace(/[^a-zA-Z0-9-_]/g, "");
}
// Cek database KV
const existing = await env.LINKS.get(alias);
if (existing) {
return new Response(JSON.stringify({
status: 'error',
message: 'Alias sudah dipakai!'
}), {
headers: { 'Content-Type': 'application/json' }
});
}
// Simpan ke KV (Key = Alias, Value = Long URL)
await env.LINKS.put(alias, longUrl);
// AUTO DETECT DOMAIN
const shortUrl = `${url.origin}/${alias}`;
return new Response(JSON.stringify({
status: 'success',
short_url: shortUrl
}), {
headers: { 'Content-Type': 'application/json' }
});
} catch (err) {
return new Response(JSON.stringify({
status: 'error',
message: 'Server Error: ' + err.message
}), {
headers: { 'Content-Type': 'application/json' }
});
}
}
// 3. HANDLE REDIRECT (Get Alias)
const aliasKey = path.substring(1); // Hapus slash depan
if (aliasKey && aliasKey !== 'api') {
const destination = await env.LINKS.get(aliasKey);
if (destination) {
// Encode URL untuk Anti-Bot
const encoded = btoa(encodeURIComponent(destination));
return new Response(cloakingHtml(encoded), {
headers: { 'Content-Type': 'text/html' }
});
}
}
// 4. JIKA TIDAK DITEMUKAN (404)
return new Response('Link Not Found', {
status: 404,
headers: { 'Content-Type': 'text/html' }
});
}
};