之前的文章:

  1. Cloudflare workers不完全指南"
  2. Cloudflare Workers实战(一):随心所欲操作客户端请求
  3. Cloudflare Workers实战(二):动态修改后端响应

咱们前面两篇,把请求和响应这两大块给盘得明明白白了。现在,是时候发散一下想像力了!今天我们来看看怎么用Cloudflare Workers实现认证重定向缓存这三大金刚。

你可别小看这仨兄弟。在传统架构里,这些活儿通常是交给API网关、Nginx这种负载均衡器,甚至是后端业务代码自己去干的。但你想想,如果把这些工作全都搬到Cloudflare的边缘节点上,那会发生什么?

低情商回答: 你就有了更多的活

高情商回答: 快! 无与伦比的快!而且你的源站服务器会瞬间感觉压力骤减,因为它再也不用处理那些乱七八糟的认证、重定向逻辑了。

认证: 在世界的边缘给你“站岗放哨”

啥叫边缘认证?说白了,就是在用户请求还没到你服务器门口的时候,就先在Cloudflare的节点上把它拦下来,“对一下暗号”。暗号对上了,放行;对不上,直接打回去!

这样做的好处是显而易见的:

  • 安全:坏人连你服务器的门都摸不到,安全性大大提升。
  • 省钱:无效请求不消耗你宝贵的服务器资源,省下来的都是真金白银。

示例一:最经典的“你瞅啥”——HTTP Basic认证

HTTP Basic认证,老牌认证方式了,简单粗暴但有效。浏览器会弹个小窗让你输用户名和密码。咱们用Worker给网站的某个后台管理路径(比如/admin)加上这层保护。

// worker.js

// 定义合法的用户名和密码
const USER = 'admin';
const PASS = 'supersecretpassword';

export default {
  async fetch(request, env, ctx) {
    // 1. 从请求头中获取 'Authorization' 信息
    const authHeader = request.headers.get('Authorization');

    // 2. 检查Header是否存在且格式正确
    if (authHeader && authHeader.startsWith('Basic ')) {
      // 解码Base64编码的凭证
      const encodedCreds = authHeader.substring(6);
      const decodedCreds = atob(encodedCreds);
      const [user, pass] = decodedCreds.split(':');

      // 3. 验证用户名和密码
      if (user === USER && pass === PASS) {
        // 验证通过,将请求转发到源站
        return fetch(request);
      }
    }

    // 4. 验证失败,返回401 Unauthorized响应
    return new Response('Unauthorized', {
      status: 401,
      headers: {
        // 这个头会提示浏览器弹出用户名密码输入框
        'WWW-Authenticate': 'Basic realm="Protected Area"',
      },
    });
  },
};

示例二:API的“令牌”——Bearer Token认证

现在做API服务,更流行的是用Bearer Token来做认证。客户端在请求头里带上一个Authorization: Bearer <你的Token>,服务端验证这个Token就行。这活儿让Worker来干,简直是天造地设。

注意:这样的Token不像JWT那样可以包含更多信息,也不会超时,所以适合一次性的认证场景。

// worker.js

// 假设有效的Token存储在环境变量中,名为 'VALID_API_TOKEN'

export default {
  async fetch(request, env, ctx) {
    const authHeader = request.headers.get('Authorization');
    const expectedToken = `Bearer ${env.VALID_API_TOKEN}`;

    if (authHeader === expectedToken) {
      // Token有效,处理请求
      return fetch(request);
    } else {
      // Token无效或缺失,返回403 Forbidden
      return new Response('Forbidden', { status: 403 });
    }
  },
};

重定向: “此路不通,请走那边”

重定向也是个常见需求。比如网站换域名了,或者搞活动需要临时跳转页面。在边缘做重定向,那速度叫一个快,因为它压根儿就不用跟你的源站服务器打招呼,在Cloudflare节点上直接就给用户指路了。实现起来也超级简单,就一个Response.redirect()函数。

示例一:永久搬家(301)

假设你的博客从old-blog.com换到了new-cool-blog.com,为了不让搜索引擎(比如Google)和老用户迷路,你得告诉他们:“我永久搬家啦!”

