Orbit

边缘函数

Edge functions are small JavaScript handlers that run on Kapsule's edge network before a request reaches your project, so you can do redirects, header injection, A/B routing and bot filtering…

边界函数是在请求到达您的项目前在 Kapsule 边界网络上运行的小型 JavaScript 处理程序,因此您可以执行重定向、请求头注入、A/B 路由和机器人过滤,无需往返您的应用。本指南涵盖编写函数、接受的入口点形式、路径匹配、多个函数如何相互作用、部署以及函数抛出异常时发生的情况。

函数位置

Orbit 中打开您的项目,然后单击边界函数选项卡。每个函数属于一个项目,并通过其状态徽章列出:LIVEPAUSEDNOT DEPLOYEDDEPLOY FAILED

Orbit 项目的边界函数选项卡

创建函数

  1. 单击新函数
  2. 填写名称(最多 120 个字符)。
  3. 填写路径模式,即此函数应运行的 URL 模式。
  4. 选择触发器:请求(源之前)、响应(源之后)或两者。
  5. 选择环境范围:所有环境、仅生产环境或仅预览环境。
  6. 函数体中编写处理程序。
  7. 单击保存,然后单击部署到边界

request 对象始终在作用域内,源码限制为 64 KB。

编写处理程序

返回 Response 以在边界处回答请求。返回任何内容,或 undefined,以将请求原封不动地传递到您的项目。

export default {
  async fetch(request) {
    const url = new URL(request.url)

    // Redirect /old to /new
    if (url.pathname === '/old') {
      return new Response(null, {
        status: 301,
        headers: { Location: '/new' },
      })
    }

    // Returning nothing passes through to the origin
  },
}

命名函数形式也适用:

export default async function handler(request) {
  // Add a security header to every response
  const response = await fetch(request)
  const headers = new Headers(response.headers)
  headers.set('X-Frame-Options', 'DENY')
  return new Response(response.body, { status: response.status, headers })
}

支持的入口点形式

形式示例
具有 fetch 方法的对象export default { async fetch(request) { ... } }
具有箭头 fetch 属性的对象export default { fetch: async (request) => { ... } }
命名函数声明export default async function handler(request) { ... }
纯主体,无导出直接编写语句,不使用包装器

任何其他使用 export default 的形式,例如 export default class,在您单击保存时会被拒绝,并显示一条错误消息,命名要改用的两种形式。验证在保存时而不是部署时运行,因此您会立即发现,破损的函数永远不会被发布。

路径模式

路径模式决定哪些请求运行该函数。它必须以 / 开头,最多可包含 2048 个字符。* 匹配任何字符序列,? 匹配单个字符。没有通配符的模式会匹配该确切路径及其下方的所有内容。

模式匹配
/*每个路径
/api/*任何以 /api/ 开头的内容
/blog/*/comments例如 /blog/my-post/comments
/page/page/page/ 下方的任何内容

request 对象

request 是一个标准的 Fetch API Request。您可以读取 URL、方法、请求头和主体:

export default {
  async fetch(request) {
    const url    = new URL(request.url)
    const cookie = request.headers.get('cookie') ?? ''
    const ua     = request.headers.get('user-agent') ?? ''

    if (ua.includes('BadBot')) {
      return new Response('Forbidden', { status: 403 })
    }
  },
}

不要假设某个请求头存在,仅仅因为您在其他平台上见过它。读取您自己的函数实际接收的请求头(从函数中记录它们,或在临时路径上的调试响应中返回它们)后,再对其中一个进行条件判断。对永远不会出现的请求头进行条件判断的处理程序会在每个请求上无声地走向错误的路径。

常见模式

重定向旧 URL

export default {
  async fetch(request) {
    const url = new URL(request.url)
    const redirects = {
      '/old-about':   '/about',
      '/old-contact': '/contact',
    }
    const dest = redirects[url.pathname]
    if (dest) return Response.redirect(url.origin + dest, 301)
  },
}

对于少数几个简单直接的路径到路径的移动,请改用内置重定向引擎:它不需要代码,并在设置中配置。参见配置重定向和重写

添加安全请求头

export default async function handler(request) {
  const response = await fetch(request)
  const headers = new Headers(response.headers)
  headers.set('X-Frame-Options', 'DENY')
  headers.set('X-Content-Type-Options', 'nosniff')
  headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
  return new Response(response.body, {
    status: response.status,
    statusText: response.statusText,
    headers,
  })
}

对于不需要代码的静态请求头规则,设置也有一个响应请求头部分,其中包含用于 HSTS、CSP、no-embed、no-sniff、referrer policy 和 CORS 的快速添加预设。

A/B 路由

export default {
  async fetch(request) {
    const url     = new URL(request.url)
    const variant = Math.random() < 0.5 ? 'a' : 'b'
    url.searchParams.set('variant', variant)
    return fetch(url.toString(), request)
  },
}

环境范围

范围运行位置
所有环境生产、暂存和每个分支预览
仅生产环境生产环境
仅预览环境每个非生产环境

首先将新函数作为仅预览环境发布,在分支预览上确认其行为,然后将其切换为所有环境。边界函数在每个请求前运行,因此其中的错误会在所有页面上同时出现。

多个函数如何相互作用

您项目的所有已启用函数按创建顺序进行评估。对于每个请求,边界会遍历列表并运行第一个路径模式与请求路径匹配且范围涵盖该环境的函数。

  • 如果该函数返回 Response,它会被发送,评估停止。
  • 如果它返回任何内容,评估继续进行到下一个匹配的函数。
  • 如果它们都不返回 Response,请求会像往常一样发送到您的项目。

这意味着早期创建的广泛 /* 函数可能会遮蔽稍后创建的更窄函数,如果广泛函数返回 Response。先创建特定的函数,或让广泛函数对于不应处理的路径返回任何内容。

部署

单击部署到边界。部署从数据库的当前状态为整个边界网络重新生成单个组合路由器,因此启用、禁用、编辑或删除任何函数都会重新发布所有内容。更改通常在几秒钟内生效。

每个函数行都保留一个部署日志,显示上次部署的步骤,如果部署失败,还有一个带错误的 DEPLOY FAILED 徽章。

暂停可将函数从路由器中移除而不删除它,这是快速回滚故障函数的最快方法。恢复可将其重新放入。

函数抛出异常时

函数内的异常在边界处被捕获。错误被记录,请求会像函数返回任何内容一样被传递到您的项目。

这是一个安全网,而不是监控系统。在每个请求上抛出异常的函数从您的访问者的角度来看会静默失败,您的流量只会表现得好像该函数不存在。如果函数停止产生预期的效果,先怀疑异常,然后再怀疑路由。

限制

  • 每个项目最多 20 个函数。第 21 个会被拒绝。
  • 每个函数最多 64 KB 的源码。
  • 名称最多 120 个字符,路径模式最多 2048 个字符

相关阅读

仍需帮助?

请发送邮件至 support@kapsulehost.com 或在 KPanel 中打开聊天。

打开 KPanel
边缘函数