bypass more cors for onedrive

This commit is contained in:
fyears 2022-03-10 23:52:56 +08:00
parent 1b59ac1e58
commit 8cffa38eba
1 changed files with 87 additions and 53 deletions

View File

@ -7,8 +7,9 @@ import type {
} from "@microsoft/microsoft-graph-types"; } from "@microsoft/microsoft-graph-types";
import cloneDeep from "lodash/cloneDeep"; import cloneDeep from "lodash/cloneDeep";
import * as origLog from "loglevel"; import * as origLog from "loglevel";
import { request, Vault } from "obsidian"; import { request, requestUrl, requireApiVersion, Vault } from "obsidian";
import { import {
API_VER_REQURL,
COMMAND_CALLBACK_ONEDRIVE, COMMAND_CALLBACK_ONEDRIVE,
OAUTH2_FORCE_EXPIRE_MILLISECONDS, OAUTH2_FORCE_EXPIRE_MILLISECONDS,
OnedriveConfig, OnedriveConfig,
@ -482,28 +483,45 @@ export class WrappedOnedriveClient {
deleteJson = async (pathFragOrig: string) => { deleteJson = async (pathFragOrig: string) => {
const theUrl = this.buildUrl(pathFragOrig); const theUrl = this.buildUrl(pathFragOrig);
log.debug(`deleteJson, theUrl=${theUrl}`); log.debug(`deleteJson, theUrl=${theUrl}`);
// TODO: delete does not have response, so Obsidian request may have error if (requireApiVersion(API_VER_REQURL)) {
// currently downgraded to fetch()! await requestUrl({
await fetch(theUrl, { url: theUrl,
method: "DELETE", method: "DELETE",
headers: { headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
}, },
}); });
} else {
await fetch(theUrl, {
method: "DELETE",
headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
},
});
}
}; };
putArrayBuffer = async (pathFragOrig: string, payload: ArrayBuffer) => { putArrayBuffer = async (pathFragOrig: string, payload: ArrayBuffer) => {
const theUrl = this.buildUrl(pathFragOrig); const theUrl = this.buildUrl(pathFragOrig);
log.debug(`putArrayBuffer, theUrl=${theUrl}`); log.debug(`putArrayBuffer, theUrl=${theUrl}`);
// TODO: Obsidian doesn't support ArrayBuffer if (requireApiVersion(API_VER_REQURL)) {
// currently downgraded to fetch()! await requestUrl({
await fetch(theUrl, { url: theUrl,
method: "PUT", method: "PUT",
body: payload, body: payload,
headers: { headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`, Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
}, },
}); });
} else {
await fetch(theUrl, {
method: "PUT",
body: payload,
headers: {
Authorization: `Bearer ${await this.authGetter.getAccessToken()}`,
},
});
}
}; };
/** /**
@ -527,7 +545,7 @@ export class WrappedOnedriveClient {
rangeEnd - 1 rangeEnd - 1
}, len=${rangeEnd - rangeStart}, size=${size}` }, len=${rangeEnd - rangeStart}, size=${size}`
); );
// TODO: Obsidian doesn't support ArrayBuffer // obsidian requestUrl doesn't support setting Content-Length
// currently downgraded to fetch()! // currently downgraded to fetch()!
// AND, NO AUTH HEADER here! // AND, NO AUTH HEADER here!
const res = await fetch(theUrl, { const res = await fetch(theUrl, {
@ -539,8 +557,7 @@ export class WrappedOnedriveClient {
"Content-Type": "application/octet-stream", "Content-Type": "application/octet-stream",
}, },
}); });
return (await res.json()) as DriveItem | UploadSession;
return res.json() as DriveItem | UploadSession;
}; };
} }
@ -704,40 +721,52 @@ export const uploadToRemote = async (
// no need to create parent folders firstly, cool! // no need to create parent folders firstly, cool!
// upload large files!
// ref: https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession?view=odsp-graph-online
// 1. create uploadSession
// uploadFile already starts with /drive/special/approot:/${vaultName}
const s: UploadSession = await client.postJson(
`${uploadFile}:/createUploadSession`,
{
item: {
"@microsoft.graph.conflictBehavior": "replace",
},
}
);
const uploadUrl = s.uploadUrl;
log.debug("uploadSession = ");
log.debug(s);
// 2. upload by ranges
// convert to uint8
const uint8 = new Uint8Array(remoteContent);
// hard code range size // hard code range size
const MIN_UNIT = 327680; // bytes in msft doc, about 0.32768 MB const MIN_UNIT = 327680; // bytes in msft doc, about 0.32768 MB
const RANGE_SIZE = MIN_UNIT * 20; // about 6.5536 MB const RANGE_SIZE = MIN_UNIT * 20; // about 6.5536 MB
// upload the ranges one by one
let rangeStart = 0; if (remoteContent.byteLength <= RANGE_SIZE) {
while (rangeStart < uint8.byteLength) { // directly using put!
await client.putUint8ArrayByRange( await client.putArrayBuffer(
uploadUrl, `${uploadFile}:/content?${new URLSearchParams({
uint8, "@microsoft.graph.conflictBehavior": "replace",
rangeStart, })}`,
Math.min(rangeStart + RANGE_SIZE, uint8.byteLength), remoteContent
uint8.byteLength
); );
rangeStart += RANGE_SIZE; } else {
// upload large files!
// ref: https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession?view=odsp-graph-online
// 1. create uploadSession
// uploadFile already starts with /drive/special/approot:/${vaultName}
const s: UploadSession = await client.postJson(
`${uploadFile}:/createUploadSession`,
{
item: {
"@microsoft.graph.conflictBehavior": "replace",
},
}
);
const uploadUrl = s.uploadUrl;
log.debug("uploadSession = ");
log.debug(s);
// 2. upload by ranges
// convert to uint8
const uint8 = new Uint8Array(remoteContent);
// upload the ranges one by one
let rangeStart = 0;
while (rangeStart < uint8.byteLength) {
await client.putUint8ArrayByRange(
uploadUrl,
uint8,
rangeStart,
Math.min(rangeStart + RANGE_SIZE, uint8.byteLength),
uint8.byteLength
);
rangeStart += RANGE_SIZE;
}
} }
const res = await getRemoteMeta(client, uploadFile); const res = await getRemoteMeta(client, uploadFile);
@ -755,8 +784,13 @@ const downloadFromRemoteRaw = async (
`${key}?$select=@microsoft.graph.downloadUrl` `${key}?$select=@microsoft.graph.downloadUrl`
); );
const downloadUrl: string = rsp["@microsoft.graph.downloadUrl"]; const downloadUrl: string = rsp["@microsoft.graph.downloadUrl"];
const content = await (await fetch(downloadUrl)).arrayBuffer(); if (requireApiVersion(API_VER_REQURL)) {
return content; const content = (await requestUrl({ url: downloadUrl })).arrayBuffer;
return content;
} else {
const content = await (await fetch(downloadUrl)).arrayBuffer();
return content;
}
}; };
export const downloadFromRemote = async ( export const downloadFromRemote = async (