Skip to content

Commit ca05660

Browse files
committed
Release 0.3.6
Make upload size unlimited by default while keeping optional upload limits. Add a Simplified Chinese README and document bilingual README maintenance.
1 parent 6fabe03 commit ca05660

7 files changed

Lines changed: 125 additions & 17 deletions

File tree

‎AGENTS.md‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Treat this project as a temporary file-sharing tool for trusted environments. It
2222
- Adds an HTML upload form to directory listings.
2323
- Stores uploaded files in the requested directory after sanitizing the uploaded filename.
2424
- Avoids overwriting existing files by appending `_` to the target filename.
25-
- Rejects uploads larger than the configured upload limit; the default is 100 MiB and can be raised with `--max-upload-size MIB`.
25+
- Does not limit upload size by default; `--max-upload-size MIB` can set an explicit limit.
2626
- Uses Python standard library modules only.
2727

2828
## Important Implementation Notes
@@ -46,8 +46,8 @@ When making changes, prioritize these issues first:
4646
3. Preserve safer network defaults.
4747
The default bind address is `127.0.0.1`; document `0.0.0.0` as an explicit LAN/public option.
4848

49-
4. Maintain upload limits.
50-
Large or slow uploads can exhaust disk, memory, or worker capacity. The current limit is 100 MiB.
49+
4. Keep upload size behavior explicit.
50+
Large or slow uploads can exhaust disk, memory, or worker capacity. The default is currently unlimited; document any limit changes clearly and keep `--max-upload-size` behavior covered by tests.
5151

5252
5. Improve request robustness.
5353
Handle missing `Content-Type`, missing `content-length`, malformed multipart bodies, and interrupted uploads without crashing the server.
@@ -105,7 +105,8 @@ Keep these files aligned:
105105

106106
- `simple_http_server.py`: source version in `__version__`.
107107
- `CHANGELOG.md`: released changes.
108-
- `README.md`: install, run, Docker, support status, and security caveats.
108+
- `README.md`: English install, run, Docker, support status, and security caveats.
109+
- `README.zh-CN.md`: Simplified Chinese translation of `README.md`; update it whenever the English README changes.
109110
- `SECURITY.md`: supported versions and vulnerability contact.
110111
- `.github/workflows/github-actions-test.yml`: supported Python versions and CI checks.
111112

‎CHANGELOG.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
<a name="0.3.6"></a>
2+
## [0.3.6] (2026-06-03)
3+
### Features
4+
5+
* make upload size unlimited by default while keeping optional `--max-upload-size`
6+
* add a Simplified Chinese README and language links between README files
7+
18
<a name="0.3.5"></a>
29
## [0.3.5] (2026-06-03)
310
### Features

‎README.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# simple_http_server
22

3+
[English](README.md) | [简体中文](README.zh-CN.md)
4+
35
## Features
46

57
- ✔ simple
@@ -19,7 +21,7 @@ $ cd simple_http_server
1921
# run server
2022
$ python simple_http_server.py 8000
2123

22-
# allow upload requests up to 1 GiB
24+
# optionally limit upload requests to 1 GiB
2325
$ python simple_http_server.py --max-upload-size 1024 8000
2426

2527
# expose to another host in a trusted network
@@ -49,7 +51,7 @@ docker run
4951

5052
This server is intended for temporary file sharing in trusted environments. The default bind address is `127.0.0.1`; use `--bind 0.0.0.0` only when you explicitly want other hosts to connect.
5153

52-
Uploaded file names are sanitized, upload results and directory listings escape user-controlled text, and upload requests larger than 100 MiB are rejected by default. Use `--max-upload-size MIB` to raise that limit in trusted environments.
54+
Uploaded file names are sanitized, and upload results and directory listings escape user-controlled text. Upload size is unlimited by default; use `--max-upload-size MIB` to set a limit when you need one in trusted environments.
5355

5456
## Example
5557

