CF Workers HTTP/2 Only or HTTP/3 too?

Been playing with CF Workers for custom CF cache with additional headers added. But seems this only works with HTTP/2. If I test with Canary web browser and HTTP/3, then the custom CF Worker cache and additional headers do not show up and show the cache control settings from my origin server instead.

@harris is CF Workers currently HTTP/2 only ?

with HTTP/2 response headers

status: 200
content-length: 34
content-disposition: inline; filename="clear.webp"
cf-polished: origFmt=png, origSize=137
accept-ranges: bytes
expires: Wed, 01 Jul 2020 23:51:12 GMT
vary: Accept, Accept-Encoding
last-modified: Thu, 30 May 2019 01:11:04 GMT
cf-req-priority: weight=147;exclusive=1
cf-cachetime: 2592000
cf-cache-status: HIT
date: Mon, 01 Jun 2020 23:51:12 GMT
cf-bot-score: 98
cf-bgj: imgq:85,h2pri
cf-ray: 59ccd75f9fa474b3-IAD
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
alt-svc: h3-27=":443"; ma=86400
cf-tls: TLSv1.3
x-powered-by: centminmod
age: 7633
cf-request-id: 0313e4efba000074b3c80a7200000001
server: cloudflare
etag: "5cef2da8-89"
cache-control: public, max-age=2592000
cf-req-country: US
content-type: image/webp
cf-cache-xf: 1
:status: 200

with HTTP/3 H3-27 response headers

status: 200
content-length: 34
content-disposition: inline; filename="clear.webp"
cf-polished: origFmt=png, origSize=137
accept-ranges: bytes
expires: Tue, 01 Jun 2021 21:43:59 GMT
vary: Accept, Accept-Encoding
last-modified: Thu, 30 May 2019 01:11:04 GMT
date: Mon, 01 Jun 2020 23:51:45 GMT
cf-ray: 59ccd82f5f890dda-IAD
server: cloudflare
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
x-powered-by: centminmod
age: 7666
cf-request-id: 0313e5719b00000ddaf7901200000001
cf-bgj: imgq:85,h2pri
etag: "5cef2da8-89"
cache-control: max-age=31536000, public, must-revalidate, proxy-revalidate, immutable, stale-while-revalidate=86400, stale-if-error=604800
alt-svc: h3-27=":443"; ma=86400
content-type: image/webp
cf-cache-status: HIT

Hi @eva2000, Workers are (supposed to be) agnostic to what HTTP version the client speaks to our edge. If your script appears to behave differently based on the client protocol, it’s probably worth a support ticket. (Off the top of my head, I can’t think of any reason for the discrepancy.)

1 Like

cheers @harris yeah using curl built with HTTP/3 support via CF Quiche also shows the differences

http/3

curl-http3 --http3 -I https://domain.com/styles/default/xenforo/clear.png
HTTP/3 200
date: Tue, 02 Jun 2020 21:35:19 GMT
content-type: image/png
content-length: 98
set-cookie: __cfduid=d392569c4c1031a2403d3934d6a128d151591133719; expires=Thu, 02-Jul-20 21:35:19 GMT; path=/; domain=.domain.com; HttpOnly; SameSite=Lax
cf-ray: 59d44db45fb3f001-EWR
accept-ranges: bytes
age: 7212
cache-control: max-age=31536000, public, must-revalidate, proxy-revalidate, immutable, stale-while-revalidate=86400, stale-if-error=604800
etag: "5cef2da8-89"
expires: Wed, 02 Jun 2021 19:35:07 GMT
last-modified: Thu, 30 May 2019 01:11:04 GMT
vary: Accept
cf-cache-status: HIT
cf-bgj: imgq:85,h2pri
cf-polished: origSize=137
x-powered-by: centminmod
cf-request-id: 03188ee4b60000f001f7139200000001
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
alt-svc: h3-27=":443"; ma=86400

HTTP/2

curl-http3 --http2 -I https://domain.com/styles/default/xenforo/clear.png 
HTTP/2 200 
date: Tue, 02 Jun 2020 21:35:28 GMT
content-type: image/png
content-length: 98
set-cookie: __cfduid=d583b7cb87300d4ae03ce3fe84d5ba9fd1591133728; expires=Thu, 02-Jul-20 21:35:28 GMT; path=/; domain=.domain.com; HttpOnly; SameSite=Lax
cf-ray: 59d44dea9d8de74c-EWR
accept-ranges: bytes
age: 7221
cache-control: public, max-age=2592000
etag: "5cef2da8-89"
expires: Thu, 02 Jul 2020 21:35:28 GMT
last-modified: Thu, 30 May 2019 01:11:04 GMT
vary: Accept
cf-cache-status: HIT
cf-bgj: imgq:85,h2pri
cf-bot-score: 1
cf-cache-xf: 1
cf-cachetime: 2592000
cf-polished: origSize=137
cf-req-country: CA
cf-req-priority: weight=16;exclusive=0;group=0;group-weight=0
cf-request-id: 03188f069d0000e74cd7bcf200000001
cf-tls: TLSv1.3
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
x-powered-by: centminmod
server: cloudflare
alt-svc: h3-27=":443"; ma=86400

