From e0652dfbb8f59cb3ee798a9116df549bf8ec83f5 Mon Sep 17 00:00:00 2001 From: Kieran Date: Mon, 22 May 2023 15:14:22 +0100 Subject: [PATCH] Add headers to request --- VoidCat/spa/src/api/package.json | 4 ++-- VoidCat/spa/src/api/src/Api.ts | 6 ++--- VoidCat/spa/src/api/src/StreamUploader.ts | 21 +++++++++------- VoidCat/spa/src/api/src/Upload.ts | 20 +++++++++------- VoidCat/spa/src/api/src/XHRUploader.ts | 29 ++++++++++++++--------- VoidCat/spa/src/api/webpack.config.js | 4 +++- 6 files changed, 50 insertions(+), 34 deletions(-) diff --git a/VoidCat/spa/src/api/package.json b/VoidCat/spa/src/api/package.json index db45ac8..5855000 100644 --- a/VoidCat/spa/src/api/package.json +++ b/VoidCat/spa/src/api/package.json @@ -1,8 +1,8 @@ { "name": "@void-cat/api", - "version": "1.0.1", + "version": "1.0.4", "description": "void.cat API package", - "main": "dist/index.js", + "main": "dist/lib.js", "types": "dist/index.d.ts", "repository": "https://git.v0l.io/Kieran/void.cat", "author": "Kieran", diff --git a/VoidCat/spa/src/api/src/Api.ts b/VoidCat/spa/src/api/src/Api.ts index 81371df..f12e10d 100644 --- a/VoidCat/spa/src/api/src/Api.ts +++ b/VoidCat/spa/src/api/src/Api.ts @@ -52,9 +52,9 @@ export class VoidApi { */ getUploader( file: File | Blob, - stateChange: StateChangeHandler, - progress: ProgressHandler, - proxyChallenge: ProxyChallengeHandler, + stateChange?: StateChangeHandler, + progress?: ProgressHandler, + proxyChallenge?: ProxyChallengeHandler, chunkSize?: number ): VoidUploader { if (StreamUploader.canUse()) { diff --git a/VoidCat/spa/src/api/src/StreamUploader.ts b/VoidCat/spa/src/api/src/StreamUploader.ts index de3957a..ef0517d 100644 --- a/VoidCat/spa/src/api/src/StreamUploader.ts +++ b/VoidCat/spa/src/api/src/StreamUploader.ts @@ -27,15 +27,15 @@ export class StreamUploader extends VoidUploader { return this.#encrypt?.getKey() } - async upload(): Promise { - this.onStateChange(UploadState.Hashing); + async upload(headers?: HeadersInit): Promise { + this.onStateChange?.(UploadState.Hashing); const hash = await this.digest(this.file); let offset = 0; const DefaultChunkSize = 1024 * 1024; const rsBase = new ReadableStream({ start: async () => { - this.onStateChange(UploadState.Uploading); + this.onStateChange?.(UploadState.Uploading); }, pull: async (controller) => { const chunk = await this.readChunk(offset, controller.desiredSize ?? DefaultChunkSize); @@ -43,7 +43,7 @@ export class StreamUploader extends VoidUploader { controller.close(); return; } - this.onProgress(offset + chunk.byteLength); + this.onProgress?.(offset + chunk.byteLength); offset += chunk.byteLength controller.enqueue(chunk); }, @@ -55,23 +55,26 @@ export class StreamUploader extends VoidUploader { highWaterMark: DefaultChunkSize }); - const headers = { + const reqHeaders = { "Content-Type": "application/octet-stream", "V-Content-Type": !this.file.type ? "application/octet-stream" : this.file.type, "V-Filename": "name" in this.file ? this.file.name : "", - "V-Full-Digest": hash + "V-Full-Digest": hash, } as Record; if (this.#encrypt) { - headers["V-EncryptionParams"] = JSON.stringify(this.#encrypt!.getParams()); + reqHeaders["V-EncryptionParams"] = JSON.stringify(this.#encrypt!.getParams()); } if (this.auth) { - headers["Authorization"] = `Bearer ${this.auth}`; + reqHeaders["Authorization"] = `Bearer ${this.auth}`; } const req = await fetch(`${this.uri}/upload`, { method: "POST", mode: "cors", body: this.#encrypt ? rsBase.pipeThrough(this.#encrypt!.getEncryptionTransform()) : rsBase, - headers, + headers: { + ...reqHeaders, + ...headers + }, // @ts-ignore New stream spec duplex: 'half' }); diff --git a/VoidCat/spa/src/api/src/Upload.ts b/VoidCat/spa/src/api/src/Upload.ts index 39a638c..173849c 100644 --- a/VoidCat/spa/src/api/src/Upload.ts +++ b/VoidCat/spa/src/api/src/Upload.ts @@ -27,16 +27,16 @@ export abstract class VoidUploader { protected file: File | Blob; protected auth?: string; protected maxChunkSize: number; - protected onStateChange: StateChangeHandler; - protected onProgress: ProgressHandler; - protected onProxyChallenge: ProxyChallengeHandler; + protected onStateChange?: StateChangeHandler; + protected onProgress?: ProgressHandler; + protected onProxyChallenge?: ProxyChallengeHandler; constructor( uri: string, file: File | Blob, - stateChange: StateChangeHandler, - progress: ProgressHandler, - proxyChallenge: ProxyChallengeHandler, + stateChange?: StateChangeHandler, + progress?: ProgressHandler, + proxyChallenge?: ProxyChallengeHandler, auth?: string, chunkSize?: number ) { @@ -65,12 +65,16 @@ export abstract class VoidUploader { const slice = file.slice(offset, offset + ChunkSize); const chunk = await slice.arrayBuffer(); sha.update(sjclcodec.toBits(new Uint8Array(chunk))); - this.onProgress(progress += chunk.byteLength); + this.onProgress?.(progress += chunk.byteLength); } return buf2hex(sjclcodec.fromBits(sha.finalize())); } - abstract upload(): Promise; + /** + * Upload a file to the API + * @param headers any additional headers to send with the request + */ + abstract upload(headers?: HeadersInit): Promise; /** * Can we use local encryption diff --git a/VoidCat/spa/src/api/src/XHRUploader.ts b/VoidCat/spa/src/api/src/XHRUploader.ts index 9e61089..1e9e8d3 100644 --- a/VoidCat/spa/src/api/src/XHRUploader.ts +++ b/VoidCat/spa/src/api/src/XHRUploader.ts @@ -14,23 +14,23 @@ export class XHRUploader extends VoidUploader { return undefined; } - async upload(): Promise { - this.onStateChange(UploadState.Hashing); + async upload(headers?: HeadersInit): Promise { + this.onStateChange?.(UploadState.Hashing); const hash = await this.digest(this.file); if (this.file.size > this.maxChunkSize) { - return await this.#doSplitXHRUpload(hash, this.maxChunkSize); + return await this.#doSplitXHRUpload(hash, this.maxChunkSize, headers); } else { - return await this.#xhrSegment(this.file, hash); + return await this.#xhrSegment(this.file, hash, undefined, undefined, 1, 1, headers); } } - async #doSplitXHRUpload(hash: string, splitSize: number) { + async #doSplitXHRUpload(hash: string, splitSize: number, headers?: HeadersInit) { let xhr: VoidUploadResult | null = null; const segments = Math.ceil(this.file.size / splitSize); for (let s = 0; s < segments; s++) { const offset = s * splitSize; const slice = this.file.slice(offset, offset + splitSize, this.file.type); - xhr = await this.#xhrSegment(slice, hash, xhr?.file?.id, xhr?.file?.metadata?.editSecret, s + 1, segments); + xhr = await this.#xhrSegment(slice, hash, xhr?.file?.id, xhr?.file?.metadata?.editSecret, s + 1, segments, headers); if (!xhr.ok) { break; } @@ -46,9 +46,11 @@ export class XHRUploader extends VoidUploader { * @param editSecret * @param part Segment number * @param partOf Total number of segments + * @param headers */ - async #xhrSegment(segment: ArrayBuffer | Blob, fullDigest: string, id?: string, editSecret?: string, part?: number, partOf?: number) { - this.onStateChange(UploadState.Uploading); + async #xhrSegment(segment: ArrayBuffer | Blob, fullDigest: string, + id?: string, editSecret?: string, part?: number, partOf?: number, headers?: HeadersInit) { + this.onStateChange?.(UploadState.Uploading); return await new Promise((resolve, reject) => { try { @@ -60,15 +62,15 @@ export class XHRUploader extends VoidUploader { } else if (req.readyState === XMLHttpRequest.DONE && req.status === 403) { const contentType = req.getResponseHeader("content-type"); if (contentType?.toLowerCase().trim().indexOf("text/html") === 0) { - this.onProxyChallenge(req.response); - this.onStateChange(UploadState.Challenge); + this.onProxyChallenge?.(req.response); + this.onStateChange?.(UploadState.Challenge); reject(new Error("CF Challenge")); } } }; req.upload.onprogress = (e) => { if (e instanceof ProgressEvent) { - this.onProgress(e.loaded); + this.onProgress?.(e.loaded); } }; req.open("POST", id ? `${this.uri}/upload/${id}` : `${this.uri}/upload`); @@ -84,6 +86,11 @@ export class XHRUploader extends VoidUploader { if (editSecret) { req.setRequestHeader("V-EditSecret", editSecret); } + if (headers) { + for (const [k, v] of Object.entries(headers)) { + req.setRequestHeader(k, v); + } + } req.send(segment); } catch (e) { reject(e); diff --git a/VoidCat/spa/src/api/webpack.config.js b/VoidCat/spa/src/api/webpack.config.js index 908b039..32b46f2 100644 --- a/VoidCat/spa/src/api/webpack.config.js +++ b/VoidCat/spa/src/api/webpack.config.js @@ -3,7 +3,9 @@ const path = require('path'); const isProduction = process.env.NODE_ENV == 'production'; const config = { - entry: './src/index.ts', + entry: { + lib: './src/index.ts', + }, devtool: isProduction ? "source-map" : "eval", output: { path: path.resolve(__dirname, 'dist'),