文档中心 边缘应用 短链接(网址)分享

短链接(网址)分享

更新时间:2023-11-30 11:03:30

本章示例为基于『边缘KV』+『边缘函数』,实现短链接应用管理及分享。
代码说明:短链接(Short URL)是一种通过缩短网页链接长度来方便分享的技术。首先,长链接会生成对应的短链接地址。而后,用户分享短链,被分享方点击具体短链地址,将重定向到指定的长链接。

详细代码

const md5 = require('./lib-md5.js')

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(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('请输入合法的长链接!')
    }

    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 = `
<html>
<head>
<title>短链生成与查询</title>
<style>
body {
font-family: Arial, sans-serif;
}
h1 {
color: #333;
text-align: center;
}
.container {
max-width: 400px;
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>短链生成与查询</h1>
<input type="text" id="urlInput" placeholder="输入长链接">
<br><br>
<button class="btn" onclick="createShortLink()">重新生成</button>
<button class="btn" onclick="searchShortLink()">查询</button>
<button class="btn" onclick="deleteShortLink()">删除</button>
<div class="response">
<p id="responseText"></p>
</div>
<p style="color:gray">链接仅用于测试,5分钟后将自动失效</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 = "操作失败:" + 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))
})

注:我司不作为短链生成服务商。这里更多演示,分享型业务接入边缘函数和边缘KV的好处。

本篇文档内容对您是否有帮助?
有帮助
我要反馈
提交成功!非常感谢您的反馈,我们会继续努力做到更好!