六维教程

EdgeOne Makers Edge Functions

请求从用户到你的服务器,中间会经过很多个边缘节点。Edge Functions 就是跑在这些节点上的轻量函数,能在请求到达你的源站之前就把事情处理掉。这一篇讲 Edge Functions 的概念、优势,以及怎么创建第一个 Edge Function 并处理请求和响应。

Edge Functions 是什么

Edge Functions 运行在全球各地的边缘节点上。用户发一个请求,离他最近的边缘节点就会执行你写的代码,不用把请求送到千里之外的中心机房。

打个比方: 传统服务器像是在北京开了一个仓库,全国的用户都得从北京发货。Edge Functions 则是在每个省都设了前置仓,用户要的东西直接从最近的仓库处理。

它和 Cloud Functions 的核心区别在Functions 概览里讲过,这里再强调一下 Edge Functions 的定位: 轻量、快速、每个请求都会走一遍。

Edge Functions 的优势

低延迟。代码跑在离用户最近的节点上,网络传输距离最短。改个请求头、做个鉴权判断,通常在几毫秒内就能完成。

高可用。边缘节点天然分布式,一个节点挂了其他节点顶上,不用担心单点故障。

节省源站压力。非法请求、过期缓存这些在边缘就拦截掉了,不用打到源站,源站的负载直接降下来。

按量计费。没有请求就不执行,不执行就不花钱。对比一台一直开着的服务器,空闲时段完全不产生费用。

创建第一个 Edge Function

第一步: 进入 EdgeOne 控制台

打开 EdgeOne 控制台,找到你的站点,进入”边缘函数”模块。点击”新建函数”,填写函数名称,比如 hello-world

第二步: 编写函数代码

Edge Functions 使用 JavaScript 运行时,语法上接近标准 Web API。最简单的一个函数如下。

// 导出默认的 fetch 处理函数
export default {
  async fetch(request, env, ctx) {
    // 返回一段纯文本
    return new Response('Hello from Edge Function', {
      headers: { 'content-type': 'text/plain; charset=utf-8' }
    });
  }
};

这段代码做了一件事: 不管什么请求进来,都返回一句 “Hello from Edge Function”。fetch 是 Edge Functions 的入口函数,接收三个参数。

参数 类型 说明
request Request 当前的 HTTP 请求对象
env Object 环境变量和绑定的资源
ctx Context 执行上下文,可以注册异步任务

第三步: 绑定路由

函数写好了,还得告诉 EdgeOne 哪些请求走这个函数。在”触发器”配置里添加路由规则,比如 example.com/hello/*,表示所有 /hello/ 开头的请求都走这个函数。

第四步: 部署

点击”部署”,函数就会推送到所有边缘节点。几秒后访问 https://example.com/hello/test 就能看到返回结果。

请求处理

实际使用中,你通常需要读取请求信息来做不同的处理。

读取请求方法和 URL

export default {
  async fetch(request, env, ctx) {
    // 获取请求方法: GET、POST 等
    const method = request.method;

    // 获取完整 URL
    const url = new URL(request.url);

    // 获取路径名
    const pathname = url.pathname;

    // 获取查询参数
    const keyword = url.searchParams.get('keyword');

    return new Response(JSON.stringify({
      method: method,
      pathname: pathname,
      keyword: keyword
    }), {
      headers: { 'content-type': 'application/json' }
    });
  }
};

读取请求头

export default {
  async fetch(request, env, ctx) {
    // 读取单个请求头
    const userAgent = request.headers.get('user-agent');

    // 读取自定义请求头
    const apiKey = request.headers.get('x-api-key');

    // 检查某个请求头是否存在
    const hasToken = request.headers.has('authorization');

    return new Response(JSON.stringify({
      userAgent: userAgent,
      hasApiKey: apiKey !== null,
      hasToken: hasToken
    }), {
      headers: { 'content-type': 'application/json' }
    });
  }
};

读取请求体

POST 请求通常带有请求体,Edge Functions 支持多种读取方式。

export default {
  async fetch(request, env, ctx) {
    // 只有 POST、PUT 等方法才有请求体
    if (request.method === 'POST') {
      // 方式一: 读成文本
      const textBody = await request.text();

      // 方式二: 读成 JSON(前提是客户端发的是 JSON)
      // 注意: text() 和 json() 只能调一个,请求体只能读一次
      const jsonBody = await request.json();

      // 方式三: 读成 ArrayBuffer
      // const bufferBody = await request.arrayBuffer();

      return new Response(JSON.stringify({
        received: jsonBody
      }), {
        headers: { 'content-type': 'application/json' }
      });
    }

    return new Response('请用 POST 方法', { status: 405 });
  }
};

响应处理

返回响应不只是 new Response() 这么简单,状态码、响应头都有讲究。

设置状态码和响应头

export default {
  async fetch(request, env, ctx) {
    // 正常返回 200,设置 JSON 响应头
    return new Response(JSON.stringify({ message: 'success' }), {
      status: 200,
      headers: {
        'content-type': 'application/json; charset=utf-8',
        'cache-control': 'no-cache',
        'x-custom-header': 'hello'
      }
    });
  }
};

常见状态码用法

状态码 含义 典型场景
200 成功 正常返回数据
301 永久重定向 旧地址迁移到新地址
302 临时重定向 临时跳转,比如登录页
304 未修改 缓存命中,不用重新传输
400 请求有误 参数格式不对
401 未授权 缺少或无效的身份凭证
403 禁止访问 有凭证但权限不够
404 未找到 资源不存在
405 方法不允许 比如该用 POST 却用了 GET
500 服务器错误 代码出异常了

重定向

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // 旧路径重定向到新路径
    if (url.pathname === '/old-page') {
      return Response.redirect('https://example.com/new-page', 301);
    }

    return new Response('Normal page');
  }
};

返回 HTML 页面

export default {
  async fetch(request, env, ctx) {
    const html = `
      <!DOCTYPE html>
      <html>
        <head><title>Edge Page</title></head>
        <body>
          <h1>这个页面由 Edge Function 动态生成</h1>
        </body>
      </html>
    `;

    return new Response(html, {
      headers: { 'content-type': 'text/html; charset=utf-8' }
    });
  }
};

结合环境变量使用

实际项目中,API 密钥、数据库地址这些不能硬编码在代码里,要用环境变量。在概览里提过的 env 参数就是用来读环境变量的。

export default {
  async fetch(request, env, ctx) {
    // 读取在控制台配置的环境变量
    const apiBaseUrl = env.API_BASE_URL;

    // 用环境变量拼接口地址
    const targetUrl = apiBaseUrl + '/data';

    return new Response(JSON.stringify({
      target: targetUrl
    }), {
      headers: { 'content-type': 'application/json' }
    });
  }
};

在 EdgeOne 控制台的函数配置里,找到”环境变量”模块,添加键值对就行。env.API_BASE_URL 就能读到对应的值。

速查卡片

要点 说明
Edge Functions 运行位置 全球边缘节点,离用户最近
入口函数 fetch(request, env, ctx)
request 参数 标准 Web Request 对象
env 参数 环境变量和绑定资源
返回响应 new Response(body, { status, headers })
读取 JSON 请求体 await request.json(),只能读一次
重定向 Response.redirect(url, statusCode)
环境变量 控制台配置,代码里用 env.KEY 读取
上一篇
EdgeOne Makers Functions 概览
下一篇
EdgeOne Makers Cloud Functions 基础