跳到主要内容
Subhosting

为 Deno 子托管引入更灵活的域名关联

Subhosting 让您可以轻松安全地在安全托管的沙箱中运行来自多个客户的不受信任的 JavaScript 代码。Subhosting 有许多用例,例如 为其用户提供边缘函数托管靠近用户的电子商务店面 等等 - 所有这些都无需担心安全性和维护生产基础设施。

当托管用户的代码时,您有时希望他们的部署可以通过简洁的自定义域名公开访问,例如 user1.yourcompany.com现在,借助我们新的、更灵活的域名关联,跨用户的部署管理自定义域名变得更加简单。这允许您通过 Subhosting API 以编程方式管理域名映射并将自定义域名附加到部署。

在这篇文章中,我们将介绍

在我们深入研究如何使用 API 之前,让我们回顾一下此功能现在支持的内容。

组织范围内的通配符子域名

您现在可以将同一通配符域名下的不同子域名分配给不同的部署。例如,给定 *.example.com 通配符域名,您现在可以将 foo.example.com 分配给一个部署,将 bar.example.com 分配给另一个部署。这种灵活性允许更复杂的部署策略和更轻松的资源管理。

用于简化域名管理的变量

为了使以编程方式管理和引用用户的部署更简单,当您指定要与部署关联的域名时,现在公开了两个变量

  • {deployment.id}:部署的唯一标识符。
  • {project.name}:部署所属的项目名称。

这些可以与任意字符串组合使用,只要它们是有效域名,并且在替换后在您注册的通配符域名范围内即可。例如,您可以指定如下域名:

  • {deployment.id}.example.com
  • {project.name}.example.com
  • {project.name}-{deployment.id}.example.com
  • foo-{deployment.id}.example.com
  • foo-{deployment.id}-{project.name}.example.com

这些变量也可以与 deno.dev 域名结合使用,但在此情况下,仅允许以下两种格式

  • {project.name}-{deployment.id}.deno.dev
  • {project.name}.deno.dev

这些增强功能提供了更好的自定义和自动化功能,使以编程方式管理和引用部署变得更加容易。

让我们看看如何在实践中使用这些功能,通过一个示例。

如何附加和分离自定义域名

在将自定义域名附加到部署之前,您的自定义域名首先需要使用 POST /organizations/{organizationId}/domains 端点进行注册

import { assert } from "jsr:@std/assert/assert";

const orgId = "your-organization-id";
const orgToken = "your-organization-token";

const res = await fetch(
  `https://api.deno.com/v1/organizations/${orgId}/domains`,
  {
    method: "POST",
    body: JSON.stringify({
      domain: "*.example.com",
    }),
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${orgToken}`,
    },
  },
);

assert(res.ok);

此调用的响应正文包含 dnsRecords 字段,这是一个 DNS 记录列表,您可以使用这些记录来设置名称服务器。

下一步是为域名颁发 TLS 证书。虽然您可以通过上传证书来执行此操作,但您也可以通过 POST /domains/{domainId}/certificates/provision 来配置 TLS 证书

import { assert } from "jsr:@std/assert/assert";

const orgToken = "your-organization-token";
// Domain ID you got from the previous step
const domainId = "your-domain-id";

const res = await fetch(
  `https://api.deno.com/v1/domains/${domainId}/certificates/provision`,
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${orgToken}`,
    },
  },
);

assert(res.ok);

现在您已准备就绪 — 让我们使用 POST /projects/{projectId}/deployments 创建新的部署

import { assert } from "jsr:@std/assert/assert";

const projectId = "your-project-id";
const orgToken = "your-organization-token";

const res = await fetch(
  `https://api.deno.com/v1/projects/${projectId}/deployments`,
  {
    method: "POST",
    body: JSON.stringify({
      entryPointUrl: "main.ts",
      assets: {
        "main.ts": {
          kind: "file",
          content: 'Deno.serve(() => new Response("hello"));',
        },
      },
      envVars: {},
      domains: [
        "foo.example.com",
        "{deployment.id}.example.com",
        "{project.name}-{deployment.id}.deno.dev",
      ],
    }),
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${orgToken}`,
    },
  },
);

assert(res.ok);

请注意 JSON 有效载荷中的新 domains 字段,这是一个自定义域名数组,一旦成功创建部署,这些域名将附加到部署。此外,您可以在此处使用域名中的命名变量,它们将变成实际值。

假设新创建的部署 ID 是 chonky-dog-57,项目为 my-project。在我们的示例中,以下域名都将路由到这个新创建的部署

  • https://foo.example.com
  • https://chonky-dog-57.example.com
  • https://my-project-chonky-dog-57.deno.dev

如果我们想将自定义域名附加到现有部署怎么办?我们可以使用 PUT /deployments/{deploymentId}/domains/{domain}

import { assert } from "jsr:@std/assert/assert";

const deploymentId = "chonky-dog-57";
const orgToken = "your-organization-token";

const extraDomain = "prefix-{project.name}.example.com";

const res = await fetch(`/deployments/${deploymentId}/domains/${extraDomain}`, {
  method: "PUT",
  headers: {
    "Authorization": `Bearer ${orgToken}`,
  },
});

assert(res.ok);

现在,任何访问 https://prefix-my-project.example.com 的人都将被定向到现有的 chonky-dog-57 部署。

请注意,每当域名附加到部署时,它都会自动从之前的任何部署中分离。

我们还可以使用 DELETE /deployments/{deploymentId}/domains/{domain} 手动从部署中分离域名

import { assert } from "jsr:@std/assert/assert";

const deploymentId = "chonky-dog-57";
const orgToken = "your-organization-token";

const res = await fetch(
  `/deployments/${deploymentId}/domains/foo.example.com`,
  {
    method: "DELETE",
    headers: {
      "Authorization": `Bearer ${orgToken}`,
    },
  },
);

assert(res.ok);

现在,域名 https://foo.example.com 将不再定向到 chonky-dog-57 部署。

下一步是什么

Subhosting 对于有兴趣运行用户代码而无需担心安全性或维护生产基础设施的组织来说,仍然是一个绝佳的选择。

我们将继续投入资源,使 Subhosting 成为安全运行第三方不受信任代码的最简单方式,以便您可以专注于为最终用户交付价值。

🚨 想要安全地运行用户的不受信任的代码,而无需从头开始构建吗?

查看 Deno Subhosting,您可以在几分钟内在安全托管的沙箱中运行来自多个用户的 JavaScript 代码。