75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
import type { OdThumbnail } from '../../types'
|
|
|
|
import { posix as pathPosix } from 'path'
|
|
|
|
import axios from 'axios'
|
|
import type { NextApiRequest, NextApiResponse } from 'next'
|
|
|
|
import { checkAuthRoute, encodePath, getAccessToken } from '.'
|
|
import apiConfig from '../../config/api.config'
|
|
|
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
const accessToken = await getAccessToken()
|
|
if (!accessToken) {
|
|
res.status(403).json({ error: 'No access token.' })
|
|
return
|
|
}
|
|
|
|
// Get item thumbnails by its path since we will later check if it is protected
|
|
const { path = '', size = 'medium', odpt = '' } = req.query
|
|
|
|
// Set edge function caching for faster load times, if route is not protected, check docs:
|
|
// https://vercel.com/docs/concepts/functions/edge-caching
|
|
if (odpt === '') res.setHeader('Cache-Control', apiConfig.cacheControlHeader)
|
|
|
|
// 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))
|
|
|
|
const { code, message } = await checkAuthRoute(cleanPath, accessToken, odpt as string)
|
|
// Status code other than 200 means user has not authenticated yet
|
|
if (code !== 200) {
|
|
res.status(code).json({ error: message })
|
|
return
|
|
}
|
|
// If message is empty, then the path is not protected.
|
|
// Conversely, protected routes are not allowed to serve from cache.
|
|
if (message !== '') {
|
|
res.setHeader('Cache-Control', 'no-cache')
|
|
}
|
|
|
|
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 ?? 'Internal server error.' })
|
|
}
|
|
return
|
|
}
|