使用deno和oak创建短链应用v1.0

在本文中,我们将学习Deno的基础知识,比如如何运行程序和接受安全性。

Deno是用Rust编写的新的JavaScript和TypeScript运行时。它提供了严格的安全性、开箱即用的typescript支持、运行它的单个可执行文件,以及一组经过审查和审核的标准模块。

与Node.js中的npm一样,Deno中的包也是在名为X的集中包存储库中管理的。我们将使用其中一个库Oak在Deno中构建一个基于rest API的服务器。

在使用类似Express的路由器软件包OAK,学习了基础知识之后,我们将跳到Deno的最深端,构建一个完整的应用程序。

下面是我们将在此应用程序中设置的内容:

  1. 使用基于JSON的配置文件将URL快捷码映射到端点。
  2. 在每个URL上附加过期日期,使这些重定向只在有限的时间内有效。

0. 准备工作

1.从此链接安装DENO。
2.确保您了解JavaScript的基础知识。

那么,让我们开始吧。

1. 如何构建路由器。

要为我们的应用程序编写服务器端代码,我们将使用Oak模块。它具有类似Express的语法,用于定义API路由。

如果我们看一下它的这里的文档Basic Usage部分几乎涵盖了我们路由器中需要的所有用例。因此,我们将扩展该代码以构建我们的应用程序。

要测试此代码,您可以在文件夹中创建一个名为index.ts的文件,然后将基本用法代码复制到其中。

要了解如何在Deno中运行TypeScript或JavaScript文件,您首先需要了解Deno如何运行文件。

运行文件的方法是运行命令deno run file_name.tsfile_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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容