如何用Cloudflare工人创建一个URL缩短器

952 阅读6分钟

你是否使用过BitlyTinyURL等工具来缩短长链接?或者,你是否想知道这些服务是如何工作的?也许你想建立一个URL缩短器,但从未找到时间或适当的工具来这样做。在任何情况下,如果你对这个话题感兴趣,这篇文章就很适合你。

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

让我们开始吧

什么是 Cloudflare Workers?

Cloudflare Workers 是一项服务,可让您将无服务器代码部署到 Cloudflare 网络。Cloudflare网络,即Edge,是一个分布在全球各地的网络服务器网络。Cloudflare Workers的一个好处是,你不必担心代码的扩展问题。此外,您不必担心您的代码所处的时区;您在Workers中的代码在部署后几秒钟就会传播到全球各地。

除此之外,Cloudflare Workers还配有一个简单的键值数据存储,称为KV。在本教程中,我们将使用 Cloudflare Workers 和 KV 存储的组合来构建我们的 URL 短。

项目概述。URL缩短器服务

我们将从构建一个简单的、非动态的URL缩短器开始,在这里你可以硬编码你想重定向的网站。这将作为学习如何使用Wrangler(Cloudflare的官方CLI工具)的介绍,并将展示Worker领域的基本概念。

接下来,我们将增加一些内容,增加对动态 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
  • Wrangler
  • curl(或你选择的浏览器)来测试URL缩短器

我使用asdf工具来管理我的本地依赖关系,但你可以使用任何你喜欢的版本管理器。在写作的时候,这是我的Node和npm版本:

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

Wrangler是一个用于构建的命令行工具,最近,它有了2.0版本。在这篇文章中,Wrangler将满足我们所有的需求。在未来,我们可能会使用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的所有问题都做出了肯定的回答,那么你将有一个项目名称short-it ,里面有以下内容:

  • .git 在你的项目中的目录,意味着你已经准备好推送到你的Git提供者那里了
  • package.json 文件
  • tsconfig.json 带有所有TypeScript配置的文件
  • src/index.ts 文件,其中有一些简单明了的逻辑,以从我们的Worker中获得响应

真棒。让我们来看看这个东西是否能工作!

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

$ cd short-it
$ wrangler dev --local

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

Hello World Message

生成的Worker正在显示一个 "Hello World!"的消息。

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

Cloudflare Worker 是如何工作的?

我们从生成的 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 函数返回一个带有 "Hello World!"文本的新Response 对象。因此,当我们运行我们的 Worker 时,这个fetch 函数被调用。然后,被调用的fetch 函数返回 "Hello World!"的响应,这就是我们在浏览器(或通过任何用于调用Worker的工具)中获取的东西。

好了,我们已经理清了Cloudflare Worker的基本情况。我们可以放心地继续前进了。如果你是 TypeScript 的新手,请不要担心;我们将只是简单地使用其功能。想象一下,这是对 TypeScript 世界的一次轻量级入门培训。

很好,让我们继续前进吧

添加第一个重定向

我们将以温和的方式开始我们的逻辑工作。首先,我们要让我们的URL缩短器将用户重定向到一个不同的网站。这将为以后的变化打下基础。

现在,我们将让用户在访问我们的本地工人时,进入到http.cat/网站的一个页面。

如果你不熟悉http.cat/,这是一个有趣的网站,它为不同的HTTP状态显示各种猫的图片。例如,如果一个用户向我们的Worker发出了http://localhost:8787/404 的请求他们将被引导到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 From Awesome Worker

工作者显示更新的 "Hello world "信息:

但是,如果我们试图去访问http://localhost:8787/404,我们会被重定向到http.cat/404。

User Redirected

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

很好,我们得到了第一个重定向的机会。现在,让我们让我们的URL缩短器实际缩短一些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:

你可以把它改成你喜欢的样子,只是为了看看它是否有效。现在,当我访问http://localhost:8787/blog,会被重定向到我的博客所在的较长的URL。结果是这样的。

Redirects to Blog

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

但是,如果我们请求一些路径,比如http://localhost:8787/missing,我们会得到以下错误信息。"没有为路径定义的URL:'/missing',对不起:("。

Error Message Missing

