Skip to content

Commit

Permalink
refactor: breaking changes, altered request format, both back and fro…
Browse files Browse the repository at this point in the history
…nt ends need to be upgraded
  • Loading branch information
vcheckzen committed Oct 11, 2024
1 parent 1530871 commit 8b44f7f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 97 deletions.
143 changes: 65 additions & 78 deletions back-end-cf/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ const PROTECTED_LAYERS = -1;
const EXPOSE_PASSWD = '';

addEventListener('scheduled', (event) => {
event.waitUntil(fetchAccessToken(/* event.scheduledTime */));
event.waitUntil(fetchAccessToken());
});

addEventListener('fetch', (event) => {
try {
return event.respondWith(handleRequest(event.request));
} catch (e) {
return event.respondWith(new Response('Error thrown ' + e.message));
}
event.respondWith(
handleRequest(event.request).catch((e) =>
Response.json({ error: e.message })
)
);
});

const OAUTH = {
Expand All @@ -42,64 +42,58 @@ const PATH_AUTH_STATES = Object.freeze({
});

async function handleRequest(request) {
let requestPath;
const requestUrl = new URL(request.url);
const file =
requestUrl.searchParams.get('file') ||
(requestUrl.pathname.split('/').filter(Boolean).length === 0
? ''
: decodeURIComponent(requestUrl.pathname));
// Download a file
if (file) {
const fileName = file.split('/').pop();
if (fileName.toLowerCase() === PASSWD_FILENAME.toLowerCase()) {
throw new Error('access denied');
}
const url = await fetchFiles(file.replace('/' + fileName, ''), fileName);
return Response.redirect(url, 302);
}

const returnHeaders = {
'Access-Control-Allow-Origin': '*',
'Cache-Control': 'max-age=3600',
'Content-Type': 'application/json; charset=utf-8',
};
const requestUrl = new URL(request.url);
const file = requestUrl.searchParams.get('file') || (requestUrl.pathname.split('/').filter(Boolean).length === 0 ? '' : decodeURIComponent(requestUrl.pathname));
if (file) {
const fileName = file.split('/').pop();
if (fileName.toLowerCase() === PASSWD_FILENAME.toLowerCase())
return Response.redirect(
'https://www.baidu.com/s?wd=%E6%80%8E%E6%A0%B7%E7%9B%97%E5%8F%96%E5%AF%86%E7%A0%81',
301
);
requestPath = file.replace('/' + fileName, '');
const url = await fetchFiles(requestPath, fileName);
return Response.redirect(url, 302);
} else if (requestUrl.searchParams.get('upload')) {
requestPath = requestUrl.searchParams.get('upload');
const upload = await fetchFiles(requestPath, '.upload');
const uploadSecret = await fetchFiles(requestPath, PASSWD_FILENAME, null, true) || '';
const fileList = await request.json();
const uploadAttack = fileList['files'].some(
(file) =>
file.remotePath.split('/').pop().toLowerCase() ===
PASSWD_FILENAME.toLowerCase()
) || fileList['secret'] !== uploadSecret;
if (upload && !uploadAttack) {
const uploadLinks = await uploadFiles(fileList);
return new Response(uploadLinks, {
headers: returnHeaders,
});
}
return new Response(JSON.stringify({ error: 'Access forbidden' }), {
status: 403,
headers: returnHeaders,
});
} else {
const { headers } = request;
const contentType = headers.get('content-type');
const body = {};
if (contentType && contentType.includes('form')) {
const formData = await request.formData();
for (const entry of formData.entries()) {
body[entry[0]] = entry[1];
}
const body = await request.json();
const requestPath = decodeURIComponent(body.path || '');

// Upload files
if (requestUrl.searchParams.has('upload')) {
const allowUpload = await fetchFiles(requestPath, '.upload');
const uploadSecret =
(await fetchFiles(requestPath, PASSWD_FILENAME, null, true)) || '';
const uploadAttack =
!allowUpload ||
body.files.some(
(file) =>
file.remotePath.split('/').pop().toLowerCase() ===
PASSWD_FILENAME.toLowerCase()
) ||
body.passwd !== uploadSecret;
if (uploadAttack) {
throw new Error('access denied');
}
requestPath = Object.getOwnPropertyNames(body).length ? body['?path'] : '';
const files = await fetchFiles(
decodeURIComponent(requestPath),
null,
body.passwd
);
return new Response(files, {

const uploadLinks = await uploadFiles(body.files);
return new Response(uploadLinks, {
headers: returnHeaders,
});
}

// List a folder
const files = await fetchFiles(requestPath, null, body.passwd);
return new Response(files, {
headers: returnHeaders,
});
}

async function gatherResponse(response) {
Expand All @@ -120,30 +114,20 @@ async function cacheFetch(url, options) {
});
}

async function getContent(url) {
const response = await cacheFetch(url);
const result = await gatherResponse(response);
return result;
}

async function getContentWithHeaders(url, headers) {
const response = await cacheFetch(url, {
headers: headers,
});
async function getContent(url, headers) {
const response = await cacheFetch(url, { headers });
const result = await gatherResponse(response);
return result;
}

async function fetchFormData(url, data) {
const formdata = new FormData();
async function postFormData(url, data) {
const formData = new FormData();
for (const key in data) {
if (data.hasOwnProperty(key)) {
formdata.append(key, data[key]);
}
formData.append(key, data[key]);
}
const requestOptions = {
method: 'POST',
body: formdata,
body: formData,
};
const response = await cacheFetch(url, requestOptions);
const result = await gatherResponse(response);
Expand Down Expand Up @@ -174,7 +158,7 @@ async function fetchAccessToken() {
requested_token_use: 'on_behalf_of',
refresh_token: refreshToken,
};
const result = await fetchFormData(url, data);
const result = await postFormData(url, data);

if (typeof FODI_CACHE !== 'undefined' && result?.refresh_token) {
result.save_time = Date.now();
Expand All @@ -194,12 +178,16 @@ async function fetchFiles(path, fileName, passwd, viewExposePathPassword) {
'/children?select=name,size,parentReference,lastModifiedDateTime,@microsoft.graph.downloadUrl&$top=200';
const uri = OAUTH.apiUrl + path + expand;

let pageRes = await getContentWithHeaders(uri, {
let pageRes = await getContent(uri, {
Authorization: 'Bearer ' + accessToken,
});
if (pageRes.error) {
throw new Error('request failed');
}

let children = pageRes.value;
while (pageRes['@odata.nextLink']) {
pageRes = await getContentWithHeaders(pageRes['@odata.nextLink'], {
pageRes = await getContent(pageRes['@odata.nextLink'], {
Authorization: 'Bearer ' + accessToken,
});
children = children.concat(pageRes.value);
Expand Down Expand Up @@ -245,14 +233,14 @@ async function fetchFiles(path, fileName, passwd, viewExposePathPassword) {
});
}

// Download file
// Download a file
if (fileName) {
return children.find(
(file) => file.name === decodeURIComponent(fileName)
)?.['@microsoft.graph.downloadUrl'];
}

// List folder
// List a folder
return JSON.stringify({
parent,
files: children
Expand All @@ -266,8 +254,7 @@ async function fetchFiles(path, fileName, passwd, viewExposePathPassword) {
});
}

async function uploadFiles(fileJsonList) {
const fileList = fileJsonList['files'];
async function uploadFiles(fileList) {
const batchRequest = {
requests: fileList.map((file, index) => ({
id: `${index + 1}`,
Expand Down
32 changes: 13 additions & 19 deletions front-end/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1716,8 +1716,14 @@
const currentPage = paginatedUpFileList[pageIndex];
sendRequest(
window.api.method,
window.api.url + '?upload=' + odPath,
JSON.stringify({ secret: window.fileCache.get(`${odPath}/.upload`) || '', files: currentPage }),
window.api.url + '?upload',
window.api.formatPayload(
odPath,
window.fileCache.get(`${odPath}/.upload`) || '',
{
files: currentPage,
}
),
window.api.headers,
(response) => {
const uploadLinks = JSON.parse(response).files;
Expand Down Expand Up @@ -1863,23 +1869,15 @@
root: '/',
url: window.GLOBAL_CONFIG.SCF_GATEWAY,
method: 'POST',
formatPayload: (path, passwd) => {
const payload = {
formatPayload: (path, passwd, kvs) =>
JSON.stringify({
path,
passwd,
...window.api.accessToken,
};
const form = new URLSearchParams();
for (const k in payload) {
const v = payload[k];
if (v) {
form.append(k, v);
}
}
return `?${form.toString()}`;
},
...kvs,
}),
headers: {
'Content-type': 'application/x-www-form-urlencoded',
'Content-type': 'application/json; charset=utf-8',
},
};
window.backFordwardCache = {
Expand All @@ -1896,10 +1894,6 @@
new URLSearchParams(window.location.search).get('path') ||
window.api.root;
if (window.GLOBAL_CONFIG.IS_CF) {
window.api.accessToken = {
encrypted: '',
plain: '',
};
fetchFileList(initialPath);
addBackForwardListener();
addFileUploadListener();
Expand Down

2 comments on commit 8b44f7f

@alan16742
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

前端的 content-type 如果改成 json 需要后端响应,否则会引起跨域问题

@vcheckzen
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码都改了,commit message 提醒了

Please sign in to comment.