「shURL 短网址」 Github 仓库
欢迎使用 shURL \texttt{shURL} shURL ! 这是 shURL \texttt{shURL} shURL 工具的使用文档。
综述 此工具为一「短网址」工具。
何为短网址?简单来讲,就是以工具将原网址缩短长度,使访问更加便捷。
举个简单的例子:
原网址:https://www.bilibili.com/video/BV1DK4y1z7wq/?vd_source=c2c603cbba8a549035c5aaed2e9faa97 短网址:https://daoxi365.dpdns.org/?x=pkCf
显然,它实现链接转换是需要后端服务器、数据库的。但是,此工具选择了基于 LeanCloud 的线上储存,因此可以运行于静态网站,如 Github Pages
、Netlify
等。
操作步骤 注册或登录一个 LeanCloud 帐号。LeanCloud 账号分为国际、国内两种,如果你使用国外网络环境或用户面向国外,推荐使用国际版 。反之,则建议使用国内版。 本网站当前使用国内版 LeanCloud,可大幅提升访问速度。但是注册国内版 LeanCloud 账号需要实名认证。
创建一个新应用。应用名称随便写;计价方案选择开发版,否则会被收费。
进入刚刚创建的应用,左侧边栏下划到最后,在“设置”中找到“应用凭证”,在右侧按如图方式复制凭证信息。 注意:第四步 国内版 用户必须保留。国际版用户可以不使用此 rest api 地址。
打开 /js/app.js
,按注释(绿字)要求修改相关内容。
本地测试。 如果有 Python 环境,可以使用以下命令打开一个开发环境:
1 2 python -m http.server 8000 # 接下来你可以在 127 .0 .0 .1 :8000 访问到你的页面。
关于个性化:
您可以修改 media
文件夹下的网站图标(favicon.ico
)和标志(logo.png
)。 您可以自行修改网页样式,但是我希望您能保留帮助文档的链接。 push 到远端。打开 pages 服务或用其他平台发布。
修改安全网址。
测试,完成。
补充 您可以在结构化数据控制台 上增、删短网址。
原理解析 shURL 是我最初认识 LeanCloud 和 tailwindcss 的项目。以上技术栈均在原理中涉及。
shURL 的原理是建立一个长网址与随机字符串的映射关系,并存储在 LeanCloud 数据库中。
也就是说,用户每次提交原网址,shURL 都会生成一个随机字符串,并将其与长网址映射,存储在 LeanCloud 数据库中。每当用户将字符串通过接口传入 shURL 时,就会依据数据库存储重定向到原网址。
拆解 app.js
初始化 LC 对象,检测是否有 shURL
类:
1 2 3 4 5 6 7 AV .init ({ appId : APPID , appKey : APPKEY , serverURL : REST_API , }); AV .debug .enable ();const SHURL = AV .Object .extend ("shURL" );
这是一个创建最大长度为 48 48 4 8 的随机字符串的方法。该字符串就是待生成的短网址链接代号。
1 2 3 4 5 6 7 8 9 10 function randomStr (len ) { if (len > 48 ) len = 48 ; var $chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678" ; var maxPos = $chars.length ; var pwd = "" ; for (var i = 0 ; i < len; i++) { pwd += $chars.charAt (Math .floor (Math .random () * maxPos)); } return pwd; }
在前端给出提示的方法:
1 2 3 4 function setNote (s ) { var x = document .getElementById ("newURL" ); x.innerHTML = s; }
检测是否已经存在用户给出的原长网址的方法。如果有就返回其长度。
1 2 3 4 5 6 7 function checker (s ) { const query = new AV .Query ("shURL" ); query.equalTo ("shortURL" , s); query.find ().then ((link ) => { return link.length ; }); }
生成短网址的方法。首先检测是否符合 URL 格式,然后检查是否已经存在该长网址的短网址,如果有就直接返回,否则生成随机字符串,并上传到数据库,同时把短网址返回到前端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 function make ( ) { try { var ago = document .getElementById ("ago" ); var agoURL = ago.value ; var pattern = /^((ht|f)tps?):\/\/([\w\-]+(\.[\w\-]+)*\/)*[\w\-]+(\.[\w\-]+)*\/?(\?([\w\-\.,@?^=%&:\/~\+#]*)+)?/ ; if (!pattern.test (agoURL)) { setNote ( '<b class="text-purple-700">您的输入似乎不是 URL,请重新输入。</b>' ); return ; } setNote (`<b class="text-state-800">请稍等!</b>` ); const query = new AV .Query ("shURL" ); query.equalTo ("agoURL" , agoURL); query.find ().then ((link ) => { if (link.length >= 1 ) { flag = true ; var shLink = link[0 ].get ("shortURL" ); var shURL = `${WEBSITE} /` + (GITHUB ? `${GITHUB_REPOSITORY} /` : `` ) + `?x=${shLink} ` ; setNote ( `<b><a href="${shURL} " class="text-blue-700 hover:text-blue-800"><code>${shURL} </code></a></b>` ); return ; } else { var shLink = randomStr (LENGTH ); while (checker (shLink)) shLink = randomStr (LENGTH ); const todo = new SHURL (); todo.set ("agoURL" , agoURL); todo.set ("shortURL" , shLink); todo.save ().then ( (todo ) => { var shURL = `${WEBSITE} /` + (GITHUB ? `${GITHUB_REPOSITORY} /` : `` ) + `?x=${shLink} ` ; setNote ( `<b><a href="${shURL} " class="text-blue-700 hover:text-blue-800"><code>${shURL} </code></a></b>` ); }, (error ) => { setNote ( `<b class="text-rose-600">发生错误(<code>CODE = ${error.code} </code>),请稍后再试。</b>` ); } ); } }); } catch (err) { setNote ( `<b class="text-rose-600">发生错误(<code>${err} </code>),请稍后再试。</b>` ); } }
如果用户给出了短网址,则需要根据数据库查询原来的长网址,并重定向到原网址。若不存在则报错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 function getName (name ) { var reg = new RegExp ("(^|&)" + name + "=([^&]*)(&|$)" , "i" ); var r = window .location .search .substr (1 ).match (reg); var context = "" ; if (r != null ) context = r[2 ]; reg = null ; r = null ; return context == null || context == "" || context == "undefined" ? "ERROR ERROR ERROR!!!" : context; } function loadTo ( ) { try { var x = getName ("x" ); if (x == "ERROR ERROR ERROR!!!" ) return ; var w = `${WEBSITE} /` + (GITHUB ? `${GITHUB_REPOSITORY} /` : `` ); setNote ( `<b class="text-amber-700">正在跳转:<code>${x} </code>;<a href="${w} " class="text-sky-600 hover:text-sky-700">取消此操作</a>。</b>` ); const query = new AV .Query ("shURL" ); query.equalTo ("shortURL" , x); query.find ().then ((link ) => { if (!link.length ) setNote ( `<b class="text-rose-600">发生错误,此链接尚未被注册或在数据库中被删除。</b>` ); window .location .href = link[0 ].get ("agoURL" ); }); } catch (err) { setNote ( `<b class="text-rose-600">发生错误(<code>${err} </code>),请稍后再试。</b>` ); } }
创建一个 SHURL
对象,完成初始化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const initial = new SHURL ();try { const query = new AV .Query ("shURL" ); } catch (err) { initial.set ("agoURL" , "index" ); initial.set ("shortURL" , "index1" ); initial.save ().then ( (todo ) => {}, (error ) => { setNote ( `<b class="text-rose-600">初始化失败(<code>CODE = ${err.code} </code>),请联系网站开发者。</b>` ); } ); }
关于前端 前端使用的是 tailwindcss 作为 CSS 框架。确实好使。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <!DOCTYPE html > <html > <head > <meta charset ="utf-8" /> <title > shURL 短网址</title > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" /> <link rel ="shortcut icon" href ="./media/favicon.ico" /> <script src ="./js/leancloud-javascript-sdk-6f78e1c/dist/av-min.js" > </script > <script src ="./js/tailwindcss_v3.4.1.js" > </script > </head > <body > <div class ="flex flex-col items-center justify-center h-screen bg-sky-100" > <img src ="./media/logo.png" alt ="logo" class ="w-20 h-auto mb-8 rounded-lg" /> <form action ="javascript:make();" class ="flex items-center justify-center w-1/2 bg-white rounded-full shadow-xl" > <input type ="text" placeholder ="转换为短网址" id ="ago" class ="w-full px-4 py-2 rounded-l-full focus:outline-none" /> <button type ="submit" class ="flex items-center justify-center px-4 py-2 text-white bg-emerald-700 rounded-r-full hover:bg-emerald-900 focus:outline-none" > <b > Go!</b > </button > </form > <br /> <br /> <p id ="newURL" > <a class ="text-teal-500 hover:text-teal-600" href ="https://blog.daoxi365.top/posts/43801/" > <b > 帮助文档:我也想创建一个这样的网站。</b > </a > </p > </div > <script src ="./js/app.js" > </script > <script > loadTo(); </script > </body > </html >