const md5 = require('./lib-md5.js')
import { englishPage } from "./language"
async function handleRequest(request) {
let {pathname} = new URL(request.url)
pathname = pathname.toLowerCase()
if (pathname.endsWith('/')) {
pathname = pathname.substring(0, pathname.length - 1);
}
if (pathname === '/shortlink.html') {
return new Response(englishPage(request) ? HOMEPAGE_EN : HOMEPAGE, {headers: {"Content-Type": "text/html; charset=utf-8"}})
} else if (pathname === '/shortlink') {
return handleOperationShortLink(request)
} else if (pathname.startsWith('/s/')) {
return handleVisitShortLink(request)
}
}
const NS_SHORT_LINK = "short_link_1"
const NS_LONG_LINK = "long_link_2"
async function handleOperationShortLink(request) {
const body = await request.json()
const longLink = body.url
if (!isValidUrl(longLink)) {
return new Response('Please enter a valid long URL!')
}
const { protocol, host } = new URL(request.url)
const spShortLink = new EdgeKV({namespace: NS_SHORT_LINK})
const spLongLink = new EdgeKV({namespace: NS_LONG_LINK})
const md5LongLink = md5(protocol + host + longLink)
let shortLink = await spLongLink.get(md5LongLink)
if (body.action === 'create') {
if (shortLink) {
await spShortLink.delete(shortLink)
await spLongLink.delete(md5LongLink)
}
shortLink = `${protocol}//${host}/s/` + md5(`${Date.now()}-${Math.random()}-${body.url}`).substring(0, 16).toLowerCase()
const expiration = Math.floor(new Date().getTime() / 1000) + 300 // 5分钟后自动失效
await spLongLink.put(md5LongLink, shortLink, {expiration: expiration})
await spShortLink.put(shortLink, longLink, {expiration: expiration})
return new Response(shortLink)
} else if (body.action === 'search') {
if (shortLink) {
return new Response(shortLink)
} else {
return new Response('Short link not exist!', {status: 500})
}
} else if (body.action === 'delete') {
const shortLink = await spLongLink.get(md5LongLink)
if (shortLink) {
await spShortLink.delete(shortLink)
await spLongLink.delete(md5LongLink)
return new Response('Delete success')
} else {
return new Response('Short link not exist!', {status: 500})
}
} else {
return new Response('Bad request', {status: 400})
}
}
async function handleVisitShortLink(request) {
let shortLink = request.url
if (shortLink.endsWith('/')) {
shortLink = shortLink.substring(0, shortLink.length - 1)
}
const spShortLink = new EdgeKV({namespace: NS_SHORT_LINK})
const longLink = await spShortLink.get(shortLink)
if (longLink) {
return Response.redirect(longLink)
} else {
return new Response("Page not found", {status: 404})
}
}
function isValidUrl(url) {
const urlRegex = /^(https?|ftp):\/\/([a-z0-9-]+\.)+[a-z]{2,}(:\d{1,5})?(\/[^\s]*)?$/i;
return urlRegex.test(url);
}
const HOMEPAGE_EN = `
<html>
<head>
<title>Short Link Generation and Query</title>
<style>
body {
font-family: Arial, sans-serif;
}
h1 {
color: #333;
text-align: center;
}
.container {
max-width: 500px;
margin: 0 auto;
}
input[type="text"] {
width: 100%;
height: 40px;
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
}
.btn {
display: inline-block;
padding: 10px 20px;
background-color: #333;
color: #fff;
font-size: 16px;
border: none;
cursor: pointer;
}
.response {
margin-top: 20px;
border: 1px solid #ccc;
padding: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>Short Link Generation and Query</h1>
<input type="text" id="urlInput" placeholder="Enter long URL">
<br><br>
<button class="btn" onclick="createShortLink()">Generate</button>
<button class="btn" onclick="searchShortLink()">Search</button>
<button class="btn" onclick="deleteShortLink()">Delete</button>
<div class="response">
<p id="responseText"></p>
</div>
<p style="color:gray">The short link is for testing purposes only and will expire in 5 minutes.</p>
</div>
<script>
function shortLink(action) {
var url = document.getElementById("urlInput").value;
var data = JSON.stringify({ action: action, url: url });
var xhr = new XMLHttpRequest();
xhr.open("POST", "/shortlink/");
xhr.setRequestHeader("Content-type", "application/json");
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
document.getElementById("responseText").innerHTML = xhr.responseText;
} else {
document.getElementById("responseText").innerHTML = "Operation failed: " + xhr.responseText;
}
}
};
xhr.send(data);
}
function createShortLink() {
shortLink("create")
}
function searchShortLink() {
shortLink("search")
}
function deleteShortLink() {
shortLink("delete")
}
</script>
</body>
</html>
`;
addEventListener("fetch", event => {
return event.respondWith(handleRequest(event.request))
})