使用 Cloudflare Workers 创建 URL 缩短器

冯风史
2023-12-01

您是否曾经使用过 Bitly 或 TinyURL 等工具来缩短长链接? 或者,您想知道这些服务是如何工作的吗? 也许您想构建一个 URL 缩短器,但从未找到时间或合适的工具来做这件事。 无论如何,如果您对此主题感兴趣,那么本文非常适合您。

在这篇文章中,我们将演示如何使用 Cloudflare Workers 构建基本的 URL 缩短服务。 我们将提供有关 URL 缩短服务如何工作的详细信息,介绍 Cloudflare Workers 的几个功能,并提供有关如何开始使用 Cloudflare Workers 的分步说明。

Cloudflare Workers?

Cloudflare Workers 是一项服务,可让您将无服务器代码部署到 Cloudflare 网络。 Cloudflare 网络或 Edge 是遍布全球的 Web 服务器网络。 Cloudflare Workers 的一大优点是您不必担心扩展代码。 此外,您不必担心代码所在的时区; 您在 Workers 中的代码在部署后的几秒钟内就会在全球范围内传播。

最重要的是,Cloudflare Workers 带有一个简单的键值对数据存储,称为 KV。 在本教程中,我们将结合使用 Cloudflare Workers 和 KV 存储来构建更短的 URL。

项目概述:URL 缩短服务

我们将首先构建一个简单的非动态 URL 缩短器,您可以在其中硬编码要重定向到的网站。 这将作为学习如何使用 Wrangler (Cloudflare 的官方 CLI 工具)的介绍,并将演示 Workers 领域的基本概念。

接下来,我们将增加一些趣味并添加对动态 URL 的支持。 基本上,我们将与 Cloudflare Workers KV 存储进行交互,并输入 URL 的简短版本和我们想要重定向到的实际 URL。 KV 存储中的数据将类似于以下结构:

'short-url': 'https://my-cool-website.com'
'submit': 'https://my-cool-site.org/blog/ideas/submit'

最后,我们会将我们的代码部署到生产环境中,并在全球范围内看到它的运行情况。

你已经兴奋了吗? 太好了,让我们跳进去!

设置环境

要继续阅读本文,您需要以下内容:

  • Node.js 和 npm

  • 牧马人

  • curl(或您选择的浏览器)来测试 URL 缩短器

我使用 asdf 工具 来管理我的本地依赖项,但您可以使用任何您喜欢的版本管理器。 在撰写本文时,这是我的 Node 和 npm 版本:

$ node --version
v18.5.0
$ npm --version
8.12.1

Wrangler 是一个用于构建的命令行工具,最近它有了 2.0 版本。 就本文而言,牧马人将满足我们的所有需求。 将来,我们可能会使用 Miniflare,它是 Wrangler 的一个更强大、功能更丰富的兄弟 。 但是,现在,让我们通过 npm 全局安装 Wrangler:

$ npm install -g wrangler@2.0.21

在撰写本文时,最新的 Wrangler 版本是 2.0.21,所以我们将使用那个版本。

凉爽的。 现在我们已经有了所有的依赖项,我们可以使用 Wrangler CLI 来生成我们的入门 Cloudflare Worker。

生成项目

Wrangler CLI 工具在这里将非常有用。

首先,让我们运行一个命令来正确启动和设置我们的项目:

$ wrangler init short-it

这个命令会问几个问题。 现在,我们将为所有这些回答是(通过输入 y ):

$ wrangler init short-it
  wrangler 2.0.21
--------------------
Using npm as package manager.
 Created short-it/wrangler.toml
Would you like to use git to manage this Worker? (y/n)
 Initialized git repository at short-it
No package.json found. Would you like to create one? (y/n)
 Created short-it/package.json
Would you like to use TypeScript? (y/n)
 Created short-it/tsconfig.json
Would you like to create a Worker at short-it/src/index.ts?
  None
❯ Fetch handler
  Scheduled handler
 Created short-it/src/index.ts
