Skip to content

Commit

Permalink
feat(sentry): migration sur la nouvelle version de Sentry
Browse files Browse the repository at this point in the history
  • Loading branch information
m-maillot committed Feb 12, 2025
1 parent e1b879d commit d1be4b7
Show file tree
Hide file tree
Showing 21 changed files with 878 additions and 55 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/review-auto.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ jobs:
run: |
echo "SITE_URL=https://${{ steps.env.outputs.subdomain }}.ovh.fabrique.social.gouv.fr" >> $GITHUB_ENV
- name: Run test e2e
env:
CYPRESS: "true"
run: |
TEST_BASEURL=${{ env.SITE_URL }} TEST_MODE=light yarn test:e2e
- name: Archive generated screenshots
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/review.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ jobs:
run: |
echo "SITE_URL=https://${{ steps.env.outputs.subdomain }}.ovh.fabrique.social.gouv.fr" >> $GITHUB_ENV
- name: Run test e2e
env:
CYPRESS: "true"
run: |
TEST_BASEURL=${{ env.SITE_URL }} TEST_MODE=light yarn test:e2e
- name: Archive generated screenshots
Expand Down
16 changes: 16 additions & 0 deletions .kontinuous/env/dev/templates/sentry.sealed-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
annotations:
sealedsecrets.bitnami.com/cluster-wide: 'true'
name: sentry
spec:
encryptedData:
SENTRY_DSN: AgDCMaihNlpRZTWAxW87fBaiGPbNLugKZnWAeLI8Tux2IKwn1xpIkeL/5tqHX3hwUJf1UFbanz2u1NzBAW1l/hQ0CANRGDQcqX06q9/Rbwr+s9aa8yflYJIQM+E0XHVYaauCyJBvfb00Ep8cSdPwUjA8aUug0asfNcz1iPC25bEB8HX+9Nz8L4MPeArsGiirjVNSWqojk+odLKydSatIpO81STTCF8/pCX0+Rs/6Zg2eFZU17sS1E6eyjOAec7WFF1S6l8D0o+B6WOroopSflnmY9+QWHf2UBVRb5y3PLbpR8K8jrn9ZGjjXKT77RHu6/pVR2AklGSk/ri0XAXT+TvFzFFKoy5sloZrDPdvA1JQnVgxZV5syaIQcu+BOKIN9xvUWop/hsFwpmbxFgfyDxgFV5UmGgF014RdhEGpWc6FuQc3kRXbTQerxF/nLH1OTFqnhA+jsHYNIsfv8Q24DIFE17yM7RI7W9CkFy//hqHES1AayRwx2njZxdUSwNyyzQcQIhvGQP5KcLXU9GIOr3UxCdJBswzYqTTt1VGdBMkM0I+xZgdXIWaL4WHrfe+eQhr6pwJtIJZNtpijvFuz2Ot8Ewm1PILCl0kbq9IuJb5FkDqMuzskMa/AYesfFEMUdLo7ybIHaag2i/DYdzw2U1sqT/M8tc7yZW/ztcG5rHQ3vK1twhmMznl05bpuzSozTz2X68qYwC6otGlNSlPxntOwzpL+irlJYE3JXqz8nds064EOJf7w7lffzMKpPWiyNEL3j39/ma7k6E4EwWFUwbqbSvJju6ajB8YD3e6U=
SENTRY_AUTH_TOKEN: AgAaGu/aJjM6cEx4sEKuLC3bjJrE4AnaTQKTmcG57OcJUonD6zo2ytoNx8dKwEhp6SNO8mq1ZHXJuzEDc/0vqVinTYfg3ZYmHpLMmK6ofclVcgqT/za45gDJCgt/3x3hUGrNiUz1c1hYjNje2FQ4gIvUYUYGaMSEsWGPi2cZrIsCoeaYP2l2IpVoohmAj/lfCboJD2A3d0hFJDbArqTYoBECuPf2QpidNWi14vSwZTtugGbz9wplR+Vc/P0pzkz/M/p9dQB/XwMXiPyrUHNC2bWmBfs4MctoMiG/mRRAAnUyssHLJt615IAZuRpXN0ZGi2yw+vQDG5ggq2VKHbWzPnXR2ggZI19iFFLGvdjvYdu3uQiPin3PWzqo6pbAkFCjg8h7gTaaMBtXd5zFa4xrSQ+UfQfJ7wKMABZ0Ry+XpqkW2ZkRuQdOWQaOFKy13j/+3PLg1hQBd7iEyoYIUYjR1PyIQG1fp7jG9FRvglvJimzlW8PsjSw19p6wvsRscK+u3jlHdQJ0+pZTCe7AyZvM91T9LPwW5mj9s+RM5jtJ+/b6WKrDWt9cAk4YR0Vjdja+I3yueLs4CM8a68kcLY1vsjfATWUMh1keMaMngn39UMhPOMdz76gcFGIwcn63v7wi//jIe1ZhY97566JezPZ9AFx4Iw44/T5fF/gA6SGLw0+UGuQbaPpLf1w6Dmz9KaOnQzsZSgWyTNBEX7+9LnuRL1UL4RRCah4MlFdRigvP7H1nay56QKSaZREPCisXp/h3t0XPlbjdNr529Sqwj674LC039JWYRhy+6r11rjuPz7V45FnNSoACozkNlGoFkXkP4fesBsyLiUR89n0Qs2k5ku/JTrosLLl/aRDDPXvuP0f6xXuMiFSt66MSXR/US2JGaokuOC0NL/rdPWcULGWMK8JlAtjZyimqO/KAlneLnIBa3EV1kbpSHbOdvaKf4M0RQBu/AUPT4NiDLrg9ddGkh2e2lF4wRNACysuNjb00R4YuKOe8c+VCJX2HUEvgXxsnrWL76UZi9wiQ
template:
metadata:
annotations:
sealedsecrets.bitnami.com/cluster-wide: 'true'
name: sentry
type: Opaque
1 change: 0 additions & 1 deletion .kontinuous/env/dev/templates/www.sealed-secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ spec:
encryptedData:
ELASTICSEARCH_URL: AgAUJaPLaiM5gyJSFwbPwfZauAtxMMmW85PhhA85jAmz1z2k3MS/tgc0hzdwLJ6psJcivAONP11BcJ3uXuz7MvOsdXKhkKbU03nb4lB/jDhYh3dAj2Keuz0TMKgZSZUxj8rETucDRgusJ6I35tVFshXG3tbqlP/K290CrmlqA2hWVAHoR9HtdBdbRjW3vBxiOjjSvcUo7bWCU/9/TmMhWskkgVLG6bQOSUWZBS+9ab2yzg/2aqNN7ZwzZc5yzurLjdkk/vJhPTSMbmdCy3DIxTaDMt4fcJ6ONxQZtOW5MZqlhdMEmYbW+/OuHQlDt8kYR5hIn35WIRWOXa5109GyyI9UXFOHtRn4AxrxuWlyzzwiuQsWk147ozqU1bV1j80HFDJtFmopP2jDCRK9ijmLsBThBBqyPzFrfPZWQsLEj+xAb+jc2fuwKtfeNYnzoY9p0/IKwrUFkBjzjrggCSkm87bVPZGFUBK0tnL1l4OYB3qJhyWEVlL1nPFDCxIXOO3nIwC9XH6wUKe5VIIR/XZDWPnYFI+kktHFgPgGCqsHEujwp8w+aVpQy+L3r5kSuWonUguUIUDuvGYc/I5nXzpy25yKpSXjq/1d1vvx66pD8AngyDSGowGVX3nfvf2dAq1K/UQQUvWq2Aaf5Bh03tA0RVPczgtAQZ7iwueoMVWzBddGAywcIJOW1lJQJ6kQZ6flt1dnDosLSU7Ra6KdRAElopLjqNzEUFJpGzv+Di72mcrOWDkUxqz2qFssfwDuPaQ/HLS0+mgt8qHFJLgQxCOCuhyz2GWv
ELASTICSEARCH_TOKEN_API: AgC4tRnPP5Rq9G12mvlWjt/m8w4Z6AAZPQwbLxK2sYHEfF7KuH+QVeknaX6x861lGHSZq4r1bJJJUBInCG1gwV8j8ndt6g4GfAul+fouRoYVCoyCyRZ063qXm+OsTvaihlbi8hAPoTt+iDWkX6PRkMMrWrBTgxGHpoTizeqLYyu2EXz5nSmF1UfzIgXfcArD7k8ESbQ9rJEPdEWSoH9xbami3FnPltID21g0JViXjHTm3nuIO7NHH6/gkQdXYL7mxGh+wy6bDo0+98WV5eFzUc22D9rqsd/q2RaW5s/fUCnWnU0WDknSJR4JWAOh3RFWIJ+NiWMpa4oiYs/sTp560GdJC4aZoWI7oGEzjVdHRjC8IbQIiPCLj+3KKFVFsgGLub6/ILRVtZwynYLv1V+D9GvjNMQJAsLVk/98+6GneZKHAEObEbuCw9mij+cgJzYog/aKMHF4JAnM+LAZVYJVWyn2Te0fqq6Z4NjjP6XIOGNMNQFro9+d335u1qAb50L/Rpkvzi1Qon0EBVGgtj9/VZOLk7MsJstKtB3nMI95ObsVfRCh5BxNEbC0FHMmRdUOcx204F2Lteb51LaVqL/ARFZPYRPw9Z1Cgi4focKH3J+oEAKp1N8jvymtobhIqoM+xLfmSmVvBbq5F3VfwdXEXm3WYC5gAZW7Fgkx3qForfw/lBShk/aXhs3FzAAWnXgZao8bHEsbGxGpRtwBwG5Y/WnzlVy/Z1VKI6klxK7Vn63AgrwQjsQ8izdK6EtzhJhjG/keor2Ye5Hp3MOA16A=
SENTRY_AUTH_TOKEN: AgCKID/es7BZx/js5TA1A0OXpHRvTMzxsKYdfrwXEtM+sUj9NAjPWnNMw+x/ZrxJ+927XkzvOc9bCnMMEHylXUwuz3zf1u3XYFBaGd3vG0VCDeHshH5vokLEhEy3d44qdJmIMWqXYFGWjuWj/3yW1x3+4DyBQGO1zxYleiPppYrnheF3yrdwFUM/v4PnHsBPxqL8Tqr+tdi4J3o3POanNglbF4/AsgNJbpGOFxkhZXCewWhEr9lF+sX7bxbo7Pl5tc/RwdTn9xtQiEvO8Sqxkl/cPwXcEvylTWc2eaGg76deD4Le1LEyFpNDQ5AzTmt+LnC9tGmBvpkYVZz5uJev+ybhAcj0OcOOZq1Cg0p5hZl8zD5JmHES78mMxpGvc9799wIfNx26ASNtHj+dFBRrHrgfqIrGoI9MDaSSEB9w4PBLTZsuLdaFZJgiWtzVPud1cnYSaYC4tsfG3qhHbKOUJXOA+BvJR2TZEdzHZCWMGUVg0slUjGCCbkvD7HDEswXYATDj3RzhkNbwhvbWp2HSfS8awlzTbOOhP3SQGr3EiuD0OVgBW/fRBAY77cq6NnNqpiK4STutN9uC801Zxd9uPsWiY5nv0XtMzS6No4ZutyKR6gI10ZSQqvRrdcYbAPoYbOBIUR2zXyzd1bx+wCnojRofTf/gHptKq9FopKDlTmxj040rTW42CIQzXgf5kVRUxKZrDB0LICLwRNU+YYdK8kuBIvisOQ9dx2P6Ez4nAfWdnO93z87tt7306a9kIyuw/diN75t6ai6uJhF0ac+FiIEDJTNexVg7CQg2kPzgpH4M5H7RgsxnKxPm1qnbDMJ7KG3Vzu4BG4vc/fa6fgihpN+t0b5PqHbuWaskhqUSEPsKdx8Q2cRgL0+27JCpdWRDQDX8wF3MTgdWWxE3TYZmjGq42u9TNfHBBmr/PCDfhPI3PFV+WZkwayV3K3LIjQf9H8GcpZD7w5OyL44oAYcL6Iye6Y1420A6mq5b1a9rayO6wWlLQQwtX78haGVcMv7RXo+bK/CXu+IR
template:
metadata:
annotations:
Expand Down
14 changes: 9 additions & 5 deletions .kontinuous/env/dev/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ jobs:
runs:
build-app:
use: build
env:
- name: NEXT_PUBLIC_SENTRY_DSN
valueFrom:
secretKeyRef:
name: sentry
key: SENTRY_DSN
with:
buildArgs:
NEXT_PUBLIC_SENTRY_DSN: https://[email protected]/107
NEXT_PUBLIC_SENTRY_PUBLIC_KEY: 81b6e3d265cf736588f894040d265705
NEXT_PUBLIC_SENTRY_PROJECT_ID: 107
NEXT_PUBLIC_SENTRY_BASE_URL: https://sentry.fabrique.social.gouv.fr
NEXT_PUBLIC_SENTRY_ENV: dev
NEXT_PUBLIC_SENTRY_DSN: "$NEXT_PUBLIC_SENTRY_DSN"
NEXT_PUBLIC_SENTRY_BASE_URL: https://sentry2.fabrique.social.gouv.fr
NEXT_PUBLIC_CDTN_ENV: development
NEXT_PUBLIC_SENTRY_RELEASE: "{{.Values.global.branchSlug32}}"
NEXT_PUBLIC_BUCKET_DEFAULT_FOLDER: "default"
NEXT_PUBLIC_BUCKET_SITEMAP_FOLDER: "sitemap"
Expand Down
11 changes: 11 additions & 0 deletions .kontinuous/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ app:
name: www-configmap
- secretRef:
name: www-secret
env:
- name: SENTRY_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: sentry
key: SENTRY_AUTH_TOKEN
- name: NEXT_PUBLIC_SENTRY_DSN
valueFrom:
secretKeyRef:
name: sentry
key: SENTRY_DSN
resources:
limits:
cpu: 400m
Expand Down
10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ ARG NEXT_PUBLIC_SENTRY_DSN
ENV NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN
ARG NEXT_PUBLIC_SENTRY_ENV
ENV NEXT_PUBLIC_SENTRY_ENV=$NEXT_PUBLIC_SENTRY_ENV
ARG NEXT_PUBLIC_SENTRY_PUBLIC_KEY
ENV NEXT_PUBLIC_SENTRY_PUBLIC_KEY=$NEXT_PUBLIC_SENTRY_PUBLIC_KEY
ARG NEXT_PUBLIC_SENTRY_PROJECT_ID
ENV NEXT_PUBLIC_SENTRY_PROJECT_ID=$NEXT_PUBLIC_SENTRY_PROJECT_ID
ARG NEXT_PUBLIC_SENTRY_BASE_URL
ENV NEXT_PUBLIC_SENTRY_BASE_URL=$NEXT_PUBLIC_SENTRY_BASE_URL
ARG NEXT_PUBLIC_COMMIT
Expand All @@ -56,13 +52,18 @@ ENV NEXT_PUBLIC_ES_INDEX_PREFIX=$NEXT_PUBLIC_ES_INDEX_PREFIX
ARG NEXT_PUBLIC_BRANCH_NAME_SLUG
ENV NEXT_PUBLIC_BRANCH_NAME_SLUG=$NEXT_PUBLIC_BRANCH_NAME_SLUG

