Returned R2 object in worked does not include body

I created an R2 bucket, and a worker, using the Cloudflare UI.

I then bound the R2 bucket into the variable FNALBUM, again using the UI.

I then went into the quick edit interface and tried to serve from the bucket. E.g.:

async function handleRequest(request) {
  const { pathname } = new URL(request.url);
  const url = new URL(request.url);
  const key = url.pathname.slice(1);
  const o = await FNALBUM.get(key);
  if (!o) {
    return new Response("Object Not Found", { status: 404 });
  }
  return new Response(`${JSON.stringify(o)} size=${o.size} ${o.body}`);
}

I see two problems:

  1. Contrary to documentation and example code, trying to serve a missing object will not actually return a null object, but an object with a value set to null.
$ curl […]/nonexistant
{"value": null}
  1. When object is present, all that’s returned is metadata about the object, not the actual body:
$ curl […]/test.jpg
{"value": {"locked":false}, "metadata":{"contentLength": 95704 [… more metadata …] size=undefined undefined

Those last two being ${o.size} and ${o.body}.

API documentation says that there should be a .size, and the code is pretty similar to the example code.

What am I doing wrong? I’m clearly actually connected to the bucket, because it can tell the difference between object missing, and provide correct metadata when an object is present.

Hi there! That looks like the old internal beta bindings. Have you defined a compatibility_date in your wrangler.toml file?

Old bindings:

{
    "value": {
        "locked": false
    },
    "metadata": {
        "contentLength": 13,
        "eTag": "65a8e27d8879283831b664bd8b7f0ad4",
        "published": "2022-04-25T13:52:37.592Z",
        "contentType": "application/octet-stream",
        "expiration": "1970-01-01T00:00:00.000Z",
        "customFields": {}
    }
}

New bindings:

{
    "customMetadata": {},
    "httpMetadata": {},
    "uploaded": "2022-04-25T13:52:37.592Z",
    "httpEtag": "\"65a8e27d8879283831b664bd8b7f0ad4\"",
    "etag": "65a8e27d8879283831b664bd8b7f0ad4",
    "size": 13,
    "version": "fd47f147e92541b894ef6809fb531c4f",
    "key": "hw"
}
3 Likes

Hi. Is it possible to do that in the UI?

return new Response(`${JSON.stringify(o)} size=${o.size} ${o.body}`);

This gives me the expected output.

{
  "customMetadata": {},
  "httpMetadata": {
    "contentType": "image/png"
  },
  "uploaded": "2022-05-12T09:48:21.249Z",
  "httpEtag": "\"d9d9e5eca879c296ddfab0c326b51a3e\"",
  "etag": "d9d9e5eca879c296ddfab0c326b51a3e",
  "size": 42011,
  "version": "619d25712e4c440db401db6fb4b053ff",
  "key": "blobunhappy.png"
}

size=42011 [object Object]

The body object is a ReadableStream so you’ll either pass that into a new Response to stream it or use one of the methods like text(), json(), blob(), etc.

Like @albert mentioned, there’s the ‘internal’ bindings which are effectively deprecated which will be used if the compatibility date is before 2022-04-18 iirc

2 Likes

I don’t think it’s possible to define a compatibility date when using Quick Edit in the Dashboard. When no compatibility date is defined a distant past date will be assumed instead. It is generally recommended you use Wrangler to manage your Workers :slightly_smiling_face:

2 Likes

Ok. That seems like a bug.

It’s actually not in the quick edit, but in Settings → Variables.

Essentially you’re saying that the “R2 Bucket Bindings” section of that page is broken, as there is no way to use it correctly?

Oh, actually compatability date is worker-wide, so it’ll work as a binding if I set the compat date?

I recommend you manage your Worker with the Wrangler CLI. Then you can specify a compatibility date and R2 bindings in the wrangler.toml file.

compatibility_date = "2022-05-12"
name = "r2-bindings"
type = "javascript"
workers_dev = true

[build.upload]
dir = "src"
format = "modules"
main = "./index.mjs"

[[r2_buckets]]
binding = "R2"
bucket_name = "test"

In the general case you’re right. Makes for better version control and such. But now for a quick test I need to install wrangler, deal with credentials, find my account ID, etc…

And ah yes, this is why I try to avoid using the wrangler CLI. It clears R2 Bucket Bindings on publish, likely because it’s an old version. So I try to upgrade it, but it can’t upgrade because I need to upgrade Node. Which is package managed on Ubuntu, so now in order to set the compat date I need to upgrade my OS to a new major version.

Sigh.

Thanks for your help. Wrangler is really putting me off of using Cloudflare products, though.

1 Like

This would only happen if you didn’t have them in your wrangler.toml - the ‘old’ wrangler has supported it since 07-02-2022. Release v1.19.8 · cloudflare/wrangler · GitHub

I’ve been in unupgradable wrangler/npm/node dependency hill (wow, Cloudflare doesn’t let me use well known term dependency h.ll) since 1.19.0. But after upgrading ubuntu (which I’d been avoiding since 21.10 was released with a known ZFS-corrupting bug that I had to first confirm was fixed) and then fighting npm, I got it working.

The secret was to use existing npm to install a newer npm globally, then use that npm from /usr/local/bin to install wrangler.

The only dependency system that’s not been a regression is the Go suite. Even the libc4/libc5/glibc migrations were less painful than npm.

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.