Skip to content

Commit

Permalink
[playground-preview-worker] fix: don't report invalid upload input (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mrbbot authored Feb 7, 2024
1 parent 49696ab commit e5cdd7f
Show file tree
Hide file tree
Showing 9 changed files with 338 additions and 168 deletions.
4 changes: 4 additions & 0 deletions packages/playground-preview-worker/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ["@cloudflare/eslint-config-worker"],
};
4 changes: 3 additions & 1 deletion packages/playground-preview-worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
"build-middleware": "pnpm run build-middleware:common && pnpm run build-middleware:loader",
"build-middleware:common": "pnpm dlx esbuild ../wrangler/templates/middleware/common.ts --outfile=src/middleware/common.module.template",
"build-middleware:loader": "pnpm dlx esbuild ../wrangler/templates/middleware/loader-modules.ts --outfile=src/middleware/loader.module.template",
"check:lint": "eslint .",
"deploy": "wrangler -j deploy",
"deploy:testing": "wrangler -j deploy -e testing",
"start": "wrangler -j dev",
"test:e2e": "vitest run"
},
"dependencies": {
"hono": "^3.3.2",
"hono": "^3.12.11",
"zod": "^3.22.3"
},
"devDependencies": {
"@cloudflare/eslint-config-worker": "workspace:*",
"@cloudflare/workers-types": "^4.20230321.0",
"@types/cookie": "^0.5.1",
"cookie": "^0.5.0",
Expand Down
124 changes: 124 additions & 0 deletions packages/playground-preview-worker/src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import type { ZodIssue } from "zod";

export class HttpError extends Error {
constructor(
message: string,
readonly status: number,
// Only report errors to sentry when they represent actionable errors
readonly reportable: boolean
) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
toResponse() {
return Response.json(
{
error: this.name,
message: this.message,
data: this.data,
},
{
status: this.status,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,PUT,POST",
},
}
);
}

get data(): Record<string, unknown> {
return {};
}
}

export class WorkerTimeout extends HttpError {
name = "WorkerTimeout";
constructor() {
super("Worker timed out", 400, false);
}

toResponse(): Response {
return new Response("Worker timed out");
}
}

export class ServiceWorkerNotSupported extends HttpError {
name = "ServiceWorkerNotSupported";
constructor() {
super(
"Service Workers are not supported in the Workers Playground",
400,
false
);
}
}
export class ZodSchemaError extends HttpError {
name = "ZodSchemaError";
constructor(private issues: ZodIssue[]) {
super("Something went wrong", 500, true);
}

get data(): { issues: string } {
return { issues: JSON.stringify(this.issues) };
}
}

export class PreviewError extends HttpError {
name = "PreviewError";
constructor(private error: string) {
super(error, 400, false);
}

get data(): { error: string } {
return { error: this.error };
}
}

export class TokenUpdateFailed extends HttpError {
name = "TokenUpdateFailed";
constructor() {
super("Provide valid token", 400, false);
}
}

export class RawHttpFailed extends HttpError {
name = "RawHttpFailed";
constructor() {
super("Provide valid token", 400, false);
}
}

export class PreviewRequestFailed extends HttpError {
name = "PreviewRequestFailed";
constructor(private tokenId: string | undefined, reportable: boolean) {
super("Valid token not found", 400, reportable);
}
get data(): { tokenId: string | undefined } {
return { tokenId: this.tokenId };
}
}

export class UploadFailed extends HttpError {
name = "UploadFailed";
constructor() {
super("Valid token not provided", 401, false);
}
}

export class PreviewRequestForbidden extends HttpError {
name = "PreviewRequestForbidden";
constructor() {
super("Preview request forbidden", 403, false);
}
}

export class BadUpload extends HttpError {
name = "BadUpload";
constructor(message = "Invalid upload", private readonly error?: string) {
super(message, 400, false);
}
get data() {
return { error: this.error };
}
}
127 changes: 11 additions & 116 deletions packages/playground-preview-worker/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { Hono } from "hono";
import { getCookie, setCookie } from "hono/cookie";
import prom from "promjs";
import { Toucan } from "toucan-js";
import { ZodIssue } from "zod";
import {
HttpError,
PreviewRequestFailed,
PreviewRequestForbidden,
RawHttpFailed,
TokenUpdateFailed,
UploadFailed,
} from "./errors";
import { handleException, setupSentry } from "./sentry";
import type { RegistryType } from "promjs";
import type { Toucan } from "toucan-js";