​
added 62 packages, and audited 63 packages in 1s
​
1 package is looking for funding
  run `npm fund` for details
​
found 0 vulnerabilities
 Installed @cloudflare/workers-types and typescript into devDependencies
​
To start developing your Worker, run `cd short-it && npm start`
To publish your Worker to the Internet, run `npm run deploy`

如果您对 Wrangler 提出的所有问题的回答都是肯定的,那么您将拥有一个项目名称 short-it, 里面有以下内容:

  • .git项目中的目录,这意味着您已准备好将其推送到您的 Git 提供程序

  • package.json文件

  • tsconfig.json包含所有 TypeScript 配置的文件

  • src/index.ts带有一些简单逻辑的文件以从我们的 Worker 中获得响应

惊人的。 让我们看看这个东西是否有效!

让我们 cd进入 short-it目录并以本地开发模式启动 Wrangler:

$ cd short-it
$ wrangler dev --local

上运行我们的 Worker 这应该在http://localhost:8787/ 。 如果我们访问 localhost,我们应该会看到一个简单的“Hello World!” 信息:

Generated Worker 显示“Hello World!” 信息。

耶! 我们让它工作。 但是怎么做? 让我们仔细看看。


超过 20 万开发人员使用 LogRocket 来创造更好的数字体验了解更多 →

Cloudflare Workers 如何工作?

我们从生成的 Worker 在本地获得了第一条消息,但它究竟是如何工作的呢?

我们来看看生成的 src/index.ts文件以更好地了解那里发生的事情。

// src/index.ts
​
/**
 * Welcome to Cloudflare Workers! This is your first worker.
 *
 * - Run `wrangler dev src/index.ts` in your terminal to start a development server
 * - Open a browser tab at http://localhost:8787/ to see your worker in action
 * - Run `wrangler publish src/index.ts --name my-worker` to publish your worker
 *
 * Learn more at https://developers.cloudflare.com/workers/
 */
​
export interface Env {
  // Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
  // MY_KV_NAMESPACE: KVNamespace;
  //
  // Example binding to Durable Object. Learn more at https://developers.cloudflare.com/workers/runtime-apis/durable-objects/
  // MY_DURABLE_OBJECT: DurableObjectNamespace;
  //
  // Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
  // MY_BUCKET: R2Bucket;
}
​
export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext
  ): Promise<Response> {
    return new Response("Hello World!");
  },
};

上面的代码包含了我们环境的定义( Env界面)和一些与 ENV界面。

由于接口超出了本文的范围,我们将忽略这部分代码,只关注主要逻辑:

// src/index.ts
​
export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext
  ): Promise<Response> {
    return new Response("Hello World!");
  },
};

这里发生的是我们的 index.ts出口一个 fetch功能。 这是一个类似于 Web Workers 的界面。 事实上,“Cloudflare Workers”这个名字就是从这个界面来的。 Cloudflare Workers 类似于 Web Workers,不同之处在于它运行在 Cloudflare 基础架构而不是浏览器上。

在上面的代码中, fetch函数返回一个新的 Response带有“Hello World!”的对象 文本。 所以当我们运行我们的 Worker 时,这个 fetch函数被调用。 然后,被调用的 fetch函数返回“Hello World!” 响应,这就是我们在浏览器中获取的(或通过任何用于调用 Worker 的工具)。

好的,我们已经了解了 Cloudflare Workers 的基础知识。 我们可以充满信心地继续前进。 如果您是 TypeScript 新手,请不要担心; 我们只会轻轻地使用它的功能。 将其想象为 TypeScript 世界的轻量级入门。

太好了,让我们继续前进!

添加第一个重定向

我们将从一个温和的开始着手我们的逻辑。 首先,我们将让我们的 URL 缩短器将用户重定向到不同的网站。 这将是以后更改的基础。

,我们将让用户访问 HTTP Cats网站上的一个页面。 现在,当用户访问我们的本地 Worker 时

