Skip to content

Commit 92978dc

Browse files
committed
feat: support multi-suffix config files and switch default to TOML
1 parent 7fa0dc3 commit 92978dc

11 files changed

Lines changed: 168 additions & 103 deletions

File tree

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ENV UID=1000
66
ENV GID=1000
77
ENV WEBDAV_HOST="0.0.0.0"
88
ENV WEBDAV_PORT="8000"
9-
ENV WEBDAV_CONFIGFILE="/data/webdav.json"
9+
ENV WEBDAV_CONFIGFILE="/data/webdav.toml"
1010
ENV WEBDAV_LOGGING_LEVEL="INFO"
1111

1212
RUN if [ "$BUILD_DEV" = "rex" ]; then echo "Change depends" \

TODO

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
进行中:
2-
匿名账号支持
2+
匿名账号支持 @done(25-10-30)
33
✔ 重新设计 Config 部分 @done(25-10-08)
44
✔ 匿名账号在账号清单中生效 @done(25-10-19)
55
✔ 匿名账号能通过 HTTP Auth 登录 @done(25-10-19)
@@ -11,7 +11,13 @@
1111
TOML 作为配置文件的第一格式
1212
✔ pydantic => dataclass @done
1313
✔ 添加 TOML 支持 @done
14-
☐ 使用 TOML 方便方便添加注释的特性增加各种使用场景配置范例 @long-term
14+
✔ docker 环境支持自动尝试多种配置文件后缀 @done(25-10-31)
15+
✔ 默认配置文件改为 webdav.toml @done(25-10-31)
16+
☐ 自动尝试多种配置文件后缀这个行为通过命令行打开,默认不开启
17+
☐ 通过配置文件实现 dev 模式的切换
18+
☐ 通过配置文件实现 litmus 模式的切换 @wip
19+
☐ 更新文档 @wip
20+
☐ 使用 TOML 方便添加注释的特性, 增加各种使用场景配置范例 @long-term
1521
☐ 以 TOML 下的可读性为标准,适当调整配置文件结构 @long-term
1622

1723
长期性任务:
@@ -31,12 +37,15 @@
3137
☐ 文档自动部署失效问题
3238

3339
待实现:
40+
☐ 兼容 Py3.14
3441
☐ 重构 DAVResponse 来统一 401 的响应行为 @high @next-release
3542
☐ 浏览器请求才弹认证请求框, 服务器返回 401 时不弹认证框
3643
☐ 重构部分 DAVResponse 代码, 这个与压缩依赖部分一起修改
3744
☐ 顺带解决 litmus 的一个告警?
38-
☐ 移除第三方压缩依赖,添加sztd支持 @delay dataclass-wizard 不兼容 py3.14
39-
☐ Digest auth support neon @low @@deplay 需要时间过多
45+
☐ 移除第三方压缩依赖,添加sztd支持 @block dataclass-wizard 不兼容 py3.14
46+
☐ 更新 xmltodict 到最新版本
47+
这个上游库变化非常大, 之前版本与现在版本不兼容
48+
☐ Digest auth support neon @deplay 需要时间过多
4049

4150
待确定实现方案:
4251
☐ 统一 user/account 的概念 @low
@@ -53,5 +62,6 @@
5362

5463
待确定可行性:
5564
☐ generate random URL for share(read only) @high
65+
`/_/share/ + random string`
5666
☐ rewrite MemoryProvider with mmap or other
5767
☐ logout at the web page

asgi_webdav/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def convert_click_kwargs_to_aep(kwargs: dict) -> AppEntryParameters:
5656
"-c",
5757
"--config",
5858
default=None,
59-
help="Load configuration from file. [default: None]",
59+
help="Load configuration from file, support .toml/.json [default: None]",
6060
)
6161
@click.option(
6262
"-u",

asgi_webdav/config.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
AppEntryParameters,
2626
DAVCompressLevel,
2727
)
28+
from asgi_webdav.exception import DAVExceptionConfigFileNotFound
2829

2930
logger = getLogger(__name__)
3031

@@ -337,7 +338,8 @@ def reinit_config_from_file(file_name: str, complete_config: bool = False) -> bo
337338
message = f"Can not open config file[{file}]!"
338339
logger.error(message)
339340
logger.error(e)
340-
return False
341+
# return False
342+
raise DAVExceptionConfigFileNotFound(e)
341343