访问/missing会显示一个错误信息。

太棒了,现在我们准备把我们的硬编码的URL和它们的缩短版转移到某个地方的存储空间。幸运的是,我们使用的是 Cloudflare Workers,它提供了一个名为 KV 的简单键值存储。

添加存储

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

登录 Cloudflare

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

$ wrangler login

一个浏览器将打开,要求您登录到Cloudflare。不要担心;免费计划涵盖了我们在本教程中所需要的一切,不会要求你付款。继续注册,如果你已经有一个账户,则可以登录。

接下来,Cloudflare会问你是否要向Wrangler授予授权。在你同意后,你应该看到以下屏幕。

Wrangler CLI Tool

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

在注册过程中不应该有任何障碍。但是,如果你在任何时候被卡住了,你可以按照Cloudflare的指南来创建一个账户

棒极了!现在你已经注册并登录了,让我们检查一切是否连接正常。

使用以下命令:

$ wrangler whoami
 

很好,我们已经准备好制作一个KV命名空间了。

创建一个KV命名空间

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

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

$ wrangler kv:namespace create SHORT_URLS

在这两个命令运行后,两个命名空间都被创建了,我们需要告诉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.toml 文件是一个配置文件,它告诉wrangler 有关我们项目的某些信息。现在,我们已经绑好了,准备向我们的KV添加一些数据。

将数据添加到KV中

我们的下一步是将数据加入到KV中。记住,我们有两个命名空间,所以我们必须运行两个命令来使数据同时出现在两个地方。让我们把/blog 条目添加到 KV 中:

$ wrangler kv:key put --binding SHORT_URLS "/blog" "https://pragmaticpineapple.com/" --preview false
 

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

从KV中读取信息

我们将迅速删除旧的硬编码短网址,并添加对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方法来获得适当的数据。这一次我们使用await env.SHORT_URLS.get(pathname) ,而不是带URL的硬编码对象。

env.SHORT_URLS.get(pathname) 的调用试图从KV中获得密钥。如果它返回一个承诺,我们必须await 。但是,如果有一个给定的pathname 的值,那么用户会被重定向到那个URL。

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

Still Redirects Blog

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

但是,如果我们现在试图访问我们硬编码的任何其他URL,我们会得到一个消息,说这些URL缺少重定向:

URL Missing Redirect

访问/twitter的结果是一条信息,表明该URL缺少重定向。

让我们使用这些命令快速将Twitter的缩短版URL添加到KV中:

$ wrangler kv:key put --binding SHORT_URLS "/twitter" "https://twitter.com/nikolalsvk" --preview false

现在,当我们刷新http://localhost:8787/twitter,我们应该得到重定向到Twitter账户。

Twitter Loading

在我们把缩短的URL添加到KV后,Twitter就会加载。

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

部署 Cloudflare Workers

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

$ wrangler publish
 

现在,服务已在short-it.nikolalsvk.workers.dev 上运行耶!

如果你跟着这个教程走,你的服务应该在 URLshort-it.YOUR_SUBDOMAIN.workers.dev 的某个地方,这取决于你为YOUR_SUBDOMAIN 选择了什么。

在这一点上,我们的 Worker 脚本已经部署在全球各地的 Cloudflare Edge 网络上。这意味着,全球各地的朋友和陌生人如果访问short-it.nikolalsvk.workers.dev/twitter,就会以极快的速度被重定向到我们的Twitter账户

总结

感谢你在使用Cloudflare Workers创建一个简单的URL缩短器服务的过程中的关注。在这篇文章中,我们介绍了Cloudflare上下文中的Worker的概念。我们还演示了如何在 Cloudflare 的 KV 存储中创建和管理数据。

我们能够使用Wrangler顺利地执行这一切,它提供了一个很好的开发者体验。但是,最重要的是,我们成功地创建、测试和部署了我们的小服务,在世界各个角落快速运行。

在类似的技术或服务中实现这一点可能需要大量的资金和精力。然而,Cloudflare支持慷慨的免费层,每天有10万个请求。因此,在闯入付费计划之前,你可以缩短许多URL,并对其进行多次访问。

如果你喜欢这篇文章,请考虑与你的朋友和同事们分享它。

直到下一次,祝你好运!