使用deno和oak创建短链应用v1.0
在本文中,我们将学习Deno的基础知识,比如如何运行程序和接受安全性。
Deno是用Rust编写的新的JavaScript和TypeScript运行时。它提供了严格的安全性、开箱即用的typescript支持、运行它的单个可执行文件,以及一组经过审查和审核的标准模块。
与Node.js中的npm一样,Deno中的包也是在名为X的集中包存储库中管理的。我们将使用其中一个库Oak在Deno中构建一个基于rest API的服务器。
在使用类似Express的路由器软件包OAK,学习了基础知识之后,我们将跳到Deno的最深端,构建一个完整的应用程序。
下面是我们将在此应用程序中设置的内容:
- 使用基于JSON的配置文件将URL快捷码映射到端点。
- 在每个URL上附加过期日期,使这些重定向只在有限的时间内有效。
0. 准备工作
1.从此链接安装DENO。
2.确保您了解JavaScript的基础知识。
那么,让我们开始吧。
1. 如何构建路由器。
要为我们的应用程序编写服务器端代码,我们将使用Oak模块。它具有类似Express的语法,用于定义API路由。
如果我们看一下它的这里的文档,Basic Usage部分几乎涵盖了我们路由器中需要的所有用例。因此,我们将扩展该代码以构建我们的应用程序。
要测试此代码,您可以在文件夹中创建一个名为index.ts
的文件,然后将基本用法代码复制到其中。
要了解如何在Deno中运行TypeScript或JavaScript文件,您首先需要了解Deno如何运行文件。
运行文件的方法是运行命令deno run file_name.ts
或file_name.js
,后跟一组为应用程序提供特定系统权限的标志。
要测试这一点,可以使用命令deno run index.ts
运行我们刚刚创建的包含基本用法代码的文件。
您将看到Deno抱怨您没有为您的应用程序授予网络访问权限。因此,要做到这一点,您需要在run命令中添加‘--allow-net
命令。该命令将类似于deno run index.ts --allow-net
。
写在“基本用法”代码中的路由器如下所示:
router
.get("/", (context) => {
context.response.body = "Hello world!";
})
.get("/book", (context) => {
context.response.body = Array.from(books.values());
})
.get("/book/:id", (context) => {
if (context.params && context.params.id && books.has(context.params.id)) {
context.response.body = books.get(context.params.id);
}
});
为了分解上面的代码,首先定义了一个名为“router的对象。然后在路由器上调用“
get`”函数,为我们的应用程序定义各种端点。相应的逻辑在回调函数中定义。
例如,对于“/”端点,定义了一个在响应正文中返回“Hello World”的回调函数。我们可以保持该端点不变,以通过接收此响应来测试我们的应用服务器是否正在运行。
我们不需要已经定义的“/book”URL,因此可以安全地删除它的定义。此时,您的路由器应该具有以下结构:
router
.get("/", (context) => {
context.response.body = "Hello world!";
})
.get("/book/:id", (context) => {
if (context.params && context.params.id && books.has(context.params.id)) {
context.response.body = books.get(context.params.id);
}
});
在下一节中,我们将重点介绍如何开始构建实际的应用程序。
2. 如何构建URL缩放器。
现在让我们开始构建实际的URL缩短器。
应该根据一个短码
重定向到一个目的地(dest
)。重定向也只能在expiryDate
之前有效,该expiryDate
可以按年-月-日的格式提供。
基于这些假设,我们创建一个配置文件,命名为:urls.json
。文件的格式为:
{
"shortcode": {
"dest": "destination_url_string",
"expiryDate": "YYYY-MM-DD"
}
}
您可以查看json文件。
要在代码中读取此JSON文件,请将以下代码添加到您的index.ts
文件的顶部:
import { Application, Router } from "<https://deno.land/x/oak/mod.ts>";
const urls = JSON.parse(Deno.readTextFileSync("./urls.json"));
console.log(urls);
现在,如果要运行您的index.ts
,您还需要另一个标志-allow-read
,否则Deno会抛出“未提供读取权限”的错误。您的最后一个命令变成了deno run --allow-net --allow-read index.ts
。
运行此命令后,您将在终端窗口中看到JSON文件正在打印。这意味着您的程序能够正确读取JSON文件。
如果我们回到上面看到的“基本用法”示例,路径“/book/:id”就是我们所需要的。
我们不使用/book/:id,而是使用/shrt/:urlid,我们将根据URL ID(:urlid
)获取各个URL。
将“/book/:id”路由中的现有代码替换为以下代码:
.get("/shrt/:urlid", (context) => {
if (context.params && context.params.urlid && urls[context.params.urlid]) {
context.response.redirect(urls[context.params.urlid].dest);
} else {
context.response.body = "404";
}
});
路由中的“if
条件”执行以下操作:
1.检查参数是否附加到路径。
2.检查参数列表中是否有urlid
参数。
3.检查urlid
地址是否与我们JSON中的任何URL匹配。
如果它与所有这些匹配,则将用户重定向到正确的URL。如果不是,则返回正文的404响应。
要进行测试,请将此路由复制到index.ts
中。路由器现在看起来如下所示:
router
.get("/", (context) => {
context.response.body = "Hello world!";
})
.get("/shrt/:urlid", (context) => {
if (context.params && context.params.urlid && urls[context.params.urlid]) {
context.response.redirect(urls[context.params.urlid].dest);
} else {
context.response.body = "404";
}
});
并使用deno run --allow-net --allow-read index.ts
运行该文件。
如果你复制了示例中的json文件,如果你转到http://localhost:8000/shrt/g
,,你会被重定向到谷歌的主页。
另一方面,如果您使用的随机短码在我们的URL配置中不起作用,它会将您带到404页面。
但是,您将看到我们的缩短器不会实时响应JSON文件中的更改。要测试这一点,请尝试添加一个新的重定向到与以下格式相同的urls.json
地址:
"shortcode": {
"dest": "destination_url_string",
"expiryDate": "YYYY-MM-DD"
}
这是因为在开始时,urls.json
文件只被读取一次。因此,现在我们将向我们的服务器添加实时重新加载。
3. 如何添加实时重载
要使“urls
”对象对JSON文件中的更改做出实时反应,我们只需将read语句移动到我们的路径中。这应该如下所示:
.get("/shrt/:urlid", (context) => {
const urls = JSON.parse(Deno.readTextFileSync("./urls.json"));
if (context.params && context.params.urlid && urls[context.params.urlid]) {
context.response.redirect(urls[context.params.urlid].dest);
} else {
context.response.body = "404";
}
});
请注意我们是如何在路由器内移动URL对象的。现在,在本例中,配置文件在每次调用该路由时都会被读取,因此它可以实时响应在urls.json
配置文件中所做的任何更改。因此,即使我们动态添加或删除其他重定向,我们的代码也会对此做出反应。
4. 如何向URL添加过期。
为了使我们的URL在某个日期过期,我们将使用流行的Moment.js库,它使得处理日期变得很容易。
幸运的是,它还被移植到DENO.。要了解它的工作原理,请查看前面链接中的文档。
要在我们的代码中使用它,请直接通过其URL导入它,如下所示:
import { Application, Router } from "<https://deno.land/x/oak/mod.ts>";
import { moment } from "<https://deno.land/x/deno_ts_moment/mod.ts>";
const router = new Router();
为了检查URL的过期日期,我们检查了我们的urls
对象上的‘expiryDate`密钥。这将使代码看起来如下所示:
if (context.params && context.params.urlid && urls[context.params.urlid]) {
if (
urls[context.params.urlid].expiryDate > moment().format("YYYY-MM-DD")
) {
context.response.redirect(urls[context.params.urlid].dest);
} else {
context.response.body = "Link Expired";
}
} else {
context.response.body = "404";
}
在Moment().format(“YYYY-MM-DD”)
中,我们使用Moment()
获取当前日期和时间。我们可以使用.format(“YYYY-MM-DD”)
函数将其转换为“YYYY-MM-DD”(年-月-日)格式。
通过与我们的expiryDate
密钥进行比对,可以查看URL是否过期。
就这样!。您已经在Deno中构建了一个功能齐全的URL缩短器。您可以在我的gitee仓库中找到最终代码。
通过将expiryDate
设置为当前日期,并对urls.json
和我们的代码进行其他更改来测试它。
我对deno的看法。
作为这篇文章的结束语,我将在deno.land上提出我的最终想法。
虽然看到服务器端语言将安全性考虑在内并支持开箱即用的文字脚本令人耳目一新,但Deno在投入生产系统之前还有很长的路要走。
例如,typescript编译仍然非常慢,编译时间约为20秒,即使对于我们刚刚开发的这样简单的程序也是如此。
在错误报告方面,描述错误仍然相当糟糕。例如,在函数本身中嵌入读取urls.json
的代码时,Deno无法报告没有设置--allow-read
命令标志。相反,它只是抛出一个内部服务器错误,而没有在终端上打印正确的错误。
接下来呢?
你可以通过构建更复杂的应用程序来提高你
您也可以在deno.land)上浏览Deno文档,以更熟悉基础知识。
感谢您阅读了这么远的内容,并祝您编程愉快?!!
重要链接
Deno - https://deno.land
Deno X (包仓库) - https://deno.land/x/
Oak (REST 框架) - https://deno.land/x/oak
Oak 基本应用 - https://deno.land/x/oak@v6.3.1#basic-usage
GitHub 仓库- https://github.com/akash-joshi/deno-url-shortener
Gitee 仓库 https://gitee.com/x_s_j/deno-url-shortener