const app = new Hono<{
Bindings: Env;
Expand All @@ -20,118 +27,6 @@ const app = new Hono<{

const rootDomain = ROOT;
const previewDomain = PREVIEW;
export class HttpError extends Error {
constructor(
message: string,
readonly status: number,
// Only report errors to sentry when they represent actionable errors
readonly reportable: boolean
) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
toResponse() {
return Response.json(
{
error: this.name,
message: this.message,
data: this.data,
},
{
status: this.status,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,PUT,POST",
},
}
);
}

get data(): Record<string, unknown> {
return {};
}
}

export class WorkerTimeout extends HttpError {
name = "WorkerTimeout";
constructor() {
super("Worker timed out", 400, false);
}

toResponse(): Response {
return new Response("Worker timed out");
}
}

export class ServiceWorkerNotSupported extends HttpError {
name = "ServiceWorkerNotSupported";
constructor() {
super(
"Service Workers are not supported in the Workers Playground",
400,
false
);
}
}
export class ZodSchemaError extends HttpError {
name = "ZodSchemaError";
constructor(private issues: ZodIssue[]) {
super("Something went wrong", 500, true);
}

get data(): { issues: string } {
return { issues: JSON.stringify(this.issues) };
}
}

export class PreviewError extends HttpError {
name = "PreviewError";
constructor(private error: string) {
super(error, 400, false);
}

get data(): { error: string } {
return { error: this.error };
}
}

class TokenUpdateFailed extends HttpError {
name = "TokenUpdateFailed";
constructor() {
super("Provide valid token", 400, false);
}
}

class RawHttpFailed extends HttpError {
name = "RawHttpFailed";
constructor() {
super("Provide valid token", 400, false);
}
}

class PreviewRequestFailed extends HttpError {
name = "PreviewRequestFailed";
constructor(private tokenId: string | undefined, reportable: boolean) {
super("Valid token not found", 400, reportable);
}
get data(): { tokenId: string | undefined } {
return { tokenId: this.tokenId };
}
}

class UploadFailed extends HttpError {
name = "UploadFailed";
constructor() {
super("Valid token not provided", 401, false);
}
}

class PreviewRequestForbidden extends HttpError {
name = "PreviewRequestForbidden";
constructor() {
super("Preview request forbidden", 403, false);
}
}

/**
* Given a preview token, this endpoint allows for raw http calls to be inspected
Expand Down Expand Up @@ -254,7 +149,7 @@ app.get(`${rootDomain}/`, async (c) => {
});

app.post(`${rootDomain}/api/worker`, async (c) => {
let userId = getCookie(c, "user");
const userId = getCookie(c, "user");
if (!userId) {
throw new UploadFailed();
}
Expand All @@ -275,7 +170,7 @@ app.post(`${rootDomain}/api/worker`, async (c) => {

app.get(`${rootDomain}/api/inspector`, async (c) => {
const url = new URL(c.req.url);
let userId = url.searchParams.get("user");
const userId = url.searchParams.get("user");
if (!userId) {
throw new PreviewRequestFailed("", false);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/playground-preview-worker/src/realish.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { z } from "zod";
import { PreviewError } from ".";
import { PreviewError } from "./errors";

const APIResponse = <T extends z.ZodTypeAny>(resultSchema: T) =>
z.union([
Expand Down
4 changes: 2 additions & 2 deletions packages/playground-preview-worker/src/sentry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Toucan } from "toucan-js";
import { z, ZodError } from "zod";
import { HttpError, ZodSchemaError } from ".";
import { ZodError } from "zod";
import { HttpError, ZodSchemaError } from "./errors";

export function handleException(e: unknown, sentry: Toucan): Response {
console.error(e);
Expand Down
Loading

0 comments on commit e5cdd7f

Please sign in to comment.