Skip to content

Instantly share code, notes, and snippets.

@ChenYFan
Created February 18, 2024 03:17
Show Gist options
  • Save ChenYFan/ea02e65a0700e3e078ad49f032d6da83 to your computer and use it in GitHub Desktop.
Save ChenYFan/ea02e65a0700e3e078ad49f032d6da83 to your computer and use it in GitHub Desktop.
这是之前写的R2Worker,移到gist来了
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const url = new URL(request.url)
const objectName = url.pathname.slice(1)
console.log(`${request.method} object ${objectName}: ${request.url}`)
if (request.method === 'GET' || request.method === 'HEAD') {
if (objectName === '') {
if (request.method == 'HEAD') {
return new Response(undefined, { status: 400 })
}
const options = {
prefix: url.searchParams.get('prefix') ?? undefined,
delimiter: url.searchParams.get('delimiter') ?? undefined,
cursor: url.searchParams.get('cursor') ?? undefined,
include: ['customMetadata', 'httpMetadata'],
}
console.log(JSON.stringify(options))
const listing = await R2.list(options)
return new Response(JSON.stringify(listing), {
headers: {
'content-type': 'application/json; charset=UTF-8',
}
})
}
if (request.method === 'GET') {
const range = parseRange(request.headers.get('range'))
const object = await R2.get(objectName, {
range,
onlyIf: request.headers,
})
if (object === null) {
return objectNotFound(objectName)
}
const headers = new Headers()
//object.writeHttpMetadata(headers)
headers.set('etag', object.httpEtag)
const status = object.body ? (range ? 206 : 200) : 304
return new Response(object.body, {
headers,
status
})
}
const object = await R2.head(objectName, {
onlyIf: request.headers,
})
if (object === null) {
return objectNotFound(objectName)
}
const headers = new Headers()
//object.writeHttpMetadata(headers)
headers.set('etag', object.httpEtag)
return new Response(null, {
headers,
})
}
if (request.method === 'PUT' || request.method == 'POST') {
const object = await R2.put(objectName, request.body, {
httpMetadata: request.headers,
})
return new Response(null, {
headers: {
'etag': object.httpEtag,
}
})
}
if (request.method === 'DELETE') {
await R2.delete(url.pathname.slice(1))
return new Response()
}
return new Response(`Unsupported method`, {
status: 400
})
}
function parseRange(encoded) {
if (encoded === null) {
return
}
const parts = encoded.split("bytes=")[1]?.split("-") ?? []
if (parts.length !== 2) {
throw new Error('Not supported to skip specifying the beginning/ending byte at this time')
}
return {
offset: Number(parts[0]),
length: Number(parts[1]) + 1 - Number(parts[0]),
}
}
function objectNotFound(objectName) {
return new Response(`<html><body>R2 object "<b>${objectName}</b>" not found</body></html>`, {
status: 404,
headers: {
'content-type': 'text/html; charset=UTF-8'
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment