diff --git a/src/index.ts b/src/index.ts index e3e1219..445bd49 100644 --- a/src/index.ts +++ b/src/index.ts @@ -119,7 +119,7 @@ export default { let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; page += `${object.httpMetadata?.contentDisposition ?? object.key}
`; } - response = new Response(page, { status: 200, headers: { 'Content-Type': 'text/html' } }); + response = new Response(page, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } else { let object = await bucket.get(resource_path, { onlyIf: request.headers, @@ -319,30 +319,55 @@ export default { } break; case '1': { + let object = await bucket.head(resource_path); + if (object === null && resource_path.endsWith('/')) { + object = await bucket.head(resource_path.slice(0, -1)); + } + + if (object === null) { + response = new Response('Not Found', { status: 404 }); + break; + } + + if (object.customMetadata?.resourcetype !== '') { + let page = ` + + + /${resource_path} + + + ${Object.entries(fromR2Object(object)) + .filter(([_, value]) => value !== undefined) + .map(([key, value]) => `<${key}>${value}`) + .join('\n ') + } + + HTTP/1.1 200 OK + + + +`; + response = new Response(page, { + status: 207, + headers: { + 'Content-Type': 'text/xml', + }, + }); + break; + } + let page = ` `; let cursor: string | undefined = undefined; do { var r2_objects = await bucket.list({ - prefix: resource_path, + prefix: resource_path.endsWith('/') ? resource_path : resource_path + '/', delimiter: '/', cursor: cursor, include: ['httpMetadata', 'customMetadata'], }); - if (r2_objects.objects.length === 1) { - let object = r2_objects.objects[0]; - // When the resource is a collection - if (object.key === resource_path && object.customMetadata?.resourcetype === '') { - resource_path = resource_path.endsWith('/') ? resource_path : resource_path + '/'; - if (r2_objects.truncated) { - delete r2_objects.cursor - } - r2_objects.truncated = true; - } - } - for (let object of r2_objects.objects.filter(object => object.key !== resource_path)) { let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; page += ` @@ -374,8 +399,88 @@ export default { }); } break; + case 'infinity': { + let object = await bucket.head(resource_path); + if (object === null && resource_path.endsWith('/')) { + object = await bucket.head(resource_path.slice(0, -1)); + } + + if (object === null) { + response = new Response('Not Found', { status: 404 }); + break; + } + + if (object.customMetadata?.resourcetype !== '') { + let page = ` + + + /${resource_path} + + + ${Object.entries(fromR2Object(object)) + .filter(([_, value]) => value !== undefined) + .map(([key, value]) => `<${key}>${value}`) + .join('\n ') + } + + HTTP/1.1 200 OK + + + +`; + response = new Response(page, { + status: 207, + headers: { + 'Content-Type': 'text/xml', + }, + }); + break; + } + + let page = ` +`; + + let cursor: string | undefined = undefined; + do { + var r2_objects = await bucket.list({ + prefix: resource_path.endsWith('/') ? resource_path : resource_path + '/', + cursor: cursor, + include: ['httpMetadata', 'customMetadata'], + }); + + for (let object of r2_objects.objects.filter(object => object.key !== resource_path)) { + let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; + page += ` + + ${href} + + + ${Object.entries(fromR2Object(object)) + .filter(([_, value]) => value !== undefined) + .map(([key, value]) => `<${key}>${value}`) + .join('\n ') + } + + HTTP/1.1 200 OK + + `; + } + + if (r2_objects.truncated) { + cursor = r2_objects.cursor; + } + } while (r2_objects.truncated); + page += '\n\n'; + response = new Response(page, { + status: 207, + headers: { + 'Content-Type': 'text/xml', + }, + }); + } + break; default: { - response = new Response('Bad Request', { status: 400 }); + response = new Response('Forbidden', { status: 403 }); } } }