Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7c715682f7 |
15
.github/workflows/ci.yml
vendored
Normal file
15
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "20.x"
|
||||||
|
- run: npm install
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"printWidth": 120,
|
"printWidth": 140,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"useTabs": true
|
"useTabs": true
|
||||||
|
18
README.md
18
README.md
@ -4,24 +4,22 @@
|
|||||||
|
|
||||||
Use Cloudflare Workers to provide a WebDav interface for Cloudflare R2.
|
Use Cloudflare Workers to provide a WebDav interface for Cloudflare R2.
|
||||||
|
|
||||||
## Usage
|
## Configuration
|
||||||
|
|
||||||
Change wrangler.toml to your own.
|
Change wrangler.toml to your own.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[[r2_buckets]]
|
[[r2_buckets]]
|
||||||
binding = 'bucket' # <~ valid JavaScript variable name, don't change this
|
binding = 'webdav' # <~ valid JavaScript variable name, don't change this
|
||||||
bucket_name = 'webdav'
|
bucket_name = 'webdav'
|
||||||
|
|
||||||
|
[vars]
|
||||||
|
USERNAME = "USERNAME"
|
||||||
|
PASSWORD = "PASSWORD"
|
||||||
```
|
```
|
||||||
|
|
||||||
Then use wrangler to deploy.
|
* USERNAME: The username of WebDav.
|
||||||
|
* PASSWORD: The password of WebDav.
|
||||||
```bash
|
|
||||||
wrangler deploy
|
|
||||||
|
|
||||||
wrangler secret put USERNAME
|
|
||||||
wrangler secret put PASSWORD
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
267
package-lock.json
generated
267
package-lock.json
generated
@ -9,24 +9,23 @@
|
|||||||
"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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/kv-asset-handler": {
|
"node_modules/@cloudflare/kv-asset-handler": {
|
||||||
"version": "0.3.1",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz",
|
||||||
"integrity": "sha512-lKN2XCfKCmpKb86a1tl4GIwsJYDy9TGuwjhDELLmpKygQhw8X2xR4dusgpC5Tg7q1pB96Eb0rBo81kxSILQMwA==",
|
"integrity": "sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mime": "^3.0.0"
|
"mime": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/workerd-darwin-64": {
|
"node_modules/@cloudflare/workerd-darwin-64": {
|
||||||
"version": "1.20240223.1",
|
"version": "1.20231030.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240223.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20231030.0.tgz",
|
||||||
"integrity": "sha512-GgHnvkazLFZ7bmR96+dTX0+WS13a+5CHOOP3qNUSR9oEnR4hHzpNIO75MuZsm9RPAXrvtT7nSJmYwiGCZXh6og==",
|
"integrity": "sha512-J4PQ9utPxLya9yHdMMx3AZeC5M/6FxcoYw6jo9jbDDFTy+a4Gslqf4Im9We3aeOEdPXa3tgQHVQOSelJSZLhIw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -40,9 +39,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/workerd-darwin-arm64": {
|
"node_modules/@cloudflare/workerd-darwin-arm64": {
|
||||||
"version": "1.20240223.1",
|
"version": "1.20231030.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240223.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20231030.0.tgz",
|
||||||
"integrity": "sha512-ZF98vUmVlC0EVEd3RRuhMq4HYWFcqmPtMIMPUN2+ivEHR92TE+6E/AvdeE6wcE7fKHQ+fk3dH+ZgB0GcfptfnA==",
|
"integrity": "sha512-WSJJjm11Del4hSneiNB7wTXGtBXI4QMCH9l5qf4iT5PAW8cESGcCmdHtWDWDtGAAGcvmLT04KNvmum92vRKKQQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -56,9 +55,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/workerd-linux-64": {
|
"node_modules/@cloudflare/workerd-linux-64": {
|
||||||
"version": "1.20240223.1",
|
"version": "1.20231030.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240223.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20231030.0.tgz",
|
||||||
"integrity": "sha512-1kH41ewNTGMmAk2zUX0Xj9VSfidl26GQ0ZrWMdi5kwf6gAHd3oVWNigJN078Jx56SgQxNcqVGX1LunqF949asw==",
|
"integrity": "sha512-2HUeRTvoCC17fxE0qdBeR7J9dO8j4A8ZbdcvY8pZxdk+zERU6+N03RTbk/dQMU488PwiDvcC3zZqS4gwLfVT8g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -72,9 +71,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/workerd-linux-arm64": {
|
"node_modules/@cloudflare/workerd-linux-arm64": {
|
||||||
"version": "1.20240223.1",
|
"version": "1.20231030.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240223.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20231030.0.tgz",
|
||||||
"integrity": "sha512-Ro8Og5C4evh890JrRm0B8sHyumRtgL+mUqPeNcEsyG45jAQy5xHpapHnmJAMJV6ah+zDc1cZtQq+en39SojXvQ==",
|
"integrity": "sha512-4/GK5zHh+9JbUI6Z5xTCM0ZmpKKHk7vu9thmHjUxtz+o8Ne9DoD7DlDvXQWgMF6XGaTubDWyp3ttn+Qv8jDFuQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -88,9 +87,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/workerd-windows-64": {
|
"node_modules/@cloudflare/workerd-windows-64": {
|
||||||
"version": "1.20240223.1",
|
"version": "1.20231030.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240223.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20231030.0.tgz",
|
||||||
"integrity": "sha512-eNP5sfaP6WL07DaoigYou5ASPF7jHsFiNzzD2vGOI7yFd5sPlb7sJ4SpIy+BCX0LdqFnjmlUo5Xr+/I6qJ2Nww==",
|
"integrity": "sha512-fb/Jgj8Yqy3PO1jLhk7mTrHMkR8jklpbQFud6rL/aMAn5d6MQbaSrYOCjzkKGp0Zng8D2LIzSl+Fc0C9Sggxjg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -104,9 +103,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/workers-types": {
|
"node_modules/@cloudflare/workers-types": {
|
||||||
"version": "4.20240222.0",
|
"version": "4.20231121.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240222.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20231121.0.tgz",
|
||||||
"integrity": "sha512-luO0BdK3rLlCv3B240+cTrfqm+XSbHtpk+88aJtGwzyVK9QF/Xz8lBgE/oZZLN8nCTmOvxAZnszyxUuZ8GP8Cg==",
|
"integrity": "sha512-+kWfpCkqiepwAKXyHoE0gnkPgkLhz0/9HOBIGhHRsUvUKvhUtm3mbqqoGRWgF1qcjzrDUBbrrOq4MYHfFtc2RA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@cspotcode/source-map-support": {
|
"node_modules/@cspotcode/source-map-support": {
|
||||||
@ -496,18 +495,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fastify/busboy": {
|
"node_modules/@fastify/busboy": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
|
||||||
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
|
"integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/resolve-uri": {
|
"node_modules/@jridgewell/resolve-uri": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
||||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
@ -530,27 +529,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.11.24",
|
"version": "20.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz",
|
||||||
"integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==",
|
"integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~5.26.4"
|
"undici-types": "~5.26.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node-forge": {
|
"node_modules/@types/node-forge": {
|
||||||
"version": "1.3.11",
|
"version": "1.3.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz",
|
||||||
"integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
|
"integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.11.3",
|
"version": "8.11.2",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
|
||||||
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
|
"integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
@ -560,9 +559,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn-walk": {
|
"node_modules/acorn-walk": {
|
||||||
"version": "8.3.2",
|
"version": "8.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz",
|
||||||
"integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==",
|
"integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
@ -606,17 +605,23 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/braces": {
|
"node_modules/braces": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fill-range": "^7.1.1"
|
"fill-range": "^7.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-from": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/capnp-ts": {
|
"node_modules/capnp-ts": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz",
|
||||||
@ -628,10 +633,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.6.0",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "~3.1.2",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
@ -644,9 +655,6 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 8.10.0"
|
"node": ">= 8.10.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
|
||||||
"url": "https://paulmillr.com/funding/"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
@ -751,9 +759,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.1.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
@ -776,15 +784,6 @@
|
|||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/function-bind": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/get-source": {
|
"node_modules/get-source": {
|
||||||
"version": "2.0.12",
|
"version": "2.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz",
|
||||||
@ -813,18 +812,6 @@
|
|||||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/hasown": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"function-bind": "^1.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-binary-path": {
|
"node_modules/is-binary-path": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
@ -837,18 +824,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-core-module": {
|
|
||||||
"version": "2.13.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
|
|
||||||
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"hasown": "^2.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-extglob": {
|
"node_modules/is-extglob": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
@ -901,20 +876,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/miniflare": {
|
"node_modules/miniflare": {
|
||||||
"version": "3.20240223.0",
|
"version": "3.20231030.4",
|
||||||
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240223.0.tgz",
|
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20231030.4.tgz",
|
||||||
"integrity": "sha512-8T/36FEfvsL4aMF7SLZ28v+PQL0jsUlVw/u114GYcdobkyPax9E6Ahn0XePOHEqLxQSndwPee+eS1phHANFePA==",
|
"integrity": "sha512-7MBz0ArLuDop1WJGZC6tFgN6c5MRyDOIlxbm3yp0TRBpvDS/KsTuWCQcCjsxN4QQ5zvL3JTkuIZbQzRRw/j6ow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cspotcode/source-map-support": "0.8.1",
|
|
||||||
"acorn": "^8.8.0",
|
"acorn": "^8.8.0",
|
||||||
"acorn-walk": "^8.2.0",
|
"acorn-walk": "^8.2.0",
|
||||||
"capnp-ts": "^0.7.0",
|
"capnp-ts": "^0.7.0",
|
||||||
"exit-hook": "^2.2.1",
|
"exit-hook": "^2.2.1",
|
||||||
"glob-to-regexp": "^0.4.1",
|
"glob-to-regexp": "^0.4.1",
|
||||||
|
"source-map-support": "0.5.21",
|
||||||
"stoppable": "^1.1.0",
|
"stoppable": "^1.1.0",
|
||||||
"undici": "^5.28.2",
|
"undici": "^5.22.1",
|
||||||
"workerd": "1.20240223.1",
|
"workerd": "1.20231030.0",
|
||||||
"ws": "^8.11.0",
|
"ws": "^8.11.0",
|
||||||
"youch": "^3.2.2",
|
"youch": "^3.2.2",
|
||||||
"zod": "^3.20.6"
|
"zod": "^3.20.6"
|
||||||
@ -977,12 +952,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/path-parse": {
|
|
||||||
"version": "1.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
|
||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/path-to-regexp": {
|
"node_modules/path-to-regexp": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
|
||||||
@ -1001,21 +970,6 @@
|
|||||||
"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",
|
||||||
@ -1034,23 +988,6 @@
|
|||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/resolve": {
|
|
||||||
"version": "1.22.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
|
||||||
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"is-core-module": "^2.13.0",
|
|
||||||
"path-parse": "^1.0.7",
|
|
||||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"resolve": "bin/resolve"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/resolve.exports": {
|
"node_modules/resolve.exports": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
|
||||||
@ -1112,6 +1049,16 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/source-map-support": {
|
||||||
|
"version": "0.5.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||||
|
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-from": "^1.0.0",
|
||||||
|
"source-map": "^0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sourcemap-codec": {
|
"node_modules/sourcemap-codec": {
|
||||||
"version": "1.4.8",
|
"version": "1.4.8",
|
||||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||||
@ -1139,18 +1086,6 @@
|
|||||||
"npm": ">=6"
|
"npm": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/supports-preserve-symlinks-flag": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
@ -1183,9 +1118,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "5.28.4",
|
"version": "5.28.2",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.2.tgz",
|
||||||
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
|
"integrity": "sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/busboy": "^2.0.0"
|
"@fastify/busboy": "^2.0.0"
|
||||||
@ -1201,9 +1136,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/workerd": {
|
"node_modules/workerd": {
|
||||||
"version": "1.20240223.1",
|
"version": "1.20231030.0",
|
||||||
"resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240223.1.tgz",
|
"resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20231030.0.tgz",
|
||||||
"integrity": "sha512-Mo1fwdp6DLva4/fWdL09ZdYllkO45I4YpWG5PbF/YUGFlu2aMk24fmU6Pd6fo5/cWek4F+n3LmYEKKHfqjiJIA==",
|
"integrity": "sha512-+FSW+d31f8RrjHanFf/R9A+Z0csf3OtsvzdPmAKuwuZm/5HrBv83cvG9fFeTxl7/nI6irUUXIRF9xcj/NomQzQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -1213,29 +1148,29 @@
|
|||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@cloudflare/workerd-darwin-64": "1.20240223.1",
|
"@cloudflare/workerd-darwin-64": "1.20231030.0",
|
||||||
"@cloudflare/workerd-darwin-arm64": "1.20240223.1",
|
"@cloudflare/workerd-darwin-arm64": "1.20231030.0",
|
||||||
"@cloudflare/workerd-linux-64": "1.20240223.1",
|
"@cloudflare/workerd-linux-64": "1.20231030.0",
|
||||||
"@cloudflare/workerd-linux-arm64": "1.20240223.1",
|
"@cloudflare/workerd-linux-arm64": "1.20231030.0",
|
||||||
"@cloudflare/workerd-windows-64": "1.20240223.1"
|
"@cloudflare/workerd-windows-64": "1.20231030.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/wrangler": {
|
"node_modules/wrangler": {
|
||||||
"version": "3.30.1",
|
"version": "3.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.21.0.tgz",
|
||||||
"integrity": "sha512-cT6Ezx8h2v5QiI0HWhnHVy32ng4omdMVdhaMQLuMnyMIHmyDoRg7pmrbhtZfj0663gExLdVtE4ucK//yncVTwg==",
|
"integrity": "sha512-DLoo4XfjeyuGRAVWZFHmU1jWnZIfyLGDm6Ika9oy/CLCPfJzVJvf2jI70EU5BlEHWDZXMSJKw7FDdgSqwhaQXg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/kv-asset-handler": "0.3.1",
|
"@cloudflare/kv-asset-handler": "^0.2.0",
|
||||||
|
"@cspotcode/source-map-support": "0.8.1",
|
||||||
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
||||||
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
||||||
"blake3-wasm": "^2.1.5",
|
"blake3-wasm": "^2.1.5",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"esbuild": "0.17.19",
|
"esbuild": "0.17.19",
|
||||||
"miniflare": "3.20240223.0",
|
"miniflare": "3.20231030.4",
|
||||||
"nanoid": "^3.3.3",
|
"nanoid": "^3.3.3",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
"resolve": "^1.22.8",
|
|
||||||
"resolve.exports": "^2.0.2",
|
"resolve.exports": "^2.0.2",
|
||||||
"selfsigned": "^2.0.1",
|
"selfsigned": "^2.0.1",
|
||||||
"source-map": "0.6.1",
|
"source-map": "0.6.1",
|
||||||
@ -1250,20 +1185,12 @@
|
|||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@cloudflare/workers-types": "^4.20230914.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@cloudflare/workers-types": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.17.1",
|
"version": "8.15.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.15.1.tgz",
|
||||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
"integrity": "sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
|
@ -5,13 +5,10 @@
|
|||||||
"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"
|
||||||
},
|
},
|
||||||
|
289
src/index.ts
289
src/index.ts
@ -46,9 +46,22 @@ 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 SUPPORT_METHODS = [
|
||||||
|
"OPTIONS",
|
||||||
|
"PROPFIND",
|
||||||
|
"MKCOL",
|
||||||
|
"GET",
|
||||||
|
"HEAD",
|
||||||
|
"PUT",
|
||||||
|
"COPY",
|
||||||
|
"MOVE",
|
||||||
|
];
|
||||||
|
|
||||||
type DavProperties = {
|
type DavProperties = {
|
||||||
creationdate: string | undefined;
|
creationdate: string | undefined;
|
||||||
displayname: string | undefined;
|
displayname: string | undefined;
|
||||||
@ -58,7 +71,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) {
|
||||||
@ -66,11 +79,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 />",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,12 +99,23 @@ 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;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handle_options(request: Request, bucket: R2Bucket): Promise<Response> {
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204,
|
||||||
|
headers: {
|
||||||
|
'DAV': DAV_CLASS,
|
||||||
|
'Allow': SUPPORT_METHODS.join(', '),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function handle_head(request: Request, bucket: R2Bucket): Promise<Response> {
|
async function handle_head(request: Request, bucket: R2Bucket): Promise<Response> {
|
||||||
let response = await handle_get(request, bucket);
|
let response = await handle_get(request, bucket);
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
@ -109,15 +133,12 @@ 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>`;
|
||||||
}
|
}
|
||||||
return new Response(page, {
|
return new Response(page, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
|
||||||
status: 200,
|
|
||||||
headers: { 'Content-Type': 'text/html; charset=utf-8' },
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
let object = await bucket.get(resource_path, {
|
let object = await bucket.get(resource_path, {
|
||||||
onlyIf: request.headers,
|
onlyIf: request.headers,
|
||||||
@ -126,70 +147,40 @@ 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 {
|
||||||
const { rangeOffset, rangeEnd } = calcContentRange(object);
|
|
||||||
const contentLength = rangeEnd - rangeOffset + 1;
|
|
||||||
return new Response(object.body, {
|
return new Response(object.body, {
|
||||||
status: (object.range && contentLength !== object.size) ? 206 : 200,
|
status: object.range ? 206 : 200,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream',
|
'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream',
|
||||||
'Content-Length': contentLength.toString(),
|
// TODO: Content-Length, Content-Range
|
||||||
...({ 'Content-Range': `bytes ${rangeOffset}-${rangeEnd}/${object.size}` }),
|
|
||||||
...(object.httpMetadata?.contentDisposition
|
...(object.httpMetadata?.contentDisposition ? {
|
||||||
? {
|
|
||||||
'Content-Disposition': object.httpMetadata.contentDisposition,
|
'Content-Disposition': object.httpMetadata.contentDisposition,
|
||||||
}
|
} : {}),
|
||||||
: {}),
|
...(object.httpMetadata?.contentEncoding ? {
|
||||||
...(object.httpMetadata?.contentEncoding
|
|
||||||
? {
|
|
||||||
'Content-Encoding': object.httpMetadata.contentEncoding,
|
'Content-Encoding': object.httpMetadata.contentEncoding,
|
||||||
}
|
} : {}),
|
||||||
: {}),
|
...(object.httpMetadata?.contentLanguage ? {
|
||||||
...(object.httpMetadata?.contentLanguage
|
|
||||||
? {
|
|
||||||
'Content-Language': object.httpMetadata.contentLanguage,
|
'Content-Language': object.httpMetadata.contentLanguage,
|
||||||
}
|
} : {}),
|
||||||
: {}),
|
...(object.httpMetadata?.cacheControl ? {
|
||||||
...(object.httpMetadata?.cacheControl
|
|
||||||
? {
|
|
||||||
'Cache-Control': object.httpMetadata.cacheControl,
|
'Cache-Control': object.httpMetadata.cacheControl,
|
||||||
}
|
} : {}),
|
||||||
: {}),
|
...(object.httpMetadata?.cacheExpiry ? {
|
||||||
...(object.httpMetadata?.cacheExpiry
|
|
||||||
? {
|
|
||||||
'Cache-Expiry': object.httpMetadata.cacheExpiry.toISOString(),
|
'Cache-Expiry': object.httpMetadata.cacheExpiry.toISOString(),
|
||||||
|
} : {}),
|
||||||
}
|
}
|
||||||
: {}),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcContentRange(object: R2ObjectBody) {
|
|
||||||
let rangeOffset = 0;
|
|
||||||
let rangeEnd = object.size - 1;
|
|
||||||
if (object.range) {
|
|
||||||
if ('suffix' in object.range) {
|
|
||||||
// Case 3: {suffix: number}
|
|
||||||
rangeOffset = object.size - object.range.suffix;
|
|
||||||
} else {
|
|
||||||
// Case 1: {offset: number, length?: number}
|
|
||||||
// Case 2: {offset?: number, length: number}
|
|
||||||
rangeOffset = object.range.offset ?? 0;
|
|
||||||
let length = object.range.length ?? (object.size - rangeOffset);
|
|
||||||
rangeEnd = Math.min(rangeOffset + length - 1, object.size - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { rangeOffset, rangeEnd };
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handle_put(request: Request, bucket: R2Bucket): Promise<Response> {
|
async function handle_put(request: Request, bucket: R2Bucket): Promise<Response> {
|
||||||
if (request.url.endsWith('/')) {
|
if (request.url.endsWith('/')) {
|
||||||
return new Response('Method Not Allowed', { status: 405 });
|
return new Response('Method Not Allowed', { status: 405 });
|
||||||
@ -218,11 +209,10 @@ 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,
|
let r2_objects, cursor: string | undefined = undefined;
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -244,14 +234,13 @@ 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,
|
let r2_objects, cursor: string | undefined = undefined;
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -278,22 +267,28 @@ 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 });
|
||||||
}
|
}
|
||||||
|
|
||||||
function generate_propfind_response(object: R2Object | null): string {
|
async function handle_propfind(request: Request, bucket: R2Bucket): Promise<Response> {
|
||||||
if (object === null) {
|
let resource_path = make_resource_path(request);
|
||||||
return `
|
|
||||||
|
let is_collection: boolean;
|
||||||
|
let page = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<multistatus xmlns="DAV:">`;
|
||||||
|
|
||||||
|
if (resource_path === "") {
|
||||||
|
page += `
|
||||||
<response>
|
<response>
|
||||||
<href>/</href>
|
<href>/</href>
|
||||||
<propstat>
|
<propstat>
|
||||||
@ -306,10 +301,38 @@ function generate_propfind_response(object: R2Object | null): string {
|
|||||||
<status>HTTP/1.1 200 OK</status>
|
<status>HTTP/1.1 200 OK</status>
|
||||||
</propstat>
|
</propstat>
|
||||||
</response>`;
|
</response>`;
|
||||||
|
is_collection = true;
|
||||||
|
} else {
|
||||||
|
let object = await bucket.head(resource_path);
|
||||||
|
if (object === null) {
|
||||||
|
return new Response('Not Found', { status: 404 });
|
||||||
}
|
}
|
||||||
|
is_collection = object.customMetadata?.resourcetype === '<collection />';
|
||||||
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
let href = `/${object.key + (object.customMetadata?.resourcetype === '<collection />' ? '/' : '')}`;
|
||||||
return `
|
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>`
|
||||||
|
};
|
||||||
|
|
||||||
|
if (is_collection) {
|
||||||
|
let depth = request.headers.get('Depth') ?? 'infinity';
|
||||||
|
switch (depth) {
|
||||||
|
case '0': break;
|
||||||
|
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>
|
<response>
|
||||||
<href>${href}</href>
|
<href>${href}</href>
|
||||||
<propstat>
|
<propstat>
|
||||||
@ -323,44 +346,26 @@ function generate_propfind_response(object: R2Object | null): string {
|
|||||||
</propstat>
|
</propstat>
|
||||||
</response>`;
|
</response>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handle_propfind(request: Request, bucket: R2Bucket): Promise<Response> {
|
|
||||||
let resource_path = make_resource_path(request);
|
|
||||||
|
|
||||||
let is_collection: boolean;
|
|
||||||
let page = `<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<multistatus xmlns="DAV:">`;
|
|
||||||
|
|
||||||
if (resource_path === '') {
|
|
||||||
page += generate_propfind_response(null);
|
|
||||||
is_collection = true;
|
|
||||||
} else {
|
|
||||||
let object = await bucket.head(resource_path);
|
|
||||||
if (object === null) {
|
|
||||||
return new Response('Not Found', { status: 404 });
|
|
||||||
}
|
|
||||||
is_collection = object.customMetadata?.resourcetype === '<collection />';
|
|
||||||
page += generate_propfind_response(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_collection) {
|
|
||||||
let depth = request.headers.get('Depth') ?? 'infinity';
|
|
||||||
switch (depth) {
|
|
||||||
case '0':
|
|
||||||
break;
|
|
||||||
case '1':
|
|
||||||
{
|
|
||||||
let prefix = resource_path === '' ? resource_path : resource_path + '/';
|
|
||||||
for await (let object of listAll(bucket, prefix)) {
|
|
||||||
page += generate_propfind_response(object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'infinity':
|
case 'infinity': {
|
||||||
{
|
let prefix = resource_path === "" ? resource_path : resource_path + '/';
|
||||||
let prefix = resource_path === '' ? resource_path : resource_path + '/';
|
|
||||||
for await (let object of listAll(bucket, prefix, true)) {
|
for await (let object of listAll(bucket, prefix, true)) {
|
||||||
page += generate_propfind_response(object);
|
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;
|
||||||
@ -390,11 +395,8 @@ 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
|
let destination_parent = destination.split('/').slice(0, destination.endsWith('/') ? -2 : -1).join('/');
|
||||||
.split('/')
|
if (destination_parent !== '' && !await bucket.head(destination_parent)) {
|
||||||
.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 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,10 +417,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, {
|
||||||
@ -485,11 +487,8 @@ 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
|
let destination_parent = destination.split('/').slice(0, destination.endsWith('/') ? -2 : -1).join('/');
|
||||||
.split('/')
|
if (destination_parent !== '' && !await bucket.head(destination_parent)) {
|
||||||
.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 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,8 +506,7 @@ 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) {
|
if (destination_exists) { // Delete the destination first
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,10 +516,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 move = 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, {
|
||||||
@ -531,9 +529,9 @@ async function handle_move(request: Request, bucket: R2Bucket): Promise<Response
|
|||||||
await bucket.delete(object.key);
|
await bucket.delete(object.key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let promise_array = [move(resource)];
|
let promise_array = [copy(resource)];
|
||||||
for await (let object of listAll(bucket, prefix, true)) {
|
for await (let object of listAll(bucket, prefix, true)) {
|
||||||
promise_array.push(move(object));
|
promise_array.push(copy(object));
|
||||||
}
|
}
|
||||||
await Promise.all(promise_array);
|
await Promise.all(promise_array);
|
||||||
if (destination_exists) {
|
if (destination_exists) {
|
||||||
@ -580,19 +578,10 @@ async function handle_move(request: Request, bucket: R2Bucket): Promise<Response
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DAV_CLASS = '1';
|
|
||||||
const SUPPORT_METHODS = ['OPTIONS', 'PROPFIND', 'MKCOL', 'GET', 'HEAD', 'PUT', 'COPY', 'MOVE'];
|
|
||||||
|
|
||||||
async function dispatch_handler(request: Request, bucket: R2Bucket): Promise<Response> {
|
async function dispatch_handler(request: Request, bucket: R2Bucket): Promise<Response> {
|
||||||
switch (request.method) {
|
switch (request.method) {
|
||||||
case 'OPTIONS': {
|
case 'OPTIONS': {
|
||||||
return new Response(null, {
|
return await handle_options(request, bucket);
|
||||||
status: 204,
|
|
||||||
headers: {
|
|
||||||
Allow: SUPPORT_METHODS.join(', '),
|
|
||||||
DAV: DAV_CLASS,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
case 'HEAD': {
|
case 'HEAD': {
|
||||||
return await handle_head(request, bucket);
|
return await handle_head(request, bucket);
|
||||||
@ -622,9 +611,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,
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -634,15 +623,11 @@ export default {
|
|||||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
||||||
const { bucket } = env;
|
const { bucket } = env;
|
||||||
|
|
||||||
if (
|
if (request.headers.get('Authorization') !== `Basic ${btoa(`${env.USERNAME}:${env.PASSWORD}`)}`) {
|
||||||
request.method !== 'OPTIONS' &&
|
|
||||||
request.headers.get('Authorization') !== `Basic ${btoa(`${env.USERNAME}:${env.PASSWORD}`)}`
|
|
||||||
) {
|
|
||||||
return new Response('Unauthorized', {
|
return new Response('Unauthorized', {
|
||||||
status: 401,
|
status: 401, headers: {
|
||||||
headers: {
|
|
||||||
'WWW-Authenticate': 'Basic realm="webdav"',
|
'WWW-Authenticate': 'Basic realm="webdav"',
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,19 +636,15 @@ 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(
|
response.headers.set('Access-Control-Allow-Headers',
|
||||||
'Access-Control-Allow-Headers',
|
["authorization", "content-type", "depth", "overwrite", "destination", "range"].join(', ')
|
||||||
['authorization', 'content-type', 'depth', 'overwrite', 'destination', 'range'].join(', '),
|
|
||||||
);
|
);
|
||||||
response.headers.set(
|
response.headers.set('Access-Control-Expose-Headers',
|
||||||
'Access-Control-Expose-Headers',
|
["content-type", "content-length", "dav", "etag", "last-modified", "location", "date", "content-range"].join(', ')
|
||||||
['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
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -12,9 +12,7 @@
|
|||||||
|
|
||||||
/* Language and Environment */
|
/* Language and Environment */
|
||||||
"target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
"target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||||
"lib": [
|
"lib": ["es2021"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
|
||||||
"es2021"
|
|
||||||
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
|
|
||||||
"jsx": "react" /* Specify what JSX code is generated. */,
|
"jsx": "react" /* Specify what JSX code is generated. */,
|
||||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
@ -33,9 +31,7 @@
|
|||||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
|
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
|
||||||
"types": [
|
"types": ["@cloudflare/workers-types"] /* Specify type package names to be included without being referenced in a source file. */,
|
||||||
"@cloudflare/workers-types"
|
|
||||||
] /* Specify type package names to be included without being referenced in a source file. */,
|
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
"resolveJsonModule": true /* Enable importing .json files */,
|
"resolveJsonModule": true /* Enable importing .json files */,
|
||||||
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
|
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
|
||||||
|
@ -7,8 +7,9 @@ node_compat = true
|
|||||||
# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
|
# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
|
||||||
# Note: Use secrets to store sensitive data.
|
# Note: Use secrets to store sensitive data.
|
||||||
# Docs: https://developers.cloudflare.com/workers/platform/environment-variables
|
# Docs: https://developers.cloudflare.com/workers/platform/environment-variables
|
||||||
# [vars]
|
[vars]
|
||||||
# MY_VARIABLE = "my-value"
|
USERNAME = "USERNAME"
|
||||||
|
PASSWORD = "PASSWORD"
|
||||||
|
|
||||||
# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
|
# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
|
||||||
# Docs: https://developers.cloudflare.com/workers/runtime-apis/kv
|
# Docs: https://developers.cloudflare.com/workers/runtime-apis/kv
|
||||||
@ -20,7 +21,7 @@ node_compat = true
|
|||||||
# Docs: https://developers.cloudflare.com/r2/api/workers/workers-api-usage/
|
# Docs: https://developers.cloudflare.com/r2/api/workers/workers-api-usage/
|
||||||
[[r2_buckets]]
|
[[r2_buckets]]
|
||||||
binding = "bucket" # <~ valid JavaScript variable name
|
binding = "bucket" # <~ valid JavaScript variable name
|
||||||
bucket_name = "zotero"
|
bucket_name = "webdav"
|
||||||
|
|
||||||
# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
|
# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
|
||||||
# Docs: https://developers.cloudflare.com/queues/get-started
|
# Docs: https://developers.cloudflare.com/queues/get-started
|
||||||
|
Loading…
Reference in New Issue
Block a user