如果你不熟悉 HTTP Cats ,它是一个有趣的网站,显示不同 HTTP 状态的各种猫图片。 例如,如果用户向我们的 Worker 请求 http://localhost:8787/404 ,他们将被定向到 https://http.cat/404

为了实现这个重定向,我们将编辑 src/index.ts,像这样:

// src/index.ts
// ...
​
const basePath = "https://http.cat";
​
export default {
  async fetch(
    request: Request,
    _env: Env,
    _ctx: ExecutionContext
  ): Promise<Response> {
    const url = new URL(request.url);
​
    const { pathname } = url;
​
    const redirectURL = basePath + pathname;
​
    if (pathname === "/") {
      return new Response("Hello World from our awesome Worker!");
    }
​
    return Response.redirect(redirectURL, 301);
  },
};

现在,如果我们访问 http://localhost:8787 ,我们将收到一条更新的消息:“Hello World from our awesome Worker!”,如下所示:

显示更新的“Hello world”消息的工作人员。

但是,如果我们尝试访问 http://localhost:8787/404 ,我们将被重定向到 https://http.cat/404

用户被重定向到 http.cat/404 网站。

太好了,我们的第一个重定向开始了。 现在,让我们的 URL 缩短器实际上缩短了一些 URL。

缩短网址

现在,我们将添加一个小数据结构来存储我们缩短的 URL。 我们可以这样做:

const shortURLs = {
  "/blog": "https://pragmaticpineapple.com/",
  "/twitter": "https://twitter.com/nikolalsvk",
  "/github": "https://github.com/nikolalsvk",
} as Record<any, string>;
​
export default {
  async fetch(
    request: Request,
    _env: Env,
    _ctx: ExecutionContext
  ): Promise<Response> {
    const url = new URL(request.url);
​
    const { pathname } = url;
​
    const redirectURL = shortURLs[pathname];
​
    if (!redirectURL) {
      return new Response(
        `There is no defined URL for the path: '${pathname}', sorry :(`
      );
    }
​
    return Response.redirect(redirectURL, 301);
  },
};

在这里,我们添加了几个缩短的 URL:

  • /blog重定向到 我的博客

  • /twitter到 我的 Twitter 个人资料

  • 和 /github到 我的 GitHub 个人资料

您可以将其更改为您喜欢的任何内容,以使其正常工作。 现在,当我访问 http://localhost:8787/blog 时,我被重定向到我的博客所在的更长的 URL。 结果如下:

访问 /blog 会重定向到实际的博客页面。

但是,如果我们请求一些路径,例如 http://localhost:8787/missing ,我们会收到以下错误消息:“路径没有定义的 URL:'/missing',对不起 :(”。

访问 /missing 会显示错误消息。

太棒了,现在我们已经准备好将硬编码的 URL 及其缩短的版本移动到某个地方的存储中。 幸运的是,我们正在使用 Cloudflare Workers,它提供了一种称为 KV 的简单键值存储。

Adding storage

在我们为项目实际创建 KV 之前,我们首先需要通过 Wrangler 登录 Cloudflare Workers。 这是必要的,因为 Wrangler 稍后需要联系 Cloudflare 以便为我们创建 KV 实例。

登录 Cloudflare

要登录 Cloudflare,请使用以下命令:

$ wrangler login

将打开一个浏览器,要求您登录 Cloudflare。 不用担心; 免费计划涵盖了本教程所需的一切,并且不会要求您付款。 继续注册,如果您已经有帐户,请登录。

接下来,Cloudflare 将询问您是否要授予 Wrangler 授权。 同意后,您应该会看到以下屏幕:

Wrangler CLI 工具现在已正确连接。

在注册过程中不应该有任何问题。 但是,如果您在任何时候遇到困难,可以按照 Cloudflare 的创建帐户指南进行操作 。

惊人的! 现在您已注册并登录,让我们检查一切是否正确连接。

使用以下命令:

$ wrangler whoami
  wrangler 2.0.21
--------------------
Getting User settings...
 You are logged in with an OAuth Token, associated with the email 'nikolaseap@gmail.com'!
┌──────────────────────┬──────────────────────────────────┐
│ Account Name         │ Account ID.                      │
├──────────────────────┼──────────────────────────────────┤
│ Nikola Đuza Personal │ 98a16dfefca0e2ee27e1e79ba590d973 │
└──────────────────────┴──────────────────────────────────┘

太好了,我们已经准备好创建 KV 命名空间了。

创建 KV 命名空间

可以将 KV 命名空间视为 Cloudflare 网络上的 KV up 实例。 我们将创建两个 KV 命名空间:一个用于我们的应用程序将生活和工作的生产环境,另一个用于预览环境。 我们将在测试和开发 URL 缩短器时使用 preview 命名空间。

我们将使用以下命令通过 Wrangler 创建 KV 命名空间:

$ wrangler kv:namespace create SHORT_URLS
 Creating namespace with title "short-it-SHORT_URLS"
 Success!
Add the following to your configuration file in your kv_namespaces array:
{ binding = "SHORT_URLS", id = "029d374ebd984e19b0bb98e37ab1a95e" }
​
$ wrangler kv:namespace create SHORT_URLS --preview
  wrangler 2.0.21
--------------------
 Creating namespace with title "short-it-SHORT_URLS_preview"
 Success!
Add the following to your configuration file in your kv_namespaces array:
{ binding = "SHORT_URLS", preview_id = "99a72876e5f84cf58de722b1c2080604" }

在这两个命令运行并创建了两个命名空间之后,我们需要在运行时告诉 Wrangler 使用这些命名空间 wrangler dev.

我们将把关于 KV 命名空间的信息添加到 wrangler.toml文件位于我们项目的根目录。 它应该看起来像这样:

name = "short-it"
main = "src/index.ts"
compatibility_date = "2022-07-15"
​
kv_namespaces = [
  { binding = "SHORT_URLS", id = "029d374ebd984e19b0bb98e37ab1a95e", preview_id = "99a72876e5f84cf58de722b1c2080604" }
]

这 wrangler.tomlfile 是一个配置文件,它告诉 wrangler关于我们项目的某些信息。 现在,我们已经准备好将一些数据添加到我们的 KV 中。

免费影视解析电脑软件,在线解析各大影视会员视频,内置多条线路秒速播放!

向 KV 添加数据

我们的下一步是将数据播种到 KV。 请记住,我们有两个命名空间,所以我们必须运行两个命令才能在两个地方都有数据。 让我们添加 /blog进入KV:

$ wrangler kv:key put --binding SHORT_URLS "/blog" "https://pragmaticpineapple.com/" --preview false
  wrangler 2.0.21
--------------------
Writing the value "https://pragmaticpineapple.com/" to key "/blog" on namespace 029d374ebd984e19b0bb98e37ab1a95e.
​
$ wrangler kv:key put --binding SHORT_URLS "/blog" "https://pragmaticpineapple.com/" --preview
  wrangler 2.0.21
--------------------
Writing the value "https://pragmaticpineapple.com/" to key "/blog" on namespace 99a72876e5f84cf58de722b1c2080604.

惊人的。 现在我们在 KV 中有一个条目。 接下来,让我们添加从 KV 读取并重定向用户的逻辑。

从 KV 读取

我们将快速删除旧的硬编码短 URL,并添加对 KV 的调用,如下所示:

// src/index.ts
export interface Env {
  SHORT_URLS: KVNamespace;
}
​
export default {
  async fetch(
    request: Request,
    env: Env,
    _ctx: ExecutionContext
  ): Promise<Response> {
    const url = new URL(request.url);
​
    const { pathname } = url;
​
    const redirectURL = await env.SHORT_URLS.get(pathname);
​
    if (!redirectURL) {
      return new Response(
        `There is no defined URL for the path: '${pathname}', sorry :(`
      );
    }
​
    return Response.redirect(redirectURL, 301);
  },
};

