diff --git a/components/DownloadBtnGtoup.tsx b/components/DownloadBtnGtoup.tsx index 24eed57..03078a9 100644 --- a/components/DownloadBtnGtoup.tsx +++ b/components/DownloadBtnGtoup.tsx @@ -82,13 +82,6 @@ const DownloadButtonGroup = () => { btnIcon="file-download" btnTitle={t('Download the file directly through OneDrive')} /> - {/* window.open(`/api/proxy?url=${encodeURIComponent(downloadUrl)}`)} - btnColor="teal" - btnText={t('Proxy download')} - btnIcon="download" - btnTitle={t('Download the file with the stream proxied through Vercel Serverless')} - /> */} { clipboard.copy(`${getBaseUrl()}/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`) diff --git a/components/FileListing.tsx b/components/FileListing.tsx index f63145f..2d6de8e 100644 --- a/components/FileListing.tsx +++ b/components/FileListing.tsx @@ -370,7 +370,7 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => { {readmeFile && (
- +
)} diff --git a/components/previews/MarkdownPreview.tsx b/components/previews/MarkdownPreview.tsx index 815b5fe..3e0030b 100644 --- a/components/previews/MarkdownPreview.tsx +++ b/components/previews/MarkdownPreview.tsx @@ -20,11 +20,16 @@ const MarkdownPreview: FC<{ file: any path: string standalone?: boolean -}> = ({ file, path, standalone = true }) => { + proxy?: boolean +}> = ({ file, path, standalone = true, proxy = false }) => { // The parent folder of the markdown file, which is also the relative image folder const parentPath = standalone ? path.substring(0, path.lastIndexOf('/')) : path - const { response: content, error, validating } = useFileContent(`/api/raw/?path=${parentPath}/${file.name}`, path) + const { + response: content, + error, + validating, + } = useFileContent(`/api/raw/?path=${parentPath}/${file.name}${proxy ? `&proxy=true` : ''}`, path) const { t } = useTranslation() // Check if the image is relative path instead of a absolute url diff --git a/components/previews/PDFPreview.tsx b/components/previews/PDFPreview.tsx index c0555b9..1849ee2 100644 --- a/components/previews/PDFPreview.tsx +++ b/components/previews/PDFPreview.tsx @@ -8,7 +8,6 @@ const PDFEmbedPreview: React.FC<{ file: any }> = ({ file }) => { const { asPath } = useRouter() const hashedToken = getStoredToken(asPath) - // const url = `/api/proxy?url=${encodeURIComponent(...)}&inline=true` const pdfPath = encodeURIComponent( `${getBaseUrl()}/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}` ) diff --git a/components/previews/VideoPreview.tsx b/components/previews/VideoPreview.tsx index 4d9953f..d69e457 100644 --- a/components/previews/VideoPreview.tsx +++ b/components/previews/VideoPreview.tsx @@ -132,14 +132,6 @@ const VideoPreview: FC<{ file: OdFileObject }> = ({ file }) => { btnText={t('Download')} btnIcon="file-download" /> - {/* - window.open(`/api/proxy?url=${encodeURIComponent(...)}`) - } - btnColor="teal" - btnText={t('Proxy download')} - btnIcon="download" - /> */} { clipboard.copy(`${getBaseUrl()}/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`) diff --git a/pages/api/proxy.ts b/pages/api/proxy.ts deleted file mode 100644 index 1db9f8a..0000000 --- a/pages/api/proxy.ts +++ /dev/null @@ -1,42 +0,0 @@ -import axios from 'axios' -import type { NextApiRequest, NextApiResponse } from 'next' - -import apiConfig from '../../config/api.config' - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - // 'inline' is used for previewing PDF files inside the browser directly - const { url, inline = false } = req.query - - if (!url || typeof url !== 'string') { - res.status(400).json({ error: 'Bad request, URL is not valid.' }) - return - } - - // Only handle urls that start with OneDrive's own direct link (or SharePoint's): - // https://public.*.files.1drv.com/y4m0G_0GPeS8AXGrux-lVV79eU1F38VbWxtCSi-8-aUkBLeZH1H6... - const hostname = new URL(url).hostname - if (hostname.match(new RegExp(apiConfig.directLinkRegex)) === null) { - res - .status(400) - .json({ error: `URL forbidden, only OneDrive direct links that match ${apiConfig.directLinkRegex} are allowed.` }) - return - } - - const { headers, data: stream } = await axios.get(url as string, { - responseType: 'stream', - }) - - // Check if requested file is PDF based on content-type - if (headers['content-type'] === 'application/pdf' && inline) { - // Get filename from content-disposition header - const filename = headers['content-disposition'].split(/filename[*]?=/)[1] - // Remove original content-disposition header - delete headers['content-disposition'] - // Add new inline content-disposition header along with filename - headers['content-disposition'] = `inline; filename*=UTF-8''${filename}` - } - - // Send data stream as response - res.writeHead(200, headers) - stream.pipe(res) -} diff --git a/pages/api/raw.ts b/pages/api/raw.ts index 604365c..86d7fbd 100644 --- a/pages/api/raw.ts +++ b/pages/api/raw.ts @@ -4,7 +4,7 @@ import type { NextApiRequest, NextApiResponse } from 'next' import axios from 'axios' import Cors from 'cors' -import { driveApi } from '../../config/api.config' +import { driveApi, cacheControlHeader } from '../../config/api.config' import { encodePath, getAccessToken, checkAuthRoute } from '.' // CORS middleware for raw links: https://nextjs.org/docs/api-routes/api-middlewares @@ -28,7 +28,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) return } - const { path = '/', odpt = '' } = req.query + const { path = '/', odpt = '', proxy = false } = req.query // Sometimes the path parameter is defaulted to '[...path]' which we need to handle if (path === '[...path]') { @@ -65,12 +65,23 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) headers: { Authorization: `Bearer ${accessToken}` }, params: { // OneDrive international version fails when only selecting the downloadUrl (what a stupid bug) - select: 'id,@microsoft.graph.downloadUrl', + select: 'id,size,@microsoft.graph.downloadUrl', }, }) if ('@microsoft.graph.downloadUrl' in data) { - res.redirect(data['@microsoft.graph.downloadUrl']) + // Only proxy raw file content response for files up to 4MB + if (proxy && 'size' in data && data['size'] < 4194304) { + const { headers, data: stream } = await axios.get(data['@microsoft.graph.downloadUrl'] as string, { + responseType: 'stream', + }) + headers['Cache-Control'] = cacheControlHeader + // Send data stream as response + res.writeHead(200, headers) + stream.pipe(res) + } else { + res.redirect(data['@microsoft.graph.downloadUrl']) + } } else { res.status(404).json({ error: 'No download url found.' }) }