From my CF logs, looks like HTTP/3 based requests are causing my CF Worker to error out with exceptions

For inspecting CF logs for my request = /styles/default/xenforo/clear.png

HTTP/3 requests for last 5 hrs of CF logs with WorkerStatus = exception so it bypassed the CF Worker cache custom rules/headers and request from my origin CF cache rules

find . -mmin +300 -exec pzcat {} \; | jq -r 'select(.ClientRequestHost == "domain.com" and .ClientRequestProtocol == "HTTP/3" and .ClientRequestPath =="/styles/default/xenforo/clear.png" and .ClientCountry == "us" ) | "\(.ClientCountry) \(.EdgeResponseStatus) \(.CacheResponseStatus) \(.ClientASN) \(.ClientIPClass) \(.ClientRequestProtocol)-\(.OriginSSLProtocol) \(.ClientRequestMethod) \(.ClientRequestPath) \(.EdgePathingOp)-\(.EdgePathingSrc)-\(.EdgePathingStatus)-\(.EdgeRateLimitAction) \(.FirewallMatchesActions)-\(.FirewallMatchesRuleIDs)-\(.FirewallMatchesSources) \(.WAFAction)-\(.WAFRuleID) [\(.WorkerStatus)-\(.WorkerSubrequest)-\(.WorkerSubrequestCount)] \(.ClientRequestUserAgent)"' | sort -n | uniq -c | sort -rn | head -n20
     14 us 200 200 701 noRecord HTTP/3-unknown GET /styles/default/xenforo/clear.png wl-macro-nr- []-[]-[] unknown- [exception-false-2] Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4158.4 Safari/537.36
      2 us 304 304 701 noRecord HTTP/3-unknown GET /styles/default/xenforo/clear.png wl-macro-nr- []-[]-[] unknown- [exception-false-2] Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4158.4 Safari/537.36

while HTTP/2 requests so WorkerStatus = ok

find . -mmin +300 -exec pzcat {} \; | jq -r 'select(.ClientRequestHost == "domain.com" and .ClientRequestProtocol == "HTTP/2" and .ClientRequestPath =="/styles/default/xenforo/clear.png" and .ClientCountry == "us" ) | "\(.ClientCountry) \(.EdgeResponseStatus) \(.CacheResponseStatus) \(.ClientASN) \(.ClientIPClass) \(.ClientRequestProtocol)-\(.OriginSSLProtocol) \(.ClientRequestMethod) \(.ClientRequestPath) \(.EdgePathingOp)-\(.EdgePathingSrc)-\(.EdgePathingStatus)-\(.EdgeRateLimitAction) \(.FirewallMatchesActions)-\(.FirewallMatchesRuleIDs)-\(.FirewallMatchesSources) \(.WAFAction)-\(.WAFRuleID) [\(.WorkerStatus)-\(.WorkerSubrequest)-\(.WorkerSubrequestCount)] \(.ClientRequestUserAgent)"' | sort -n | uniq -c | sort -rn | head -n20
     34 us 200 200 16509 noRecord HTTP/2-unknown GET /styles/default/xenforo/clear.png wl-macro-nr- []-[]-[] unknown- [ok-false-1] Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36
     28 us 200 200 701 noRecord HTTP/2-unknown GET /styles/default/xenforo/clear.png wl-macro-nr- []-[]-[] unknown- [ok-false-1] Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36

This is quite strange, can you still reproduce today?

If so, can you try with wrangler tail on your worker script? Curious to see what is logged.

3 Likes

Hi @simon

The issue is gone now for the past few months. But not sure if it’s related to me removing some code (mentioned below) from my CF Workers which removed a lot of my Worker exception errors too when related to enabling CF Enterprise’s cache prefetch with listed URL links in manifest.txt. I don’t use wrangler but direct Worker editor GUI so can’t using tail.

Some of the code I removed was for CF Enterprise account’s support for Enterprise cf fields. Now I think about it for request.cf.requestPriority, it would only be for HTTP/2 right as there’s no HTTP/3 equivalent right now?

  if(request.cf.tlsVersion){
    tls = request.cf.tlsVersion
  }

  if(request.cf.botManagement.score){
     botscore = request.cf.botManagement.score
  }

  if(request.cf.requestPriority){
     reqpriority = request.cf.requestPriority
  }

and ones for

    response.headers.set('CF-TLS', tls);
    response.headers.set('CF-Bot-Score', botscore);

and similar to below for specific static assets playing with image HTTP/2 priorities.

const white_list = [
'xxx.xxx.xxx.xxx'
];
....
    response.headers.set('CF-Req-Priority', reqpriority);
    response.headers.set('cf-priority', "25/n");
    if (white_list.indexOf(request.headers.get("cf-connecting-ip")) != -1) {
      response.headers.set('Cf-Set-Priority', "25/n");
    }

would there be a way to conditionally set these only for HTTP/2 requests and not HTTP/3 requests ?

1 Like

Yep, you can detect the protocol by inspecting the request.cf object:

httpProtocol - HTTP Protocol, e.g. "HTTP/2".
2 Likes

Cheers, I’ll see about wrapping the HTTP/2 related ones in a check for HTTP protocol :slight_smile:

1 Like