69 lines
2.4 KiB
TypeScript
69 lines
2.4 KiB
TypeScript
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=0, s-maxage=600, 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
|
|
}
|