// worker.js
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const oldDomain = 'old-website.com';
    const newDomain = 'www.new-website.com';

    if (url.hostname === oldDomain) {
      url.hostname = newDomain;
      // 使用301状态码进行永久重定向
      return Response.redirect(url.toString(), 301);
    }

    return fetch(request);
  },
};

示例二:临时有事,去隔壁(302)

临时重定向就更灵活了。比如你想根据用户用的是手机还是电脑,把他们导到不同的页面。

// worker.js
export default {
  async fetch(request, env, ctx) {
    const userAgent = request.headers.get('User-Agent') || '';

    // 如果是移动设备,临时重定向到移动版站点
    if (userAgent.includes('Mobile')) {
      return Response.redirect('https://m.example.com', 302);
    }

    return fetch(request);
  },
};

注意: 虽然301和302都是重定向,但是它们的语义不同。301代表永久重定向,搜索引擎会认为这是一个永久的重定向目的地,以后都去这里;而302代表临时重定向,搜索引擎会认为这是一个“暂时的”目的地,可能会变。这里的重点是SEO,对于搜索引擎很重要,如果你不需要SEO那就随意吧。。。。

缓存: 把好东西“藏”在边缘

说到Cloudflare,缓存是它的看家本领。默认情况下,它就会帮你缓存很多静态资源。但有了Workers,我们能玩得更高级!通过Cache API,我们可以像操作一个本地对象一样,去精确地、主动地控制缓存。

值的注意的是: 这个缓存不会像CDN一样复制到cloudflare的服务器或者说数据中心,假设在cloudflare在美国和英国都有一个数据中心,通过用户请求到英国的数据中心,美国请求到美国的数据中心,缓存是不会同步的,也就是说在英国的缓存不会同步到美国,美国的缓存也不会同步到英国。一般来说,其实没啥问题,用户除非开代理不然不会忽然跳到另一个数据中心,在者来说,没缓存就没缓存呗,其实也不是啥大事。

这对于那些不经常变动,但又很占资源的内容(比如API响应、HTML片段)来说,简直是福音。

示例一: 缓存API响应

假设你有一个API接口/api/products,返回的是全站商品列表。这个列表可能一天才更新一次。如果每次请求都打到源站,那也太浪费了。咱们把它在边缘缓存24小时!

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

    if (url.pathname === '/api/products') {
      // 1. 获取默认的缓存对象
      const cache = caches.default;

      // 2. 尝试从缓存中匹配请求
      // 注意:Cache API使用Request对象作为key,所以URL、Method、Headers不同都会导致缓存不命中
      let response = await cache.match(request);

      if (response) {
        console.log('缓存命中!');
        // 3. 如果缓存命中,直接返回缓存的响应
        return response;
      }

      console.log('缓存未命中,从源站获取。');
      // 4. 如果缓存未命中,从源站获取响应
      response = await fetch(request);

      // 5. 克隆响应,因为响应体只能被读取一次
      const responseToCache = response.clone();

      // 6. 设置响应头,告诉Cloudflare该响应可以被缓存多久
      // 缓存的时间就是请求头的这个字段来设置缓存时间的,所以put方法不需要一个expire的超时参数
      responseToCache.headers.set('Cache-Control', 'public, max-age=86400'); // 缓存24小时

      // 7. 将响应存入缓存
      // waitUntil确保即使在响应返回给用户后,写入缓存的操作也能完成
      ctx.waitUntil(cache.put(request, responseToCache));

      return response;
    }

    return fetch(request);
  },
};

小结一下

认证、重定向、缓存,可以说是Cloudflare Workers进阶玩法的核心。把这些传统上属于后端或网关的逻辑前移到边缘,带来的好处是实实在在的:

  • :用户请求在离他最近的节点就被处理了,响应速度快到飞起,如果你的业务是海外业务的话。
  • :源站服务器的压力大大减小,可以去处理更核心的业务逻辑,省钱省心。
  • 安全:在攻击到达你的核心基础设施之前,就在边缘被拦截了。

到这里,我们已经把Workers在动态请求处理和响应操纵方面的核心功能都摸了一遍。后面我们再看看怎么继续薅大善人的羊毛。