# Enable source map generation during build
ENV GENERATE_SOURCEMAP=true \
NODE_ENV=production

# hadolint ignore=SC2046
RUN --mount=type=secret,id=sentry_auth_token \

Check failure on line 60 in Dockerfile

View workflow job for this annotation

GitHub Actions / Lint Dockerfile

SC1070 error: Parsing stopped here. Mismatched keywords or invalid parentheses?
--mount=type=secret,id=elasticsearch_token_api \
--mount=type=secret,id=elasticsearch_url \
export SENTRY_AUTH_TOKEN=$(cat /run/secrets/sentry_auth_token) && \
export ELASTICSEARCH_TOKEN_API=$(cat /run/secrets/elasticsearch_token_api) && \
export ELASTICSEARCH_URL=$(cat /run/secrets/elasticsearch_url) && \
export GENERATE_SOURCEMAP=true; && \
yarn build && \
yarn workspaces focus --production --all && \
yarn cache clean
Expand All @@ -86,6 +87,7 @@ COPY --from=dist --chown=1000:1000 /dep/packages/code-du-travail-frontend/next.c
COPY --from=dist --chown=1000:1000 /dep/packages/code-du-travail-frontend/instrumentation.ts /app/packages/code-du-travail-frontend/instrumentation.ts
COPY --from=dist --chown=1000:1000 /dep/packages/code-du-travail-frontend/sentry.client.config.ts /app/packages/code-du-travail-frontend/sentry.client.config.ts
COPY --from=dist --chown=1000:1000 /dep/packages/code-du-travail-frontend/sentry.server.config.ts /app/packages/code-du-travail-frontend/sentry.server.config.ts
COPY --from=dist --chown=1000:1000 /dep/packages/code-du-travail-frontend/sentry.edge.config.ts /app/packages/code-du-travail-frontend/sentry.edge.config.ts
COPY --from=dist --chown=1000:1000 /dep/packages/code-du-travail-frontend/redirects.json /app/packages/code-du-travail-frontend/redirects.json
COPY --from=dist --chown=1000:1000 /dep/packages/code-du-travail-frontend/scripts /app/packages/code-du-travail-frontend/scripts
COPY --from=dist --chown=1000:1000 /dep/package.json /app/package.json
Expand Down
262 changes: 262 additions & 0 deletions packages/code-du-travail-frontend/app/api/monitoring/envelope/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
import { type NextRequest } from "next/server";

