miniflare 0.0.0-e7ea6005c → 0.0.0-e8aaa3930

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.
@@ -8622,6 +8622,17 @@ var require_index_cjs = __commonJS({
8622
8622
  // ../workers-shared/asset-worker/src/index.ts
8623
8623
  import { WorkerEntrypoint } from "cloudflare:workers";
8624
8624
 
8625
+ // ../workers-shared/utils/performance.ts
8626
+ var PerformanceTimer = class {
8627
+ performanceTimer;
8628
+ constructor(performanceTimer) {
8629
+ this.performanceTimer = performanceTimer;
8630
+ }
8631
+ now() {
8632
+ return this.performanceTimer ? this.performanceTimer.timeOrigin + this.performanceTimer.now() : Date.now();
8633
+ }
8634
+ };
8635
+
8625
8636
  // ../workers-shared/utils/sentry.ts
8626
8637
  var import_toucan_js = __toESM(require_index_cjs());
8627
8638
  function setupSentry(request, context, dsn, clientId, clientSecret) {
@@ -8657,6 +8668,55 @@ function setupSentry(request, context, dsn, clientId, clientSecret) {
8657
8668
  return sentry.setUser({ userAgent, colo }), sentry;
8658
8669
  }
8659
8670
 
8671
+ // ../workers-shared/asset-worker/src/analytics.ts
8672
+ var Analytics = class {
8673
+ data = {};
8674
+ readyAnalytics;
8675
+ constructor(readyAnalytics) {
8676
+ this.readyAnalytics = readyAnalytics;
8677
+ }
8678
+ setData(newData) {
8679
+ this.data = { ...this.data, ...newData };
8680
+ }
8681
+ getData(key) {
8682
+ return this.data[key];
8683
+ }
8684
+ write() {
8685
+ this.readyAnalytics && this.readyAnalytics.logEvent({
8686
+ version: 1,
8687
+ accountId: 0,
8688
+ // TODO: need to plumb through
8689
+ indexId: this.data.hostname?.substring(0, 96),
8690
+ doubles: [
8691
+ this.data.requestTime ?? -1,
8692
+ // double1
8693
+ this.data.coloId ?? -1,
8694
+ // double2
8695
+ this.data.metalId ?? -1,
8696
+ // double3
8697
+ this.data.coloTier ?? -1
8698
+ // double4
8699
+ ],
8700
+ blobs: [
8701
+ this.data.hostname?.substring(0, 256),
8702
+ // blob1 - trim to 256 bytes
8703
+ this.data.userAgent?.substring(0, 256),
8704
+ // blob2 - trim to 256 bytes
8705
+ this.data.htmlHandling,
8706
+ // blob3
8707
+ this.data.notFoundHandling,
8708
+ // blob4
8709
+ this.data.error?.substring(0, 256),
8710
+ // blob5 - trim to 256 bytes
8711
+ this.data.version,
8712
+ // blob6
8713
+ this.data.coloRegion
8714
+ // blob7
8715
+ ]
8716
+ });
8717
+ }
8718
+ };
8719
+
8660
8720
  // ../workers-shared/asset-worker/src/assets-manifest.ts
8661
8721
  var AssetsManifest = class {
8662
8722
  data;
@@ -8716,7 +8776,8 @@ var AssetsManifest = class {
8716
8776
  // ../workers-shared/asset-worker/src/configuration.ts
8717
8777
  var applyConfigurationDefaults = (configuration) => ({
8718
8778
  html_handling: configuration?.html_handling ?? "auto-trailing-slash",
8719
- not_found_handling: configuration?.not_found_handling ?? "none"
8779
+ not_found_handling: configuration?.not_found_handling ?? "none",
8780
+ serve_directly: configuration?.serve_directly ?? !0
8720
8781
  });
8721
8782
 
8722
8783
  // ../workers-shared/asset-worker/src/responses.ts
@@ -8788,19 +8849,25 @@ function isCacheable(request) {
8788
8849
  }
8789
8850
 
8790
8851
  // ../workers-shared/asset-worker/src/handler.ts
8791
- var handleRequest = async (request, configuration, exists, getByETag) => {
8792
- let { pathname, search } = new URL(request.url), decodedPathname = decodePath(pathname), intent = await getIntent(decodedPathname, configuration, exists);
8852
+ var handleRequest = async (request, env, configuration, exists, getByETag) => {
8853
+ let { pathname, search } = new URL(request.url), decodedPathname = decodePath(pathname);
8854
+ decodedPathname = decodedPathname.replace(/\/+/g, "/");
8855
+ let intent = await getIntent(decodedPathname, configuration, exists);
8793
8856
  if (!intent)
8794
8857
  return new NotFoundResponse();
8795
8858
  let method = request.method.toUpperCase();
8796
8859
  if (!["GET", "HEAD"].includes(method))
8797
8860
  return new MethodNotAllowedResponse();
8798
8861
  let decodedDestination = intent.redirect ?? decodedPathname, encodedDestination = encodePath(decodedDestination);
8799
- if (encodedDestination !== pathname || intent.redirect)
8862
+ if (encodedDestination !== pathname && intent.asset || intent.redirect)
8800
8863
  return new TemporaryRedirectResponse(encodedDestination + search);
8801
8864
  if (!intent.asset)
8802
8865
  return new InternalServerErrorResponse(new Error("Unknown action"));
8803
- let asset = await getByETag(intent.asset.eTag), headers = getHeaders(intent.asset.eTag, asset.contentType, request), strongETag = `"${intent.asset.eTag}"`, weakETag = `W/${strongETag}`, ifNoneMatch = request.headers.get("If-None-Match") || "";
8866
+ let asset = await env.JAEGER.enterSpan("getByETag", async (span) => (span.setTags({
8867
+ pathname,
8868
+ eTag: intent.asset.eTag,
8869
+ status: intent.asset.status
8870
+ }), await getByETag(intent.asset.eTag))), headers = getHeaders(intent.asset.eTag, asset.contentType, request), strongETag = `"${intent.asset.eTag}"`, weakETag = `W/${strongETag}`, ifNoneMatch = request.headers.get("If-None-Match") || "";
8804
8871
  if ([weakETag, strongETag].includes(ifNoneMatch))
8805
8872
  return new NotModifiedResponse(null, { headers });
8806
8873
  let body = method === "HEAD" ? null : asset.readableStream;
@@ -9178,18 +9245,46 @@ var handleRequest = async (request, configuration, exists, getByETag) => {
9178
9245
  };
9179
9246
  }
9180
9247
  return null;
9181
- }, decodePath = (pathname) => pathname.split("/").map((x) => decodeURIComponent(x)).join("/"), encodePath = (pathname) => pathname.split("/").map((x) => encodeURIComponent(x)).join("/");
9248
+ }, decodePath = (pathname) => pathname.split("/").map((x) => {
9249
+ try {
9250
+ return decodeURIComponent(x);
9251
+ } catch {
9252
+ return x;
9253
+ }
9254
+ }).join("/"), encodePath = (pathname) => pathname.split("/").map((x) => {
9255
+ try {
9256
+ return encodeURIComponent(x);
9257
+ } catch {
9258
+ return x;
9259
+ }
9260
+ }).join("/");
9182
9261
 
9183
9262
  // ../workers-shared/asset-worker/src/utils/kv.ts
9184
- async function getAssetWithMetadataFromKV(assetsKVNamespace, assetKey, retries = 1) {
9263
+ async function getAssetWithMetadataFromKV(assetsKVNamespace, assetKey, sentry, retries = 1) {
9185
9264
  let attempts = 0;
9186
9265
  for (; attempts <= retries; )
9187
9266
  try {
9188
- return await assetsKVNamespace.getWithMetadata(assetKey, {
9189
- type: "stream",
9190
- cacheTtl: 31536e3
9191
- // 1 year
9192
- });
9267
+ let asset = await assetsKVNamespace.getWithMetadata(
9268
+ assetKey,
9269
+ {
9270
+ type: "stream",
9271
+ cacheTtl: 31536e3
9272
+ // 1 year
9273
+ }
9274
+ );
9275
+ if (asset.value === null) {
9276
+ let retriedAsset = await assetsKVNamespace.getWithMetadata(assetKey, {
9277
+ type: "stream",
9278
+ cacheTtl: 60
9279
+ // Minimum value allowed
9280
+ });
9281
+ return retriedAsset.value !== null && sentry && sentry.captureException(
9282
+ new Error(
9283
+ `Initial request for asset ${assetKey} failed, but subsequent request succeeded.`
9284
+ )
9285
+ ), retriedAsset;
9286
+ }
9287
+ return asset;
9193
9288
  } catch {
9194
9289
  if (attempts >= retries)
9195
9290
  throw new Error(
@@ -9201,38 +9296,98 @@ async function getAssetWithMetadataFromKV(assetsKVNamespace, assetKey, retries =
9201
9296
  }
9202
9297
  }
9203
9298
 
9299
+ // ../workers-shared/asset-worker/src/utils/mocks.ts
9300
+ function mockJaegerBindingSpan() {
9301
+ return {
9302
+ addLogs: () => {
9303
+ },
9304
+ setTags: () => {
9305
+ },
9306
+ end: () => {
9307
+ },
9308
+ isRecording: !0
9309
+ };
9310
+ }
9311
+ function mockJaegerBinding() {
9312
+ return {
9313
+ enterSpan: (_, span, ...args) => span(mockJaegerBindingSpan(), ...args),
9314
+ getSpanContext: () => ({
9315
+ traceId: "test-trace",
9316
+ spanId: "test-span",
9317
+ parentSpanId: "test-parent-span",
9318
+ traceFlags: 0
9319
+ }),
9320
+ runWithSpanContext: (_, callback, ...args) => callback(...args),
9321
+ traceId: "test-trace",
9322
+ spanId: "test-span",
9323
+ parentSpanId: "test-parent-span",
9324
+ cfTraceIdHeader: "test-trace:test-span:0"
9325
+ };
9326
+ }
9327
+
9204
9328
  // ../workers-shared/asset-worker/src/index.ts
9205
9329
  var src_default = class extends WorkerEntrypoint {
9206
9330
  async fetch(request) {
9207
- let sentry;
9331
+ let sentry, analytics = new Analytics(this.env.ANALYTICS), performance = new PerformanceTimer(this.env.UNSAFE_PERFORMANCE), startTimeMs = performance.now();
9208
9332
  try {
9209
- return sentry = setupSentry(
9333
+ this.env.JAEGER || (this.env.JAEGER = mockJaegerBinding()), sentry = setupSentry(
9210
9334
  request,
9211
9335
  this.ctx,
9212
9336
  this.env.SENTRY_DSN,
9213
9337
  this.env.SENTRY_ACCESS_CLIENT_ID,
9214
9338
  this.env.SENTRY_ACCESS_CLIENT_SECRET
9215
- ), handleRequest(
9339
+ );
9340
+ let config = applyConfigurationDefaults(this.env.CONFIG), userAgent = request.headers.get("user-agent") ?? "UA UNKNOWN";
9341
+ if (sentry) {
9342
+ let colo = this.env.COLO_METADATA.coloId;
9343
+ sentry.setTag("colo", this.env.COLO_METADATA.coloId), sentry.setTag("metal", this.env.COLO_METADATA.metalId), sentry.setUser({ userAgent, colo });
9344
+ }
9345
+ let url = new URL(request.url);
9346
+ return this.env.COLO_METADATA && this.env.VERSION_METADATA && analytics.setData({
9347
+ coloId: this.env.COLO_METADATA.coloId,
9348
+ metalId: this.env.COLO_METADATA.metalId,
9349
+ coloTier: this.env.COLO_METADATA.coloTier,
9350
+ coloRegion: this.env.COLO_METADATA.coloRegion,
9351
+ version: this.env.VERSION_METADATA.id,
9352
+ hostname: url.hostname,
9353
+ htmlHandling: config.html_handling,
9354
+ notFoundHandling: config.not_found_handling,
9355
+ userAgent
9356
+ }), this.env.JAEGER.enterSpan("handleRequest", async (span) => (span.setTags({
9357
+ hostname: url.hostname,
9358
+ eyeballPath: url.pathname,
9359
+ env: this.env.ENVIRONMENT
9360
+ }), handleRequest(
9216
9361
  request,
9217
- applyConfigurationDefaults(this.env.CONFIG),
9362
+ this.env,
9363
+ config,
9218
9364
  this.unstable_exists.bind(this),
9219
9365
  this.unstable_getByETag.bind(this)
9366
+ ))).catch(
9367
+ (err) => this.handleError(sentry, analytics, performance, startTimeMs, err)
9220
9368
  );
9221
9369
  } catch (err) {
9370
+ return this.handleError(sentry, analytics, performance, startTimeMs, err);
9371
+ }
9372
+ }
9373
+ handleError(sentry, analytics, performance, startTimeMs, err) {
9374
+ try {
9222
9375
  let response = new InternalServerErrorResponse(err);
9223
- return sentry && sentry.captureException(err), response;
9376
+ return sentry && sentry.captureException(err), err instanceof Error && analytics.setData({ error: err.message }), response;
9377
+ } finally {
9378
+ analytics.setData({ requestTime: performance.now() - startTimeMs }), analytics.write();
9224
9379
  }
9225
9380
  }
9226
9381
  async unstable_canFetch(request) {
9227
- let url = new URL(request.url), method = request.method.toUpperCase(), decodedPathname = decodePath(url.pathname), intent = await getIntent(
9382
+ let url = new URL(request.url), decodedPathname = decodePath(url.pathname);
9383
+ return await getIntent(
9228
9384
  decodedPathname,
9229
9385
  {
9230
9386
  ...applyConfigurationDefaults(this.env.CONFIG),
9231
9387
  not_found_handling: "none"
9232
9388
  },
9233
9389
  this.unstable_exists.bind(this)
9234
- );
9235
- return intent && ["GET", "HEAD"].includes(method) ? new MethodNotAllowedResponse() : intent !== null;
9390
+ ) !== null;
9236
9391
  }
9237
9392
  async unstable_getByETag(eTag) {
9238
9393
  let asset = await getAssetWithMetadataFromKV(