98 lines
2.5 KiB
JavaScript
98 lines
2.5 KiB
JavaScript
// vim: set noexpandtab:
|
|
import mime from 'mime'
|
|
import GoogleDrive from './googleDrive'
|
|
|
|
self.props = {
|
|
root_id: typeof(ROOT_ID) !== 'undefined' ? ROOT_ID : 'root',
|
|
client_id: typeof(CLIENT_ID) !== 'undefined' ? CLIENT_ID : '202264815644.apps.googleusercontent.com',
|
|
client_secret: typeof(CLIENT_SECRET) !== 'undefined' ? CLIENT_SECRET : 'X4Z3ca8xfWDb1Voo-F9a7ZxJ',
|
|
refresh_token: typeof(REFRESH_TOKEN) !== 'undefined' ? REFRESH_TOKEN : '' // left here for debugging
|
|
}
|
|
|
|
const gd = new GoogleDrive(self.props)
|
|
|
|
async function onGet(request) {
|
|
let { pathname: path } = request
|
|
const rootId =
|
|
request.searchParams.get('rootId') || self.props.root_id
|
|
const result = await gd.getMetaByPath(path, rootId)
|
|
if (!result || result.mimeType.includes('vnd.google-apps')) {
|
|
return new Response('404 Not Found', {
|
|
headers: {
|
|
'Content-Type': 'text/plain'
|
|
},
|
|
status: 404
|
|
})
|
|
}
|
|
const r = await gd.download(result.id, request.headers.get('Range'))
|
|
const h = new Headers(r.headers)
|
|
h.set(
|
|
'Content-Disposition',
|
|
`inline; filename*=UTF-8''${encodeURIComponent(result.name)}`
|
|
)
|
|
return new Response(r.body, {
|
|
status: r.status,
|
|
headers: h
|
|
})
|
|
}
|
|
|
|
function encodePathComponent(path) {
|
|
return path
|
|
.split('/')
|
|
.map(encodeURIComponent)
|
|
.join('/')
|
|
}
|
|
|
|
async function handleRequest(request) {
|
|
if (request.method === 'OPTIONS')
|
|
// allow preflight request
|
|
return new Response('', {
|
|
status: 200,
|
|
headers: {
|
|
'Access-Control-Allow-Origin': '*',
|
|
'Access-Control-Allow-Headers': '*',
|
|
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS'
|
|
}
|
|
})
|
|
request = Object.assign({}, request, new URL(request.url))
|
|
request.pathname = request.pathname
|
|
.split('/')
|
|
.map(decodeURIComponent)
|
|
.map(decodeURIComponent) // for some super special cases, browser will force encode it... eg: +αあるふぁきゅん。 - +♂.mp3
|
|
.join('/')
|
|
|
|
if (request.pathname.endsWith('/')) request.pathname += 'index.html'
|
|
|
|
let resp
|
|
if (request.method === 'GET') resp = await onGet(request)
|
|
else
|
|
resp = new Response('', {
|
|
status: 405
|
|
})
|
|
const obj = Object.create(null)
|
|
for (const [k, v] of resp.headers.entries()) {
|
|
obj[k] = v
|
|
}
|
|
return new Response(resp.body, {
|
|
status: resp.status,
|
|
statusText: resp.statusText,
|
|
headers: Object.assign(obj, {
|
|
'Access-Control-Allow-Origin': '*'
|
|
})
|
|
})
|
|
}
|
|
|
|
addEventListener('fetch', event => {
|
|
event.respondWith(
|
|
handleRequest(event.request).catch(err => {
|
|
console.error(err)
|
|
new Response(JSON.stringify(err.stack), {
|
|
status: 500,
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
})
|
|
})
|
|
)
|
|
})
|