import type { OdThumbnail } from '../../types' import { posix as pathPosix } from 'path' import axios from 'axios' import type { NextApiRequest, NextApiResponse } from 'next' import { encodePath, getAccessToken, getAuthTokenPath } from '.' import apiConfig from '../../config/api.config' export default async function handler(req: NextApiRequest, res: NextApiResponse) { // Get access token from storage const accessToken = await getAccessToken() // Get item thumbnails by its path since we will later check if it is protected const { path = '', size = 'medium' } = req.query // Set edge function caching for faster load times, check docs: // https://vercel.com/docs/concepts/functions/edge-caching res.setHeader('Cache-Control', 'max-age=60, s-maxage=3600, stale-while-revalidate') // Check whether the size is valid - must be one of 'large', 'medium', or 'small' if (size !== 'large' && size !== 'medium' && size !== 'small') { res.status(400).json({ error: 'Invalid size' }) return } // Sometimes the path parameter is defaulted to '[...path]' which we need to handle if (path === '[...path]') { res.status(400).json({ error: 'No path specified.' }) return } // If the path is not a valid path, return 400 if (typeof path !== 'string') { res.status(400).json({ error: 'Path query invalid.' }) return } const cleanPath = pathPosix.resolve('/', pathPosix.normalize(path)) // Check if the path is protected const authTokenPath = getAuthTokenPath(cleanPath) // Currently protected paths are rejected to avoid file content leak if (authTokenPath) { res.status(404).json({ error: 'Protected pathes are not allowed.' }) return } const requestPath = encodePath(cleanPath) // Handle response from OneDrive API const requestUrl = `${apiConfig.driveApi}/root${requestPath}` // Whether path is root, which requires some special treatment const isRoot = requestPath === '' try { const { data } = await axios.get(`${requestUrl}${isRoot ? '' : ':'}/thumbnails`, { headers: { Authorization: `Bearer ${accessToken}` }, }) const thumbnailUrl = data.value && data.value.length > 0 ? (data.value[0] as OdThumbnail)[size].url : null if (thumbnailUrl) { res.redirect(thumbnailUrl) } else { res.status(400).json({ error: "The item doesn't have a valid thumbnail." }) } } catch (error: any) { res.status(error.response.status).json({ error: error.response.data }) } return }