‎README.zh-CN.md‎

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# simple_http_server
2+
3+
[English](README.md) | [简体中文](README.zh-CN.md)
4+
5+
## 功能
6+
7+
- 简单易用
8+
- 支持上传
9+
- 支持批量上传
10+
- 支持下载
11+
- 支持 Python 2 和 Python 3
12+
- 支持多线程
13+
14+
## 使用方法
15+
16+
```bash
17+
# 获取代码
18+
$ git clone https://github.com/freelamb/simple_http_server.git
19+
20+
# 进入目录
21+
$ cd simple_http_server
22+
23+
# 启动服务
24+
$ python simple_http_server.py 8000
25+
26+
# 可选:将上传请求限制为 1 GiB
27+
$ python simple_http_server.py --max-upload-size 1024 8000
28+
29+
# 在可信网络中允许其他主机访问
30+
$ python simple_http_server.py --bind 0.0.0.0 8000
31+
```
32+
33+
发布版本后,可以从 PyPI 安装:
34+
35+
```bash
36+
$ python -m pip install simple-http-server-upload
37+
$ simple-http-server-upload 8000
38+
```
39+
40+
```bash
41+
# 作为 Docker 容器运行
42+
# 1. 构建镜像(下面的 "." 表示项目根目录)
43+
docker build -t freelamb/simple_http_server .
44+
45+
# 2. 使用刚刚构建的镜像启动容器
46+
docker run
47+
--name simple_http_server \
48+
-p 8000:8000 \
49+
-v /opt/data:/opt/data \
50+
-d freelamb/simple_http_server:latest
51+
```
52+
53+
## 安全说明
54+
55+
这个服务用于可信环境中的临时文件共享。默认绑定地址是 `127.0.0.1`;只有在明确希望其他主机连接时,才使用 `--bind 0.0.0.0`。
56+
57+
上传文件名会被清理,上传结果和目录列表会对用户可控文本做 HTML 转义。上传大小默认不设上限;如需限制上传大小,可以在可信环境中使用 `--max-upload-size MIB`。
58+
59+
## 示例
60+
61+
![](image/example.jpeg)
62+
63+
## 待办
64+
65+
- [ ] 添加 Docker 镜像
66+
67+
## 贡献
68+
69+
1. 检查已有 issue,或新建 issue 来讨论功能想法或问题。
70+
2. 在 GitHub 上 fork [本仓库](https://github.com/freelamb/simple_http_server),从 **master** 分支开始修改,或基于它创建新分支。
71+
3. 编写测试,证明问题已经修复,或功能符合预期。
72+
4. 提交 pull request,并持续跟进直到合并和发布。记得把自己添加到 [AUTHORS](AUTHORS.md)。
73+
74+
## 更新日志
75+
76+
[更新日志](CHANGELOG.md)
77+
78+
## 参考
79+
80+
<https://github.com/tualatrix/tools/blob/master/SimpleHTTPServerWithUpload.py>
81+
82+
## 许可证
83+
84+
[MIT](https://tldrlegal.com/license/mit-license)

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "simple-http-server-upload"
7-
version = "0.3.5"
7+
version = "0.3.6"
88
description = "A small HTTP file server with directory browsing and uploads."
99
readme = "README.md"
1010
requires-python = ">=3.9"

‎simple_http_server.py‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
and HEAD requests in a fairly straightforward manner.
77
"""
88

9-
__version__ = "0.3.5"
9+
__version__ = "0.3.6"
1010
__author__ = "yangyongbao@126.com"
1111
__all__ = ["SimpleHTTPRequestHandler"]
1212

@@ -47,8 +47,8 @@ class ThreadingHTTPServer(ThreadingMixIn, BaseHTTPServer):
4747

4848

4949
BYTES_PER_MIB = 1024 * 1024
50-
DEFAULT_MAX_UPLOAD_SIZE_MIB = 100
51-
MAX_UPLOAD_SIZE = DEFAULT_MAX_UPLOAD_SIZE_MIB * BYTES_PER_MIB
50+
DEFAULT_MAX_UPLOAD_SIZE_MIB = None
51+
MAX_UPLOAD_SIZE = None
5252

5353
try:
5454
CONNECTION_ERRORS = (ConnectionResetError, ConnectionAbortedError, BrokenPipeError)
@@ -124,6 +124,8 @@ def do_POST(self):
124124
f.close()
125125

126126
def is_upload_too_large(self):
127+
if self.max_upload_size is None:
128+
return False
127129
content_length = self.headers.get('content-length')
128130
if not content_length:
129131
return False
@@ -149,7 +151,7 @@ def deal_post_data(self):
149151
return False, "Invalid content-length header"
150152
if remain_bytes < 0:
151153
return False, "Invalid content-length header"
152-
if remain_bytes > self.max_upload_size:
154+
if self.max_upload_size is not None and remain_bytes > self.max_upload_size:
153155
return False, "Upload exceeds the %d byte limit" % self.max_upload_size
154156

155157
remain_bytes_value = [remain_bytes]
@@ -443,7 +445,7 @@ def positive_int(value):
443445
def _argparse():
444446
parser = argparse.ArgumentParser()
445447
parser.add_argument('--bind', '-b', metavar='ADDRESS', default='127.0.0.1', help='Specify alternate bind address [default: 127.0.0.1]')
446-
parser.add_argument('--max-upload-size', metavar='MIB', default=DEFAULT_MAX_UPLOAD_SIZE_MIB, type=positive_int, help='Maximum upload request size in MiB [default: 100]')
448+
parser.add_argument('--max-upload-size', metavar='MIB', default=DEFAULT_MAX_UPLOAD_SIZE_MIB, type=positive_int, help='Maximum upload request size in MiB [default: unlimited]')
447449
parser.add_argument('--version', '-v', action='version', version=__version__)
448450
parser.add_argument('port', action='store', default=8000, type=int, nargs='?', help='Specify alternate port [default: 8000]')
449451
return parser.parse_args()
@@ -452,7 +454,10 @@ def main():
452454
args = _argparse()
453455
# print(args)
454456
server_address = (args.bind, args.port)
455-
SimpleHTTPRequestHandler.max_upload_size = args.max_upload_size * BYTES_PER_MIB
457+
if args.max_upload_size is None:
458+
SimpleHTTPRequestHandler.max_upload_size = None
459+
else:
460+
SimpleHTTPRequestHandler.max_upload_size = args.max_upload_size * BYTES_PER_MIB
456461
signal.signal(signal.SIGINT, signal_handler)
457462
signal.signal(signal.SIGTERM, signal_handler)
458463
httpd = ThreadingHTTPServer(server_address, SimpleHTTPRequestHandler)

‎tests/test_simple_http_server.py‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def test_default_bind_is_localhost(self):
199199
sys.argv = old_argv
200200
self.assertEqual(args.bind, "127.0.0.1")
201201
self.assertEqual(args.port, 8000)
202-
self.assertEqual(args.max_upload_size, 100)
202+
self.assertIsNone(args.max_upload_size)
203203

204204
def test_custom_max_upload_size(self):
205205
old_argv = sys.argv
@@ -242,12 +242,21 @@ def raise_disconnect(_self):
242242

243243

244244
class UploadLimitTests(unittest.TestCase):
245-
def test_large_upload_is_reported_as_too_large(self):
245+
def test_upload_size_is_unlimited_by_default(self):
246246
handler = simple_http_server.SimpleHTTPRequestHandler.__new__(
247247
simple_http_server.SimpleHTTPRequestHandler
248248
)
249-
handler.headers = {'content-length': str(simple_http_server.MAX_UPLOAD_SIZE + 1)}
250-
handler.max_upload_size = simple_http_server.MAX_UPLOAD_SIZE
249+
handler.headers = {'content-length': str(1024 * 1024 * 1024 * 10)}
250+
handler.max_upload_size = None
251+
252+
self.assertFalse(handler.is_upload_too_large())
253+
254+
def test_configured_large_upload_is_reported_as_too_large(self):
255+
handler = simple_http_server.SimpleHTTPRequestHandler.__new__(
256+
simple_http_server.SimpleHTTPRequestHandler
257+
)
258+
handler.headers = {'content-length': str((100 * simple_http_server.BYTES_PER_MIB) + 1)}
259+
handler.max_upload_size = 100 * simple_http_server.BYTES_PER_MIB
251260

252261
self.assertTrue(handler.is_upload_too_large())
253262

0 commit comments

Comments
 (0)