export const dynamic = "force-dynamic";

export async function POST(request: NextRequest) {
const sentryUrl = process.env.SENTRY_URL;
if (!sentryUrl) {
console.error("Sentry URL not configured");
return new Response("Sentry URL not configured", { status: 500 });
}

try {
// Get the raw body
const body = await request.text();
// console.log("Received envelope body:", body);
// console.log("Envelope body length:", body.length);
// console.log("Envelope newlines count:", (body.match(/\n/g) || []).length);
// Parse envelope format (newline-delimited JSON)
let projectId: string | undefined;
let publicKey: string | undefined;

// Split into lines
const lines = body.split("\n");
if (lines.length < 2) {
console.error("Invalid envelope format: missing parts");
return new Response("Invalid envelope format", { status: 400 });
}

const headerRaw = lines[0];
const items: string[] = [];

// Process lines after header to build items with proper newlines
let i = 1;
while (i < lines.length) {
const itemHeaderLine = lines[i];
if (!itemHeaderLine || itemHeaderLine.trim() === "") {
i++;
continue;
}

try {
// Try to parse item header
const itemHeader = JSON.parse(itemHeaderLine);
if (!itemHeader.type) {
i++;
continue;
}

// Found an item header, collect payload until next item header or end
const itemPayloadLines: string[] = [];
i++;
while (i < lines.length) {
const payloadLine = lines[i];
// Stop if we hit an empty line or another item header
if (payloadLine.trim() === "") {
i++;
continue;
}
try {
const parsed = JSON.parse(payloadLine);
if (parsed.type) {
break;
}
} catch (e) {
// Not a header, add to payload
}
itemPayloadLines.push(payloadLine);
i++;
}

// Add item with its payload, ensuring proper newlines
if (itemPayloadLines.length > 0) {
// For items with payload: header + \n + payload
items.push(itemHeaderLine + "\n" + itemPayloadLines.join("\n"));
} else {
// For header-only items: just the header
items.push(itemHeaderLine);
}

// Log item structure for debugging
// console.log("Added item:", {
// type: itemHeader.type,
// hasPayload: itemPayloadLines.length > 0,
// payloadLines: itemPayloadLines.length,
// });
} catch (e) {
// Not a valid item header, skip
i++;
}
}

// Log parsed items with detailed structure
// items.forEach((item, index) => {
// console.log(`Item ${index} structure:`, {
// content: item,
// length: item.length,
// newlines: (item.match(/\n/g) || []).length,
// endsWithNewline: item.endsWith("\n"),
// });
// });

// Reconstruct envelope with proper format:
// header + \n\n + item1 + \n\n + item2 + \n\n
const envelope = headerRaw + "\n\n" + items.join("\n");

// Log detailed envelope structure
// console.log("Envelope structure:", {
// headerLength: headerRaw.length,
// itemsCount: items.length,
// totalLength: envelope.length,
// newlines: (envelope.match(/\n/g) || []).length,
// firstNewlineAt: envelope.indexOf("\n"),
// headerAndFirstItem: envelope.split("\n").slice(0, 3),
// });

try {
// Parse header
const header = JSON.parse(headerRaw);

// Try to get DSN from envelope header
if (header.dsn) {
const dsnUrl = new URL(header.dsn);
projectId = dsnUrl.pathname.split("/")[1];
publicKey = dsnUrl.username;
// console.log("Parsed DSN from envelope:", { projectId, publicKey });
}
} catch (e) {
console.error("Failed to parse envelope header:", e);
return new Response("Invalid envelope header", { status: 400 });
}

// Fallback to environment DSN if needed
if (!projectId || !publicKey) {
const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN;
if (dsn) {
try {
const dsnUrl = new URL(dsn);
projectId = dsnUrl.pathname.split("/")[1];
publicKey = dsnUrl.username;
// console.log("Parsed DSN from environment:", { projectId, publicKey });
} catch (e) {
console.warn("Could not parse environment DSN:", e);
}
}
}

if (!projectId || !publicKey) {
console.warn("Could not extract project details from DSN");
return new Response("Could not parse Sentry DSN", { status: 500 });
}

// Get origin for CORS headers
const origin = request.headers.get("origin");

// Forward the request to Sentry's envelope endpoint
const sentryResponse = await fetch(
`${sentryUrl}/api/${projectId}/envelope/`,
{
method: "POST",
credentials: "omit", // Don't send cookies for client-side error reporting
headers: {
// Forward original headers needed for client error reporting
"Content-Type": "text/plain;charset=UTF-8",
Accept: "*/*",
// Forward original auth header from client request
"X-Sentry-Auth":
request.headers.get("X-Sentry-Auth") ||
`Sentry sentry_key=${publicKey},sentry_version=7,sentry_client=sentry.javascript.nextjs/8.0.0`,
},
// Use reconstructed envelope with proper newlines
body: envelope,
}
);

if (sentryResponse.status === 403) {
console.error("Sentry authentication failed:", {
responseStatus: sentryResponse.status,
responseStatusText: sentryResponse.statusText,
sentryError: sentryResponse.headers.get("X-Sentry-Error"),
url: `${sentryUrl}/api/${projectId}/envelope/`,
});

// Try to get response body for more error details
try {
const errorBody = await sentryResponse.clone().text();
console.error("Sentry error response body:", errorBody);
} catch (e) {
console.error("Could not read error response body");
}
}

// console.log("Sentry response:", {
// status: sentryResponse.status,
// statusText: sentryResponse.statusText,
// error: sentryResponse.headers.get("X-Sentry-Error"),
// });

// Get Sentry response headers we want to forward
const sentryHeaders = [
"X-Sentry-Error",
"X-Sentry-Rate-Limits",
"Retry-After",
];

// Get the request origin or default to *
const requestOrigin = request.headers.get("origin") || "*";

const responseHeaders: Record<string, string> = {
"Content-Type": "text/plain;charset=UTF-8",
"Access-Control-Allow-Origin": requestOrigin,
"Access-Control-Allow-Credentials": "true",
"Access-Control-Expose-Headers":
"X-Sentry-Error, X-Sentry-Rate-Limits, Retry-After",
// Add Vary header when using dynamic origin
...(requestOrigin !== "*" ? { Vary: "Origin" } : {}),
};

// Forward specific Sentry headers if they exist
for (const header of sentryHeaders) {
const value = sentryResponse.headers.get(header);
if (value) {
responseHeaders[header] = value;
// console.log(`Forwarding header ${header}:`, value);
}
}

// Return the response from Sentry with forwarded headers
return new Response(await sentryResponse.text(), {
status: sentryResponse.status,
headers: responseHeaders,
});
} catch (error) {
console.error("Error forwarding to Sentry:", error);
return new Response("Error forwarding to Sentry", { status: 500 });
}
}

// Handle OPTIONS requests for CORS
export async function OPTIONS(request: NextRequest) {
// Get the request origin or default to *
const requestOrigin = request.headers.get("origin") || "*";

const headers: Record<string, string> = {
"Access-Control-Allow-Origin": requestOrigin,
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "Accept, Content-Type, X-Sentry-Auth",
"Access-Control-Expose-Headers":
"X-Sentry-Error, X-Sentry-Rate-Limits, Retry-After",
"Access-Control-Max-Age": "86400",
};

// Add Vary header when using dynamic origin
if (requestOrigin !== "*") {
headers["Vary"] = "Origin";
}

return new Response(null, {
status: 200,
headers,
});
}
Loading

0 comments on commit d1be4b7

Please sign in to comment.