342344
except (json.JSONDecodeError, tomllib.TOMLDecodeError) as e:
343345
message = f"Load config from file[{file}] failed!"
@@ -348,3 +350,32 @@ def reinit_config_from_file(file_name: str, complete_config: bool = False) -> bo
348350
reinit_config_from_dict(data, complete_config)
349351
logger.info(f"Load config from file: [{file}] success!")
350352
return True
353+
354+
355+
def reinit_config_from_file_multi_suffix(
356+
file_name: str, complete_config: bool = False
357+
) -> bool:
358+
"""help users in switching from .json to .toml configuration files."""
359+
360+
try:
361+
return reinit_config_from_file(file_name, complete_config)
362+
except DAVExceptionConfigFileNotFound:
363+
logger.warning(f"Can not found config file: {file_name}!")
364+
365+
# try other suffix
366+
file = Path(file_name)
367+
stem = file.stem
368+
suffix = file.suffix
369+
370+
suffixs = {".json", ".toml"}
371+
suffixs.remove(suffix)
372+
373+
for suffix in suffixs:
374+
file_name = f"{stem}{suffix}"
375+
logger.warning(f"Try load config file: {file_name}!")
376+
try:
377+
return reinit_config_from_file(file_name, complete_config)
378+
except DAVExceptionConfigFileNotFound:
379+
logger.warning(f"Can not found config file: {file_name}!")
380+
381+
return False

asgi_webdav/exception.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class DAVExceptionConfig(DAVException):
1414
pass
1515

1616

17+
class DAVExceptionConfigFileNotFound(DAVExceptionConfig):
18+
pass
19+
20+
1721
class DAVExceptionRequestParserFailed(DAVException):
1822
pass
1923

asgi_webdav/server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
Config,
1414
get_config,
1515
reinit_config_from_dict,
16-
reinit_config_from_file,
16+
reinit_config_from_file_multi_suffix,
1717
)
1818
from asgi_webdav.constants import AppEntryParameters, DAVMethod, DevMode
1919
from asgi_webdav.exception import DAVExceptionProviderInitFailed
@@ -109,7 +109,7 @@ def get_asgi_app(aep: AppEntryParameters, config_obj: dict | None = None):
109109

110110
# init config
111111
if aep.config_file is not None:
112-
reinit_config_from_file(aep.config_file)
112+
reinit_config_from_file_multi_suffix(aep.config_file)
113113
elif config_obj is not None:
114114
reinit_config_from_dict(config_obj)
115115

docs/compatibility.en.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ litmus http://IPAddress:8000/provider/memory username password
3434
- Version: 1.3.2
3535

3636
```shell
37-
python -m asgi_webdav --litmus
37+
python -m asgi_webdav -c examples/config/litmus.toml -H 0.0.0.0
38+
# or
39+
python -m asgi_webdav --litmus # Deprecated
3840
```
3941

4042
```text

docs/reference/config-file.en.md

Lines changed: 67 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# Config File
22

3-
## `webdav.json` file
3+
## `webdav.toml` file
4+
5+
### Convert `.json` to `.toml`
6+
7+
please search `convert json toml` in your browser.
48

59
### When the file does not exist
610

7-
When the file `/data/webdav.json` does not exist, `http://127.0.0.1/` will map to the `/data` directory.
11+
When the file `/data/webdav.toml(.json)` does not exist, `http://127.0.0.1/` will map to the `/data` directory.
812

913
#### logging output
1014

@@ -21,62 +25,54 @@ INFO: [uvicorn] Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
2125

2226
When the file exists, the mapping relationship is defined by the file content.
2327

