首页 > 解决方案 > Cloudflare Worker Cache Put Mobile 不工作

问题描述

下面是在 Cloudflare Worker 中运行的代码。我正在使用它来按设备类型代理请求缓存。用户将访问 example.com/blog,Worker 会将请求代理到 blog.example.com - 这一切正常。完成此操作后,我将使用 Cache API 来缓存特定于设备的页面版本。问题是从移动设备请求的 url 不会从缓存中获得服务。无论是真正的移动设备还是使用 Chrome 的开发工具。

x-key 标头包含正确的 url 'https://m.www.example.com/blog/',但是 cf-cache-status 标头在每个请求中都包含 DYNAMIC。如果我换成台式电脑或平板电脑,x-key 是“https://d.www.example.com/blog/”或“https://t.www.example.com/blog/”,而cf-cache-status 标头在第一次请求后包含 HIT。

我假设如果 cache.put 失败,什么都不会返回,或者我会看到一条错误消息?

我只是看不出设备的类型会如何产生影响......任何人都可以看到代码的问题吗?

下面是我正在使用的代码:

const originUrl = 'https://blog.example.com/'
const publicUrl = 'https://www.example.com/blog/'
const blockedPaths = ['wp-admin', 'wp-login', 'wp-json']

addEventListener('fetch', event => {  
    return event.respondWith(handleRequest(event))
})

async function handleRequest(e) {
  if (new RegExp(blockedPaths.join('|')).test(e.request.url)) {
      return Response.redirect(publicUrl, 302)
  }

  let cache = caches.default
  let deviceType = 'd'
  let userAgent = e.request.headers.get('User-Agent') || ''
  let url = new URL(e.request.url)

  if(isMobileAgent(userAgent)) {
    deviceType = 'm'
  } else if(isTabletAgent(userAgent)) {
    deviceType = 't'
  }
  
  let cacheKey = `${url.protocol}//${deviceType}.${url.hostname}${url.pathname}`
  let response = await cache.match(cacheKey)
  
  if(!response) {
    response = await fetch(buildOriginUrl(e.request.url), e.request)
    response = new Response(response.body, response)
    response = urlRewriter.transform(response)

    response.headers.delete('vary')
    response.headers.delete('pragma')
    response.headers.delete('expires')
    response.headers.delete('last-modified')

    e.waitUntil(cache.put(cacheKey, response.clone()));
  }

  response = new Response(response.body, response)
  response.headers.set('Cache-Control', 'public; max-age=604800')
  response.headers.set('x-devicetype', deviceType)
  response.headers.set('x-key', cacheKey)
  response.headers.set('x-powered-by', '')
  response.headers.delete('x-powered-by')

  return response
}

function buildOriginUrl(requestUrl) {
  if(!requestUrl){
    return
  }

  return requestUrl.replace(publicUrl, originUrl)
}

function isMobileAgent(userAgent) {
  var check = false;
  (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(userAgent)
  return check;
}

function isTabletAgent(userAgent) {
  var check = false;
  (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(userAgent)
  return check;
}

class AttributeRewriter {
  constructor(attributeName) {
    this.attributeName = attributeName
  }

  element(element) {
    const attribute = element.getAttribute(this.attributeName)
    
    if (attribute) {
      element.setAttribute(this.attributeName, attribute.replace(originUrl, publicUrl))
    }
  }
}

const urlRewriter = new HTMLRewriter().on('a', new AttributeRewriter('href')).on('img', new AttributeRewriter('src'))

我也尝试过使用:

let cache = await caches.open('example');

然而这并没有什么不同

2021 年 1 月 14 日更新 15:40

缓存请求的 HTTP 标头是:

age: 5908
cache-control: public; max-age=604800
cf-cache-status: HIT
cf-ray: 611859ce7e2f40a7-LHR
cf-request-id: 07a316750b000040a7e02aa000000001
content-encoding: br
content-type: text/html; charset=UTF-8
date: Thu, 14 Jan 2021 15:22:09 GMT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
link: <https://www.example.com/shipping/wp-json/>; rel="https://api.w.org/", <https://www.example.com/shipping/?p=1317>; rel=shortlink
nel: {"report_to":"cf-nel","max_age":604800}
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=HbUZpOq5ZHVhF7%2FznXlPx9iUuoLUWD5ArGot5I0dYy7fSVuvJ%2BVTS3xzM%2Fety5mZIU4K1AeptoFEUznT5IQhxO7ZIzI%2BxLxPh8JtE15P8LWppw%3D%3D"}],"group":"cf-nel","max_age":604800}
server: cloudflare
set-cookie: __cfduid=d2e0c44aa8532edfea9ad8cdeca463ff41610637729; expires=Sat, 13-Feb-21 15:22:09 GMT; path=/; domain=.example.com; HttpOnly; SameSite=Lax; Secure
vary: Accept-Encoding
x-devicetype: d
x-key: https://d.www.example.com/shipping/my-baggage-boxes/
x-pingback: https://shipping.example.com/xmlrpc.php

非缓存请求的 HTTP 标头是:

cache-control: public; max-age=604800
cf-cache-status: DYNAMIC
cf-ray: 61185ab4fe3140a7-LHR
cf-request-id: 07a3170518000040a7319c5000000001
content-encoding: br
content-type: text/html; charset=UTF-8
date: Thu, 14 Jan 2021 15:22:46 GMT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
link: <https://www.example.com/shipping/wp-json/>; rel="https://api.w.org/", <https://www.example.com/shipping/?p=1317>; rel=shortlink
nel: {"report_to":"cf-nel","max_age":604800}
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=qct0tHNNNSwVEkWMNCWHjKDDmdRibPMCexx10C377q6X8UxoEouyHLpMvPA7xa9jTrexW3O2CjVf4Vjq1aqNEA7Izc9wYsH71pmN3Qn9PybjmQ%3D%3D"}],"group":"cf-nel","max_age":604800}
server: cloudflare
vary: Accept-Encoding
x-devicetype: m
x-key: https://m.www.example.com/shipping/my-baggage-boxes/
x-pingback: https://shipping.example.com/xmlrpc.php

我已经更新了 Worker 以删除 Cache.Put 之前的变量、杂注、过期和最后修改。我仍然不明白是什么导致了这个问题。我假设没有办法获得看跌期权的报告?

标签: cloudflare-workers

解决方案


可能存在修改缓存行为的活动页面规则。你检查过吗?


推荐阅读