mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-24 12:19:41 +00:00
Rename files
This commit is contained in:
118
ts/logging/uploadDebugLog.node.ts
Normal file
118
ts/logging/uploadDebugLog.node.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright 2018 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { Response } from 'got';
|
||||
import { z } from 'zod';
|
||||
import FormData from 'form-data';
|
||||
import got from 'got';
|
||||
import { gzip } from 'node:zlib';
|
||||
import pify from 'pify';
|
||||
import { getUserAgent } from '../util/getUserAgent.node.js';
|
||||
import { maybeParseUrl } from '../util/url.std.js';
|
||||
import * as durations from '../util/durations/index.std.js';
|
||||
import type { LoggerType } from '../types/Logging.std.js';
|
||||
import { parseUnknown } from '../util/schemas.std.js';
|
||||
|
||||
const BASE_URL = 'https://debuglogs.org';
|
||||
|
||||
const UPLOAD_TIMEOUT = { request: durations.MINUTE };
|
||||
|
||||
const tokenBodySchema = z
|
||||
.object({
|
||||
fields: z.record(z.unknown()),
|
||||
url: z.string(),
|
||||
})
|
||||
.nonstrict();
|
||||
|
||||
const parseTokenBody = (
|
||||
rawBody: unknown
|
||||
): { fields: Record<string, unknown>; url: string } => {
|
||||
const body = parseUnknown(tokenBodySchema, rawBody);
|
||||
|
||||
const parsedUrl = maybeParseUrl(body.url);
|
||||
if (!parsedUrl) {
|
||||
throw new Error("Token body's URL was not a valid URL");
|
||||
}
|
||||
if (parsedUrl.protocol !== 'https:') {
|
||||
throw new Error("Token body's URL was not HTTPS");
|
||||
}
|
||||
|
||||
return body;
|
||||
};
|
||||
|
||||
export type UploadOptionsType = Readonly<{
|
||||
content: string | Buffer | Uint8Array;
|
||||
appVersion: string;
|
||||
logger: LoggerType;
|
||||
extension?: string;
|
||||
contentType?: string;
|
||||
compress?: boolean;
|
||||
prefix?: string;
|
||||
}>;
|
||||
|
||||
export const upload = async ({
|
||||
content,
|
||||
appVersion,
|
||||
logger,
|
||||
extension = 'gz',
|
||||
contentType = 'application/gzip',
|
||||
compress = true,
|
||||
prefix,
|
||||
}: UploadOptionsType): Promise<string> => {
|
||||
const headers = { 'User-Agent': getUserAgent(appVersion) };
|
||||
|
||||
const formUrl = new URL(BASE_URL);
|
||||
|
||||
if (prefix !== undefined) {
|
||||
formUrl.searchParams.set('prefix', prefix);
|
||||
}
|
||||
|
||||
const signedForm = await got.get(formUrl.toString(), {
|
||||
responseType: 'json',
|
||||
headers,
|
||||
timeout: UPLOAD_TIMEOUT,
|
||||
});
|
||||
const { fields, url } = parseTokenBody(signedForm.body);
|
||||
|
||||
const uploadKey = `${fields.key}.${extension}`;
|
||||
|
||||
const form = new FormData();
|
||||
// The API expects `key` to be the first field:
|
||||
form.append('key', uploadKey);
|
||||
Object.entries(fields)
|
||||
.filter(([key]) => key !== 'key')
|
||||
.forEach(([key, value]) => {
|
||||
form.append(key, value);
|
||||
});
|
||||
|
||||
const contentBuffer = compress
|
||||
? await pify(gzip)(Buffer.from(content))
|
||||
: Buffer.from(content);
|
||||
form.append('Content-Type', contentType);
|
||||
form.append('file', contentBuffer, {
|
||||
contentType,
|
||||
filename: `signal-desktop-debug-log-${appVersion}.txt.gz`,
|
||||
});
|
||||
|
||||
logger.info('Debug log upload starting...');
|
||||
try {
|
||||
const { statusCode, body } = await got.post(url, {
|
||||
headers,
|
||||
body: form,
|
||||
timeout: UPLOAD_TIMEOUT,
|
||||
});
|
||||
if (statusCode !== 204) {
|
||||
throw new Error(
|
||||
`Failed to upload to S3, got status ${statusCode}, body '${body}'`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
const response = error.response as Response<string>;
|
||||
throw new Error(
|
||||
`Got threw on upload to S3: "${error.message}", got status ${response?.statusCode}, body '${response?.body}' `
|
||||
);
|
||||
}
|
||||
logger.info('Debug log upload complete.');
|
||||
|
||||
return `${BASE_URL}/${uploadKey}`;
|
||||
};
|
||||
Reference in New Issue
Block a user