pettier . --write
This commit is contained in:
parent
bdef65eafd
commit
988fc29dda
@ -18,8 +18,8 @@ USERNAME = "USERNAME"
|
|||||||
PASSWORD = "PASSWORD"
|
PASSWORD = "PASSWORD"
|
||||||
```
|
```
|
||||||
|
|
||||||
* USERNAME: The username of WebDav.
|
- USERNAME: The username of WebDav.
|
||||||
* PASSWORD: The password of WebDav.
|
- PASSWORD: The password of WebDav.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
16
package-lock.json
generated
16
package-lock.json
generated
@ -9,6 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "^4.20231121.0",
|
"@cloudflare/workers-types": "^4.20231121.0",
|
||||||
|
"prettier": "3.1.1",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"wrangler": "^3.0.0"
|
"wrangler": "^3.0.0"
|
||||||
}
|
}
|
||||||
@ -970,6 +971,21 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prettier": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"prettier": "bin/prettier.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/printable-characters": {
|
"node_modules/printable-characters": {
|
||||||
"version": "1.0.42",
|
"version": "1.0.42",
|
||||||
"resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz",
|
"resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz",
|
||||||
|
@ -5,10 +5,13 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"deploy": "wrangler deploy",
|
"deploy": "wrangler deploy",
|
||||||
"dev": "wrangler dev",
|
"dev": "wrangler dev",
|
||||||
"start": "wrangler dev"
|
"start": "wrangler dev",
|
||||||
|
"lint-perttier": "prettier . --write",
|
||||||
|
"check-perttier": "prettier . --check"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "^4.20231121.0",
|
"@cloudflare/workers-types": "^4.20231121.0",
|
||||||
|
"prettier": "3.1.1",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"wrangler": "^3.0.0"
|
"wrangler": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
215
src/index.ts
215
src/index.ts
@ -46,21 +46,11 @@ async function* listAll(bucket: R2Bucket, prefix: string, isRecursive: boolean =
|
|||||||
if (r2_objects.truncated) {
|
if (r2_objects.truncated) {
|
||||||
cursor = r2_objects.cursor;
|
cursor = r2_objects.cursor;
|
||||||
}
|
}
|
||||||
} while (r2_objects.truncated)
|
} while (r2_objects.truncated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DAV_CLASS = '1';
|
||||||
const DAV_CLASS = "1";
|
const SUPPORT_METHODS = ['OPTIONS', 'PROPFIND', 'MKCOL', 'GET', 'HEAD', 'PUT', 'COPY', 'MOVE'];
|
||||||
const SUPPORT_METHODS = [
|
|
||||||
"OPTIONS",
|
|
||||||
"PROPFIND",
|
|
||||||
"MKCOL",
|
|
||||||
"GET",
|
|
||||||
"HEAD",
|
|
||||||
"PUT",
|
|
||||||
"COPY",
|
|
||||||
"MOVE",
|
|
||||||
];
|
|
||||||
|
|
||||||
type DavProperties = {
|
type DavProperties = {
|
||||||
creationdate: string | undefined;
|
creationdate: string | undefined;
|
||||||
@ -71,7 +61,7 @@ type DavProperties = {
|
|||||||
getetag: string | undefined;
|
getetag: string | undefined;
|
||||||
getlastmodified: string | undefined;
|
getlastmodified: string | undefined;
|
||||||
resourcetype: string;
|
resourcetype: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
function fromR2Object(object: R2Object | null | undefined): DavProperties {
|
function fromR2Object(object: R2Object | null | undefined): DavProperties {
|
||||||
if (object === null || object === undefined) {
|
if (object === null || object === undefined) {
|
||||||
@ -79,11 +69,11 @@ function fromR2Object(object: R2Object | null | undefined): DavProperties {
|
|||||||
creationdate: new Date().toUTCString(),
|
creationdate: new Date().toUTCString(),
|
||||||
displayname: undefined,
|
displayname: undefined,
|
||||||
getcontentlanguage: undefined,
|
getcontentlanguage: undefined,
|
||||||
getcontentlength: "0",
|
getcontentlength: '0',
|
||||||
getcontenttype: undefined,
|
getcontenttype: undefined,
|
||||||
getetag: undefined,
|
getetag: undefined,
|
||||||
getlastmodified: new Date().toUTCString(),
|
getlastmodified: new Date().toUTCString(),
|
||||||
resourcetype: "<collection />",
|
resourcetype: '<collection />',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +89,6 @@ function fromR2Object(object: R2Object | null | undefined): DavProperties {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function make_resource_path(request: Request): string {
|
function make_resource_path(request: Request): string {
|
||||||
let path = new URL(request.url).pathname.slice(1);
|
let path = new URL(request.url).pathname.slice(1);
|
||||||
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
||||||
@ -110,9 +99,9 @@ async function handle_options(request: Request, bucket: R2Bucket): Promise<Respo
|
|||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 204,
|
status: 204,
|
||||||
headers: {
|
headers: {
|
||||||
'DAV': DAV_CLASS,
|
DAV: DAV_CLASS,
|
||||||
'Allow': SUPPORT_METHODS.join(', '),
|
Allow: SUPPORT_METHODS.join(', '),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +122,7 @@ async function handle_get(request: Request, bucket: R2Bucket): Promise<Response>
|
|||||||
if (resource_path !== '') page += `<a href="../">..</a><br>`;
|
if (resource_path !== '') page += `<a href="../">..</a><br>`;
|
||||||
for await (const object of listAll(bucket, resource_path)) {
|
for await (const object of listAll(bucket, resource_path)) {
|
||||||
if (object.key === resource_path) {
|
if (object.key === resource_path) {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
||||||
page += `<a href="${href}">${object.httpMetadata?.contentDisposition ?? object.key}</a><br>`;
|
page += `<a href="${href}">${object.httpMetadata?.contentDisposition ?? object.key}</a><br>`;
|
||||||
@ -147,12 +136,12 @@ async function handle_get(request: Request, bucket: R2Bucket): Promise<Response>
|
|||||||
|
|
||||||
let isR2ObjectBody = (object: R2Object | R2ObjectBody): object is R2ObjectBody => {
|
let isR2ObjectBody = (object: R2Object | R2ObjectBody): object is R2ObjectBody => {
|
||||||
return 'body' in object;
|
return 'body' in object;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (object === null) {
|
if (object === null) {
|
||||||
return new Response('Not Found', { status: 404 });
|
return new Response('Not Found', { status: 404 });
|
||||||
} else if (!isR2ObjectBody(object)) {
|
} else if (!isR2ObjectBody(object)) {
|
||||||
return new Response("Precondition Failed", { status: 412 });
|
return new Response('Precondition Failed', { status: 412 });
|
||||||
} else {
|
} else {
|
||||||
return new Response(object.body, {
|
return new Response(object.body, {
|
||||||
status: object.range ? 206 : 200,
|
status: object.range ? 206 : 200,
|
||||||
@ -160,22 +149,32 @@ async function handle_get(request: Request, bucket: R2Bucket): Promise<Response>
|
|||||||
'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream',
|
'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream',
|
||||||
// TODO: Content-Length, Content-Range
|
// TODO: Content-Length, Content-Range
|
||||||
|
|
||||||
...(object.httpMetadata?.contentDisposition ? {
|
...(object.httpMetadata?.contentDisposition
|
||||||
'Content-Disposition': object.httpMetadata.contentDisposition,
|
? {
|
||||||
} : {}),
|
'Content-Disposition': object.httpMetadata.contentDisposition,
|
||||||
...(object.httpMetadata?.contentEncoding ? {
|
}
|
||||||
'Content-Encoding': object.httpMetadata.contentEncoding,
|
: {}),
|
||||||
} : {}),
|
...(object.httpMetadata?.contentEncoding
|
||||||
...(object.httpMetadata?.contentLanguage ? {
|
? {
|
||||||
'Content-Language': object.httpMetadata.contentLanguage,
|
'Content-Encoding': object.httpMetadata.contentEncoding,
|
||||||
} : {}),
|
}
|
||||||
...(object.httpMetadata?.cacheControl ? {
|
: {}),
|
||||||
'Cache-Control': object.httpMetadata.cacheControl,
|
...(object.httpMetadata?.contentLanguage
|
||||||
} : {}),
|
? {
|
||||||
...(object.httpMetadata?.cacheExpiry ? {
|
'Content-Language': object.httpMetadata.contentLanguage,
|
||||||
'Cache-Expiry': object.httpMetadata.cacheExpiry.toISOString(),
|
}
|
||||||
} : {}),
|
: {}),
|
||||||
}
|
...(object.httpMetadata?.cacheControl
|
||||||
|
? {
|
||||||
|
'Cache-Control': object.httpMetadata.cacheControl,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...(object.httpMetadata?.cacheExpiry
|
||||||
|
? {
|
||||||
|
'Cache-Expiry': object.httpMetadata.cacheExpiry.toISOString(),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,10 +208,11 @@ async function handle_delete(request: Request, bucket: R2Bucket): Promise<Respon
|
|||||||
let resource_path = make_resource_path(request);
|
let resource_path = make_resource_path(request);
|
||||||
|
|
||||||
if (resource_path === '') {
|
if (resource_path === '') {
|
||||||
let r2_objects, cursor: string | undefined = undefined;
|
let r2_objects,
|
||||||
|
cursor: string | undefined = undefined;
|
||||||
do {
|
do {
|
||||||
r2_objects = await bucket.list({ cursor: cursor });
|
r2_objects = await bucket.list({ cursor: cursor });
|
||||||
let keys = r2_objects.objects.map(object => object.key);
|
let keys = r2_objects.objects.map((object) => object.key);
|
||||||
if (keys.length > 0) {
|
if (keys.length > 0) {
|
||||||
await bucket.delete(keys);
|
await bucket.delete(keys);
|
||||||
}
|
}
|
||||||
@ -234,13 +234,14 @@ async function handle_delete(request: Request, bucket: R2Bucket): Promise<Respon
|
|||||||
return new Response(null, { status: 204 });
|
return new Response(null, { status: 204 });
|
||||||
}
|
}
|
||||||
|
|
||||||
let r2_objects, cursor: string | undefined = undefined;
|
let r2_objects,
|
||||||
|
cursor: string | undefined = undefined;
|
||||||
do {
|
do {
|
||||||
r2_objects = await bucket.list({
|
r2_objects = await bucket.list({
|
||||||
prefix: resource_path + "/",
|
prefix: resource_path + '/',
|
||||||
cursor: cursor,
|
cursor: cursor,
|
||||||
});
|
});
|
||||||
let keys = r2_objects.objects.map(object => object.key);
|
let keys = r2_objects.objects.map((object) => object.key);
|
||||||
if (keys.length > 0) {
|
if (keys.length > 0) {
|
||||||
await bucket.delete(keys);
|
await bucket.delete(keys);
|
||||||
}
|
}
|
||||||
@ -267,15 +268,15 @@ async function handle_mkcol(request: Request, bucket: R2Bucket): Promise<Respons
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the parent directory exists
|
// Check if the parent directory exists
|
||||||
let parent_dir = resource_path.split('/').slice(0, -1).join("/");
|
let parent_dir = resource_path.split('/').slice(0, -1).join('/');
|
||||||
|
|
||||||
if (parent_dir !== '' && !await bucket.head(parent_dir)) {
|
if (parent_dir !== '' && !(await bucket.head(parent_dir))) {
|
||||||
return new Response('Conflict', { status: 409 });
|
return new Response('Conflict', { status: 409 });
|
||||||
}
|
}
|
||||||
|
|
||||||
await bucket.put(resource_path, new Uint8Array(), {
|
await bucket.put(resource_path, new Uint8Array(), {
|
||||||
httpMetadata: request.headers,
|
httpMetadata: request.headers,
|
||||||
customMetadata: { resourcetype: '<collection />' }
|
customMetadata: { resourcetype: '<collection />' },
|
||||||
});
|
});
|
||||||
return new Response('', { status: 201 });
|
return new Response('', { status: 201 });
|
||||||
}
|
}
|
||||||
@ -287,7 +288,7 @@ async function handle_propfind(request: Request, bucket: R2Bucket): Promise<Resp
|
|||||||
let page = `<?xml version="1.0" encoding="utf-8"?>
|
let page = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
<multistatus xmlns="DAV:">`;
|
<multistatus xmlns="DAV:">`;
|
||||||
|
|
||||||
if (resource_path === "") {
|
if (resource_path === '') {
|
||||||
page += `
|
page += `
|
||||||
<response>
|
<response>
|
||||||
<href>/</href>
|
<href>/</href>
|
||||||
@ -321,53 +322,55 @@ async function handle_propfind(request: Request, bucket: R2Bucket): Promise<Resp
|
|||||||
</prop>
|
</prop>
|
||||||
<status>HTTP/1.1 200 OK</status>
|
<status>HTTP/1.1 200 OK</status>
|
||||||
</propstat>
|
</propstat>
|
||||||
</response>`
|
</response>`;
|
||||||
};
|
}
|
||||||
|
|
||||||
if (is_collection) {
|
if (is_collection) {
|
||||||
let depth = request.headers.get('Depth') ?? 'infinity';
|
let depth = request.headers.get('Depth') ?? 'infinity';
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case '0': break;
|
case '0':
|
||||||
case '1': {
|
|
||||||
let prefix = resource_path === "" ? resource_path : resource_path + '/';
|
|
||||||
for await (let object of listAll(bucket, prefix)) {
|
|
||||||
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
|
||||||
page += `
|
|
||||||
<response>
|
|
||||||
<href>${href}</href>
|
|
||||||
<propstat>
|
|
||||||
<prop>
|
|
||||||
${Object.entries(fromR2Object(object))
|
|
||||||
.filter(([_, value]) => value !== undefined)
|
|
||||||
.map(([key, value]) => `<${key}>${value}</${key}>`)
|
|
||||||
.join('\n ')}
|
|
||||||
</prop>
|
|
||||||
<status>HTTP/1.1 200 OK</status>
|
|
||||||
</propstat>
|
|
||||||
</response>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'infinity': {
|
case '1':
|
||||||
let prefix = resource_path === "" ? resource_path : resource_path + '/';
|
{
|
||||||
for await (let object of listAll(bucket, prefix, true)) {
|
let prefix = resource_path === '' ? resource_path : resource_path + '/';
|
||||||
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
for await (let object of listAll(bucket, prefix)) {
|
||||||
page += `
|
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
||||||
|
page += `
|
||||||
<response>
|
<response>
|
||||||
<href>${href}</href>
|
<href>${href}</href>
|
||||||
<propstat>
|
<propstat>
|
||||||
<prop>
|
<prop>
|
||||||
${Object.entries(fromR2Object(object))
|
${Object.entries(fromR2Object(object))
|
||||||
.filter(([_, value]) => value !== undefined)
|
.filter(([_, value]) => value !== undefined)
|
||||||
.map(([key, value]) => `<${key}>${value}</${key}>`)
|
.map(([key, value]) => `<${key}>${value}</${key}>`)
|
||||||
.join('\n ')
|
.join('\n ')}
|
||||||
}
|
|
||||||
</prop>
|
</prop>
|
||||||
<status>HTTP/1.1 200 OK</status>
|
<status>HTTP/1.1 200 OK</status>
|
||||||
</propstat>
|
</propstat>
|
||||||
</response>`;
|
</response>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'infinity':
|
||||||
|
{
|
||||||
|
let prefix = resource_path === '' ? resource_path : resource_path + '/';
|
||||||
|
for await (let object of listAll(bucket, prefix, true)) {
|
||||||
|
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
||||||
|
page += `
|
||||||
|
<response>
|
||||||
|
<href>${href}</href>
|
||||||
|
<propstat>
|
||||||
|
<prop>
|
||||||
|
${Object.entries(fromR2Object(object))
|
||||||
|
.filter(([_, value]) => value !== undefined)
|
||||||
|
.map(([key, value]) => `<${key}>${value}</${key}>`)
|
||||||
|
.join('\n ')}
|
||||||
|
</prop>
|
||||||
|
<status>HTTP/1.1 200 OK</status>
|
||||||
|
</propstat>
|
||||||
|
</response>`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
return new Response('Forbidden', { status: 403 });
|
return new Response('Forbidden', { status: 403 });
|
||||||
@ -395,8 +398,11 @@ async function handle_copy(request: Request, bucket: R2Bucket): Promise<Response
|
|||||||
destination = destination.endsWith('/') ? destination.slice(0, -1) : destination;
|
destination = destination.endsWith('/') ? destination.slice(0, -1) : destination;
|
||||||
|
|
||||||
// Check if the parent directory exists
|
// Check if the parent directory exists
|
||||||
let destination_parent = destination.split('/').slice(0, destination.endsWith('/') ? -2 : -1).join('/');
|
let destination_parent = destination
|
||||||
if (destination_parent !== '' && !await bucket.head(destination_parent)) {
|
.split('/')
|
||||||
|
.slice(0, destination.endsWith('/') ? -2 : -1)
|
||||||
|
.join('/');
|
||||||
|
if (destination_parent !== '' && !(await bucket.head(destination_parent))) {
|
||||||
return new Response('Conflict', { status: 409 });
|
return new Response('Conflict', { status: 409 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,10 +423,10 @@ async function handle_copy(request: Request, bucket: R2Bucket): Promise<Response
|
|||||||
let depth = request.headers.get('Depth') ?? 'infinity';
|
let depth = request.headers.get('Depth') ?? 'infinity';
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 'infinity': {
|
case 'infinity': {
|
||||||
let prefix = resource_path + "/";
|
let prefix = resource_path + '/';
|
||||||
const copy = async (object: R2Object) => {
|
const copy = async (object: R2Object) => {
|
||||||
let target = destination + "/" + object.key.slice(prefix.length);
|
let target = destination + '/' + object.key.slice(prefix.length);
|
||||||
target = target.endsWith("/") ? target.slice(0, -1) : target;
|
target = target.endsWith('/') ? target.slice(0, -1) : target;
|
||||||
let src = await bucket.get(object.key);
|
let src = await bucket.get(object.key);
|
||||||
if (src !== null) {
|
if (src !== null) {
|
||||||
await bucket.put(target, src.body, {
|
await bucket.put(target, src.body, {
|
||||||
@ -487,8 +493,11 @@ async function handle_move(request: Request, bucket: R2Bucket): Promise<Response
|
|||||||
destination = destination.endsWith('/') ? destination.slice(0, -1) : destination;
|
destination = destination.endsWith('/') ? destination.slice(0, -1) : destination;
|
||||||
|
|
||||||
// Check if the parent directory exists
|
// Check if the parent directory exists
|
||||||
let destination_parent = destination.split('/').slice(0, destination.endsWith('/') ? -2 : -1).join('/');
|
let destination_parent = destination
|
||||||
if (destination_parent !== '' && !await bucket.head(destination_parent)) {
|
.split('/')
|
||||||
|
.slice(0, destination.endsWith('/') ? -2 : -1)
|
||||||
|
.join('/');
|
||||||
|
if (destination_parent !== '' && !(await bucket.head(destination_parent))) {
|
||||||
return new Response('Conflict', { status: 409 });
|
return new Response('Conflict', { status: 409 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +515,8 @@ async function handle_move(request: Request, bucket: R2Bucket): Promise<Response
|
|||||||
return new Response('Bad Request', { status: 400 });
|
return new Response('Bad Request', { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destination_exists) { // Delete the destination first
|
if (destination_exists) {
|
||||||
|
// Delete the destination first
|
||||||
await handle_delete(new Request(new URL(destination_header), request), bucket);
|
await handle_delete(new Request(new URL(destination_header), request), bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,10 +526,10 @@ async function handle_move(request: Request, bucket: R2Bucket): Promise<Response
|
|||||||
let depth = request.headers.get('Depth') ?? 'infinity';
|
let depth = request.headers.get('Depth') ?? 'infinity';
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 'infinity': {
|
case 'infinity': {
|
||||||
let prefix = resource_path + "/";
|
let prefix = resource_path + '/';
|
||||||
const copy = async (object: R2Object) => {
|
const copy = async (object: R2Object) => {
|
||||||
let target = destination + "/" + object.key.slice(prefix.length);
|
let target = destination + '/' + object.key.slice(prefix.length);
|
||||||
target = target.endsWith("/") ? target.slice(0, -1) : target;
|
target = target.endsWith('/') ? target.slice(0, -1) : target;
|
||||||
let src = await bucket.get(object.key);
|
let src = await bucket.get(object.key);
|
||||||
if (src !== null) {
|
if (src !== null) {
|
||||||
await bucket.put(target, src.body, {
|
await bucket.put(target, src.body, {
|
||||||
@ -611,9 +621,9 @@ async function dispatch_handler(request: Request, bucket: R2Bucket): Promise<Res
|
|||||||
return new Response('Method Not Allowed', {
|
return new Response('Method Not Allowed', {
|
||||||
status: 405,
|
status: 405,
|
||||||
headers: {
|
headers: {
|
||||||
'Allow': SUPPORT_METHODS.join(', '),
|
Allow: SUPPORT_METHODS.join(', '),
|
||||||
'DAV': DAV_CLASS,
|
DAV: DAV_CLASS,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -625,9 +635,10 @@ export default {
|
|||||||
|
|
||||||
if (request.headers.get('Authorization') !== `Basic ${btoa(`${env.USERNAME}:${env.PASSWORD}`)}`) {
|
if (request.headers.get('Authorization') !== `Basic ${btoa(`${env.USERNAME}:${env.PASSWORD}`)}`) {
|
||||||
return new Response('Unauthorized', {
|
return new Response('Unauthorized', {
|
||||||
status: 401, headers: {
|
status: 401,
|
||||||
|
headers: {
|
||||||
'WWW-Authenticate': 'Basic realm="webdav"',
|
'WWW-Authenticate': 'Basic realm="webdav"',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,15 +647,17 @@ export default {
|
|||||||
// Set CORS headers
|
// Set CORS headers
|
||||||
response.headers.set('Access-Control-Allow-Origin', request.headers.get('Origin') ?? '*');
|
response.headers.set('Access-Control-Allow-Origin', request.headers.get('Origin') ?? '*');
|
||||||
response.headers.set('Access-Control-Allow-Methods', SUPPORT_METHODS.join(', '));
|
response.headers.set('Access-Control-Allow-Methods', SUPPORT_METHODS.join(', '));
|
||||||
response.headers.set('Access-Control-Allow-Headers',
|
response.headers.set(
|
||||||
["authorization", "content-type", "depth", "overwrite", "destination", "range"].join(', ')
|
'Access-Control-Allow-Headers',
|
||||||
|
['authorization', 'content-type', 'depth', 'overwrite', 'destination', 'range'].join(', '),
|
||||||
);
|
);
|
||||||
response.headers.set('Access-Control-Expose-Headers',
|
response.headers.set(
|
||||||
["content-type", "content-length", "dav", "etag", "last-modified", "location", "date", "content-range"].join(', ')
|
'Access-Control-Expose-Headers',
|
||||||
|
['content-type', 'content-length', 'dav', 'etag', 'last-modified', 'location', 'date', 'content-range'].join(', '),
|
||||||
);
|
);
|
||||||
response.headers.set('Access-Control-Allow-Credentials', 'false');
|
response.headers.set('Access-Control-Allow-Credentials', 'false');
|
||||||
response.headers.set('Access-Control-Max-Age', '86400');
|
response.headers.set('Access-Control-Max-Age', '86400');
|
||||||
|
|
||||||
return response
|
return response;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user