24-
#### Sample
25-
26-
```json
27-
{
28-
"account_mapping": [
29-
{
30-
"username": "username",
31-
"password": "password",
32-
"permissions": ["+"]
33-
},
34-
{
35-
"username": "litmus",
36-
"password": "password",
37-
"permissions": ["+^/$", "+^/litmus", "-^/litmus/other"]
38-
},
39-
{
40-
"username": "guest",
41-
"password": "password",
42-
"permissions": []
43-
}
44-
],
45-
"anonymous": { "enable": true },
46-
"http_basic_auth": {
47-
"cache_type": "expiring",
48-
"cache_timeout": 3600
49-
},
50-
"provider_mapping": [
51-
{
52-
"prefix": "/",
53-
"uri": "file:///data/root",
54-
"read_only": true
55-
},
56-
{
57-
"prefix": "/provider",
58-
"uri": "memory:///",
59-
"read_only": true
60-
},
61-
{
62-
"prefix": "/provider/fs",
63-
"uri": "file:///data/litmus"
64-
},
65-
{
66-
"prefix": "/provider/memory",
67-
"uri": "memory:///",
68-
"ignore_property_extra": false
69-
},
70-
{
71-
"prefix": "/~",
72-
"uri": "file:///data/home",
73-
"home_dir": true
74-
}
75-
],
76-
"logging_level": "INFO"
77-
}
28+
#### Example
29+
30+
```toml
31+
[[account_mapping]]
32+
username = "username"
33+
password = "password"
34+
permissions = [ "+" ]
35+
36+
[[account_mapping]]
37+
username = "litmus"
38+
password = "password"
39+
permissions = [ "+^/$", "+^/litmus", "-^/litmus/other" ]
40+
41+
[[account_mapping]]
42+
username = "guest"
43+
password = "password"
44+
permissions = [ ]
45+
46+
[anonymous]
47+
enable = true
48+
49+
[[provider_mapping]]
50+
prefix = "/"
51+
uri = "file:///data/root"
52+
read_only = true
53+
54+
[[provider_mapping]]
55+
prefix = "/provider"
56+
uri = "memory:///"
57+
read_only = true
58+
59+
[[provider_mapping]]
60+
prefix = "/provider/fs"
61+
uri = "file:///data/litmus"
62+
63+
[[provider_mapping]]
64+
prefix = "/provider/memory"
65+
uri = "memory:///"
66+
ignore_property_extra = false
67+
68+
[[provider_mapping]]
69+
prefix = "/~"
70+
uri = "file:///data/home"
71+
home_dir = true
7872
```
7973

74+
More example please check `examples/config/*.toml` in codebase.
75+
8076
#### logging output
8177

8278
```text
@@ -112,24 +108,9 @@ root object
112108
| text_file_charset_detect | rules | `TextFileCharsetDetect` | `TextFileCharsetDetect()` |
113109
| compression | response | `Compression` | `Compression()` |
114110
| cors | response | `CORS` | `CORS()` |
115-
| logging_level | other | `str` | `"INFO"` |
116-
117-
Example
118-
119-
```text
120-
{
121-
"account_mapping": [...],
122-
"anonymous": {...},
123-
"http_digest_auth": {...},
124-
"provider_mapping": [...],
125-
"hide_file_in_dir": {...},
126-
"guess_type_extension": {...},
127-
"text_file_charset_detect": {...},
128-
"compression": {...},
129-
"cors": {...},
130-
"logging_level": "INFO"
131-
}
132-
```
111+
| enable_dir_browser | response | `bool` | `true` |
112+
| logging | other | `Logging` | `"Logging()"` |
113+
| sentry_dsn | other | `str` | `None` |
133114

134115
## for Authentication
135116

@@ -330,3 +311,15 @@ More detail, please see howto.
330311
| allow_credentials | bool | `false` | - |
331312
| expose_headers | list[str] | `[]` | - |
332313
| preflight_max_age | int | `600` | - |
314+
315+
### `logging` Object
316+
317+
- Introduced in 1.4
318+
- Last updated in 1.4
319+
320+
| Key | Value Type | Default Value |
321+
| ---------------- | ---------- | ------------- |
322+
| enable | bool | `true` |
323+
| level | str | `"INFO"` |
324+
| display_datetime | bool | `true` |
325+
| use_colors | bool | `true` |

docs/reference/env-value.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
| ----------------- | ------------------- |
1515
| WEBDAV_HOST | `0.0.0.0` |
1616
| WEBDAV_PORT | `8000` |
17-
| WEBDAV_CONFIGFILE | `/data/webdav.json` |
17+
| WEBDAV_CONFIGFILE | `/data/webdav.toml` |

examples/config/litmus.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[[account_mapping]]
2+
username = "username"
3+
password = "password"
4+
permissions = ["+"]
5+
admin = true
6+
7+
[[provider_mapping]]
8+
uri = "memory:///"
9+
prefix = "/"
10+
read_only = true
11+
ignore_property_extra = false
12+
13+
[[provider_mapping]]
14+
prefix = "/provider"
15+
uri = "memory:///"
16+
read_only = true
17+
ignore_property_extra = false
18+
19+
[[provider_mapping]]
20+
prefix = "/provider/fs"
21+
uri = "file:///tmp"
22+
ignore_property_extra = false
23+
24+
[[provider_mapping]]
25+
prefix = "/provider/memory"
26+
uri = "memory:///"
27+
ignore_property_extra = false

0 commit comments

Comments
 (0)