@cloudflare/sandbox 0.12.7 → 0.12.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5322,11 +5322,22 @@ function xmlResponse(body, status = 200) {
5322
5322
  function normalizeObjectKey(value) {
5323
5323
  return value.replace(/^\/+/, "");
5324
5324
  }
5325
+ function decodeObjectKey(value) {
5326
+ try {
5327
+ return decodeURIComponent(value);
5328
+ } catch {
5329
+ return value;
5330
+ }
5331
+ }
5325
5332
  function trimTrailingSlashes(s) {
5326
5333
  let end = s.length;
5327
5334
  while (end > 0 && s[end - 1] === "/") end--;
5328
5335
  return s.slice(0, end);
5329
5336
  }
5337
+ function normalizeMountPrefix(prefix) {
5338
+ if (!prefix) return void 0;
5339
+ return trimTrailingSlashes(normalizeObjectKey(prefix)) || void 0;
5340
+ }
5330
5341
  function parsePath(pathname) {
5331
5342
  const stripped = pathname.startsWith("/") ? pathname.slice(1) : pathname;
5332
5343
  if (!stripped) return null;
@@ -5524,15 +5535,17 @@ async function handleGetObject(r2, key, request) {
5524
5535
  headers
5525
5536
  });
5526
5537
  }
5527
- async function handlePutObject(r2, bucketName, key, request, env$1, permitted, mountPrefix) {
5538
+ async function handlePutObject(r2, bucketName, key, request, env$1, buckets) {
5528
5539
  const copySourceHeader = request.headers.get("x-amz-copy-source");
5529
5540
  if (copySourceHeader) {
5530
5541
  const copySource = parseCopySource(copySourceHeader);
5531
5542
  if (!copySource || !copySource.key) return new Response("Bad Request: invalid x-amz-copy-source", { status: 400 });
5532
- if (!permitted.has(copySource.bucket)) return new Response(`Access to R2 bucket "${copySource.bucket}" is not permitted. Call mountBucket() with this bucket before accessing it.`, { status: 403 });
5543
+ if (!Object.hasOwn(buckets, copySource.bucket)) return new Response(`Access to R2 bucket "${copySource.bucket}" is not permitted. Call mountBucket() with this bucket before accessing it.`, { status: 403 });
5544
+ const sourceParams = buckets[copySource.bucket];
5533
5545
  const sourceBucket = copySource.bucket === bucketName ? r2 : resolveR2Bucket(env$1, copySource.bucket);
5534
5546
  if (!sourceBucket) return new Response(`R2 binding "${copySource.bucket}" not found in Worker env. Ensure the binding name matches the bucket name passed to mountBucket().`, { status: 500 });
5535
- const sourceKey = mountPrefix && copySource.bucket === bucketName ? `${mountPrefix}/${copySource.key}` : copySource.key;
5547
+ const sourcePrefix = normalizeMountPrefix(sourceParams.prefix);
5548
+ const sourceKey = sourcePrefix ? `${sourcePrefix}/${copySource.key}` : copySource.key;
5536
5549
  const sourceObject = await sourceBucket.get(sourceKey);
5537
5550
  if (!sourceObject) return new Response(null, { status: 404 });
5538
5551
  const httpMetadata = request.headers.get("x-amz-metadata-directive")?.toUpperCase() === "REPLACE" ? extractHttpMetadata(request) : sourceObject.httpMetadata;
@@ -5603,11 +5616,11 @@ const r2EgressHandler = async (request, env$1, ctx) => {
5603
5616
  const url = new URL(request.url);
5604
5617
  const parsed = parsePath(url.pathname);
5605
5618
  if (!parsed) return new Response("Bad Request: empty path", { status: 400 });
5606
- const { bucket: bucketName, key } = parsed;
5619
+ const { bucket: bucketName, key: encodedKey } = parsed;
5620
+ const key = decodeObjectKey(encodedKey);
5607
5621
  if (!ctx.params?.buckets || !(bucketName in ctx.params.buckets)) return new Response(`Access to R2 bucket "${bucketName}" is not permitted. Call mountBucket() with this bucket before accessing it.`, { status: 403 });
5608
5622
  const bucketParams = ctx.params.buckets[bucketName];
5609
- const rawPrefix = bucketParams.prefix;
5610
- const mountPrefix = rawPrefix ? trimTrailingSlashes(normalizeObjectKey(rawPrefix)) : void 0;
5623
+ const mountPrefix = normalizeMountPrefix(bucketParams.prefix);
5611
5624
  const readOnly = bucketParams.readOnly ?? false;
5612
5625
  const r2 = resolveR2Bucket(env$1, bucketName);
5613
5626
  if (!r2) return new Response(`R2 binding "${bucketName}" not found in Worker env. Ensure the binding name matches the bucket name passed to mountBucket().`, { status: 500 });
@@ -5619,7 +5632,6 @@ const r2EgressHandler = async (request, env$1, ctx) => {
5619
5632
  return new Response("Method Not Allowed", { status: 405 });
5620
5633
  }
5621
5634
  const fullKey = mountPrefix ? `${mountPrefix}/${key}` : key;
5622
- const permitted = new Set(Object.keys(ctx.params.buckets));
5623
5635
  if (readOnly && (method === "PUT" || method === "DELETE" || method === "POST" && (url.searchParams.has("uploads") || url.searchParams.has("uploadId")))) return new Response("Forbidden: bucket mount is read-only", { status: 403 });
5624
5636
  if (method === "POST" && url.searchParams.has("uploads")) return handleCreateMultipartUpload(r2, bucketName, fullKey, request);
5625
5637
  if (method === "POST" && url.searchParams.has("uploadId")) return handleCompleteMultipartUpload(r2, bucketName, fullKey, url, request);
@@ -5628,7 +5640,7 @@ const r2EgressHandler = async (request, env$1, ctx) => {
5628
5640
  switch (method) {
5629
5641
  case "HEAD": return handleHeadObject(r2, fullKey);
5630
5642
  case "GET": return handleGetObject(r2, fullKey, request);
5631
- case "PUT": return handlePutObject(r2, bucketName, fullKey, request, env$1, permitted, mountPrefix);
5643
+ case "PUT": return handlePutObject(r2, bucketName, fullKey, request, env$1, ctx.params.buckets);
5632
5644
  case "DELETE": return handleDeleteObject(r2, fullKey);
5633
5645
  default: return new Response("Method Not Allowed", { status: 405 });
5634
5646
  }
@@ -7168,7 +7180,7 @@ function createTunnelsHandler(host) {
7168
7180
  * This file is auto-updated by .github/changeset-version.ts during releases
7169
7181
  * DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
7170
7182
  */
7171
- const SDK_VERSION = "0.12.7";
7183
+ const SDK_VERSION = "0.12.9";
7172
7184
 
7173
7185
  //#endregion
7174
7186
  //#region src/sandbox.ts
@@ -11549,4 +11561,4 @@ var Sandbox = class Sandbox extends Container {
11549
11561
 
11550
11562
  //#endregion
11551
11563
  export { PortClient as A, InvalidBackupConfigError as B, collectFile as C, SandboxClient as D, isPlatformTransientError as E, BackupCreateError as F, SessionTerminatedError as G, ProcessExitedBeforeReadyError as H, BackupExpiredError as I, BackupNotFoundError as L, FileClient as M, CommandClient as N, UtilityClient as O, BackupClient as P, BackupRestoreError as R, validateTunnelName as S, isDurableObjectCodeUpdateReset as T, ProcessReadyTimeoutError as U, OperationInterruptedError as V, RPCTransportError as W, responseToAsyncIterable as _, PREVIEW_PROXY_HEADER as a, sanitizeSandboxId as b, PREVIEW_PROXY_SANDBOX_ID_HEADER as c, BucketUnmountError as d, InvalidMountConfigError as f, parseSSEStream as g, asyncIterableToSSEStream as h, proxyTerminal as i, GitClient as j, ProcessClient as k, PREVIEW_PROXY_TOKEN_HEADER as l, S3FSMountError as m, Sandbox as n, PREVIEW_PROXY_HEADERS as o, MissingCredentialsError as p, getSandbox as r, PREVIEW_PROXY_PORT_HEADER as s, ContainerProxy$1 as t, BucketMountError as u, CodeInterpreter as v, streamFile as w, validatePort as x, SandboxSecurityError as y, ContainerUnavailableError as z };
11552
- //# sourceMappingURL=sandbox-CcCJwCbh.js.map
11564
+ //# sourceMappingURL=sandbox-D0rNqxlr.js.map