Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/utils/envelope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export function parseEnvelope(env: string | Uint8Array): Envelope {
const itemHeader = readJson<BaseEnvelopeItemHeaders>();
const binaryLength = typeof itemHeader.length === 'number' ? itemHeader.length : undefined;

items.push([itemHeader, binaryLength ? readBinary(binaryLength) : readJson()]);
items.push([itemHeader, binaryLength !== undefined ? readBinary(binaryLength) : readJson()]);
}

return [envelopeHeader, items];
Expand Down
17 changes: 17 additions & 0 deletions packages/core/test/lib/utils/envelope.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { EventEnvelope } from '../../../src/types/envelope';
import type { Event } from '../../../src/types/event';
import {
addItemToEnvelope,
createAttachmentEnvelopeItem,
createEnvelope,
forEachEnvelopeItem,
parseEnvelope,
Expand Down Expand Up @@ -90,6 +91,22 @@ describe('envelope', () => {
after?.();
});

it('parses an envelope with an empty attachment', () => {
const env = createEnvelope<EventEnvelope>({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, [
[{ type: 'event' }, { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }],
createAttachmentEnvelopeItem({ filename: 'empty.txt', data: '' }),
createAttachmentEnvelopeItem({ filename: 'foo.txt', data: 'foo' }),
]);

const [, parsedItems] = parseEnvelope(serializeEnvelope(env));

expect(parsedItems).toEqual([
[{ type: 'event' }, { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }],
[{ type: 'attachment', filename: 'empty.txt', length: 0 }, new Uint8Array(0)],
[{ type: 'attachment', filename: 'foo.txt', length: 3 }, new TextEncoder().encode('foo')],
]);
});

it("doesn't throw when being passed a an envelope that contains a circular item payload", () => {
const chicken: { egg?: any } = {};
const egg = { chicken } as unknown as Event;
Expand Down
20 changes: 19 additions & 1 deletion packages/core/test/lib/utils/tunnel.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { getEnvelopeEndpointWithUrlEncodedAuth } from '../../../src/api';
import { makeDsn } from '../../../src/utils/dsn';
import { createEnvelope, serializeEnvelope } from '../../../src/utils/envelope';
import { createAttachmentEnvelopeItem, createEnvelope, serializeEnvelope } from '../../../src/utils/envelope';
import { handleTunnelRequest } from '../../../src/utils/tunnel';

const TEST_DSN = 'https://public@dsn.ingest.sentry.io/1337';
Expand Down Expand Up @@ -43,6 +43,24 @@ describe('handleTunnelRequest', () => {
expect(result).toBe(upstreamResponse);
});

it('forwards an envelope that contains an empty attachment', async () => {
const upstreamResponse = new Response('ok', { status: 200 });
fetchMock.mockResolvedValueOnce(upstreamResponse);

const envelope = createEnvelope({ dsn: TEST_DSN }, [
[{ type: 'event' }, { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }],
createAttachmentEnvelopeItem({ filename: 'empty.txt', data: '' }),
]);

const result = await handleTunnelRequest({
request: new Request('http://localhost/tunnel', { method: 'POST', body: serializeEnvelope(envelope) }),
allowedDsns: [TEST_DSN],
});

expect(fetchMock).toHaveBeenCalledOnce();
expect(result).toBe(upstreamResponse);
});

it('returns 500 when allowedDsns is empty', async () => {
const result = await handleTunnelRequest({
request: makeEnvelopeRequest({ dsn: TEST_DSN }),
Expand Down