在这里,我们添加 SHORT_URLS作为一个 KVNamespace类型。 这将允许我们调用 KV 方法来获取正确的数据。 这次我们使用的不是带有 URL 的硬编码对象,而是 await env.SHORT_URLS.get(pathname).

呼吁 env.SHORT_URLS.get(pathname)尝试从 KV 获取密钥。 如果它返回一个承诺,我们必须 await. 但是,如果给定的值 pathname,然后用户被重定向到该 URL。

现在,当我们访问 http://localhost:8787/blog 时,我们将被重定向到我们放入 KV 中的实际博客 URL。 它看起来像这样:

访问 /blog 仍然会将我们重定向到实际的博客页面。

但是,如果我们现在尝试访问我们硬编码的任何其他 URL,我们将收到一条消息,指出这些 URL 缺少重定向:

访问 /twitter 会产生一条消息,指示该 URL 缺少重定向。

让我们使用以下命令快速将 Twitter 缩短的 URL 添加到 KV:

$ wrangler kv:key put --binding SHORT_URLS "/twitter" "https://twitter.com/nikolalsvk" --preview false
 wrangler 2.0.21
--------------------
Writing the value "https://twitter.com/nikolalsvk" to key "/twitter" on namespace 029d374ebd984e19b0bb98e37ab1a95e.
​
$ wrangler kv:key put --binding SHORT_URLS "/twitter" "https://twitter.com/nikolalsvk" --preview
  wrangler 2.0.21
--------------------
Writing the value "https://twitter.com/nikolalsvk" to key "/twitter" on namespace 99a72876e5f84cf58de722b1c2080604.

现在,当我们刷新 http://localhost:8787/twitter 时,我们应该会被重定向到 Twitter 帐户。

在我们将缩短的 URL 添加到 KV 后加载 Twitter。

太棒了,现在我们有两个短 URL: /blog和 /twitter. 让我们尝试部署我们的服务并在生产中查看它。

部署 Cloudflare Worker

Cloudflare Workers 部署步骤相当简单。 我们将利用 wrangler publish,像这样:

$ wrangler publish
  wrangler 2.0.21
--------------------
Retrieving cached values for userId from node_modules/.cache/wrangler
Your worker has access to the following bindings:
- KV Namespaces:
  - SHORT_URLS: 029d374ebd984e19b0bb98e37ab1a95e
Total Upload: 0.45 KiB / gzip: 0.29 KiB
Worker ID: short-it
Worker ETag: f8395cab29edf297137631b803b14c32daaae982758c23e3019b700e2468c277
Uploaded short-it (2.14 sec)
Published short-it (6.33 sec)
  short-it.nikolalsvk.workers.dev

现在,这些服务在 上线。 耶!

如果您按照本教程进行操作,您的服务应该位于 URL ev 的某个位置,具体取决于您选择的内容 YOUR_SUBDOMAIN.

此时,我们的 Worker 脚本已部署在全球各地的 Cloudflare Edge 网络上。 时,可以极快地重定向到我们的 Twitter 帐户 这意味着全球各地的朋友和陌生人访问r。

包起来

感谢您继续使用 Cloudflare Workers 创建简单的 URL 缩短服务。 在本文中,我们介绍了 Cloudflare 上下文中 Worker 的概念。 我们还演示了如何在 Cloudflare 的 KV 存储中创建和管理数据。

我们能够使用 Wrangler 顺利执行所有这些工作,这提供了出色的开发人员体验。 但是,最重要的是,我们设法创建、测试和部署了在世界各个角落快速运行的小型服务。

在类似的技术或服务中实现这一目标可能需要大量的金钱和努力。 但是,Cloudflare 支持每天 100,000 个请求的免费套餐。 因此,您可以在违反付费计划之前缩短许多 URL 并对其进行多次访问。

 类似资料: