苦练Python第71天:一行代码就搭出服务器?别眨眼,http.server真有这么爽!

前言

大家好,我是 倔强青铜三 。欢迎关注我,微信公众号: 倔强青铜三。点赞、收藏、关注,一键三连!

欢迎来到 苦练Python第 71 天

今天我们来学习python标准库中的http.server库。

想用Python快速搭建一个HTTP服务器?

不用装Flask、不用搞Django,更不用碰Nginx,Python自带的http.server模块就能帮你搞定!

它虽然不是为生产环境准备的"重型武器",但在本地开发、接口调试、临时文件共享等场景下,简直不要太方便。

一、基础概念

1.1 HTTP 协议 30 秒速记

  • 请求/响应模型:客户端 → 请求 → 服务器 → 响应 → 客户端
  • 常见方法:GET(读)、POST(写)、PUT、DELETE...
  • 状态码:200 OK、404 Not Found、500 Internal Server Error...

1.2 Python http.server 的定位

官方文档一句话总结:

"A simple HTTP server for development and testing."

轻到没朋友,不适合生产,但本地调试、局域网文件分享爽到飞起。


二、核心类与模块结构

2.1 HTTPServer 类

位于 http.server.HTTPServer,只做三件事:

  • 监听端口
  • 接收连接
  • 把连接丢给"请求处理器"

构造函数签名:

python 复制代码
HTTPServer(server_address, RequestHandlerClass)

2.2 BaseHTTPRequestHandler 类

生命周期钩子:

  1. setup() 准备环境
  2. handle() 真正干活(如 do_GET()
  3. finish() 清理现场

常用属性:

  • self.client_address 客户端地址
  • self.command 请求方法
  • self.path 请求路径
  • self.headers 请求头(类似 email.message.EmailMessage

三、基础功能实现

3.1 单线程"Hello World"服务器

文件 hello.py

python 复制代码
from http.server import HTTPServer, BaseHTTPRequestHandler

class HelloHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        body = b'Hello from http.server!\n'
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain; charset=utf-8')
        self.send_header('Content-Length', str(len(body)))
        self.end_headers()
        self.wfile.write(body)

if __name__ == '__main__':
    server = HTTPServer(('localhost', 8000), HelloHandler)
    print('Serving on http://localhost:8000/  (Ctrl+C to stop)')
    server.serve_forever()

运行结果(终端):

vbnet 复制代码
Serving on http://localhost:8000/  (Ctrl+C to stop)
127.0.0.1 - - [21/Aug/2025 15:42:03] "GET / HTTP/1.1" 200 -

浏览器访问效果:

页面显示 Hello from http.server!


3.2 解析 GET 路径与查询参数

文件 echo_get.py

python 复制代码
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs

class EchoGetHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        parsed = urlparse(self.path)
        params = parse_qs(parsed.query)
        body = f'path={parsed.path}\nparams={params}\n'.encode()
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain; charset=utf-8')
        self.end_headers()
        self.wfile.write(body)

if __name__ == '__main__':
    HTTPServer(('localhost', 8001), EchoGetHandler).serve_forever()

运行结果(终端):

css 复制代码
127.0.0.1 - - [21/Aug/2025 15:43:10] "GET /foo?a=1&b=2 HTTP/1.1" 200 -

浏览器访问 http://localhost:8001/foo?a=1&b=2 页面返回:

ini 复制代码
path=/foo
params={'a': ['1'], 'b': ['2']}

3.3 处理 POST(表单 & JSON)

文件 echo_post.py

python 复制代码
import json
from http.server import HTTPServer, BaseHTTPRequestHandler

class EchoPostHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0))
        body_bytes = self.rfile.read(length)
        try:
            data = json.loads(body_bytes)
        except Exception:
            data = body_bytes.decode()

        resp = json.dumps({'received': data}).encode()
        self.send_response(200)
        self.send_header('Content-Type', 'application/json; charset=utf-8')
        self.end_headers()
        self.wfile.write(resp)

if __name__ == '__main__':
    HTTPServer(('localhost', 8002), EchoPostHandler).serve_forever()

运行结果(终端):

arduino 复制代码
127.0.0.1 - - [21/Aug/2025 15:44:31] "POST / HTTP/1.1" 200 -

使用 curl 测试:

bash 复制代码
curl -X POST http://localhost:8002/ -H "Content-Type: application/json" -d '{"msg":"hi"}'

返回:

json 复制代码
{"received":{"msg":"hi"}}

四、静态文件服务

4.1 一行命令托管当前目录

终端直接敲:

bash 复制代码
python -m http.server 8003

运行结果:

csharp 复制代码
Serving HTTP on 0.0.0.0 port 8003 (http://0.0.0.0:8003/) ...
127.0.0.1 - - [21/Aug/2025 15:45:55] "GET / HTTP/1.1" 200 -

浏览器访问即可浏览目录或文件。

4.2 代码方式自定义根目录

文件 static_custom.py

python 复制代码
from http.server import HTTPServer, SimpleHTTPRequestHandler
import os

web_dir = os.path.join(os.path.dirname(__file__), 'public')
os.chdir(web_dir)  # 切换工作目录

server = HTTPServer(('localhost', 8004), SimpleHTTPRequestHandler)
print(f'Serving files from {web_dir}')
server.serve_forever()

运行结果:

csharp 复制代码
Serving files from /Users/xxx/demo/public
127.0.0.1 - - [21/Aug/2025 15:47:12] "GET /index.html HTTP/1.1" 200 -

五、多线程与性能优化

5.1 ThreadingHTTPServer 登场

文件 thread_server.py

python 复制代码
from http.server import ThreadingHTTPServer, SimpleHTTPRequestHandler

server = ThreadingHTTPServer(('localhost', 8005), SimpleHTTPRequestHandler)
print('Threading server on http://localhost:8005/')
server.serve_forever()

运行结果:

csharp 复制代码
Threading server on http://localhost:8005/
127.0.0.1 - - [21/Aug/2025 15:48:22] "GET /large.zip HTTP/1.1" 200 -

多线程可同时处理多个下载,但仍是 I/O 阻塞,高并发请上专业 WSGI。


六、请求处理扩展

6.1 自定义 404 页面

文件 custom_404.py

python 复制代码
from http.server import HTTPServer, BaseHTTPRequestHandler

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b'Home sweet home')
        else:
            self.send_error(404, 'Custom 404: Nothing here')

server = HTTPServer(('localhost', 8006), MyHandler)
server.serve_forever()

运行结果(访问不存在的 /xyz):

arduino 复制代码
127.0.0.1 - - [21/Aug/2025 15:49:30] "GET /xyz HTTP/1.1" 404 -

浏览器显示:

vbnet 复制代码
Error 404: Custom 404: Nothing here

七、高级特性

7.1 极简路由系统

文件 mini_router.py

python 复制代码
import re, json
from http.server import HTTPServer, BaseHTTPRequestHandler

class RouterHandler(BaseHTTPRequestHandler):
    routes = [
        (re.compile(r'^/api/time$'), 'handle_time'),
        (re.compile(r'^/api/add/(\d+)/(\d+)$'), 'handle_add'),
    ]

    def do_GET(self):
        for pattern, method in self.routes:
            m = pattern.match(self.path)
            if m:
                getattr(self, method)(*m.groups())
                return
        self.send_error(404)

    def handle_time(self):
        import datetime
        self.send_json({'time': str(datetime.datetime.now())})

    def handle_add(self, a, b):
        self.send_json({'sum': int(a) + int(b)})

    def send_json(self, obj):
        body = json.dumps(obj).encode()
        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(body)

server = HTTPServer(('localhost', 8007), RouterHandler)
server.serve_forever()

运行结果:

css 复制代码
127.0.0.1 - - [21/Aug/2025 15:51:00] "GET /api/time HTTP/1.1" 200 -
127.0.0.1 - - [21/Aug/2025 15:51:05] "GET /api/add/3/4 HTTP/1.1" 200 -

浏览器访问 /api/add/3/4 返回:

json 复制代码
{"sum":7}

八、安全与生产注意事项

  • 默认无认证、无 HTTPS、无限制上传大小。
  • 不要暴露在公网!
  • 生产上请用 Nginx + Gunicorn/uWSGI + Flask/Django。

九、实战项目(可跑代码)

9.1 RESTful TODO API(极简版)

文件 todo_api.py(仅内存存储):

python 复制代码
import json, uuid
from http.server import HTTPServer, BaseHTTPRequestHandler

todos = {}

class TodoHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_json(list(todos.values()))

    def do_POST(self):
        data = self.read_json()
        tid = str(uuid.uuid4())
        todos[tid] = {'id': tid, 'task': data['task'], 'done': False}
        self.send_json(todos[tid], 201)

    def do_DELETE(self):
        tid = self.path.split('/')[-1]
        todos.pop(tid, None)
        self.send_response(204)
        self.end_headers()

    def read_json(self):
        length = int(self.headers.get('Content-Length', 0))
        return json.loads(self.rfile.read(length))

    def send_json(self, obj, status=200):
        body = json.dumps(obj).encode()
        self.send_response(status)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(body)

server = HTTPServer(('localhost', 8008), TodoHandler)
print('TODO API on http://localhost:8008/')
server.serve_forever()

运行结果(终端):

csharp 复制代码
TODO API on http://localhost:8008/
127.0.0.1 - - [21/Aug/2025 15:52:33] "POST / HTTP/1.1" 201 -
127.0.0.1 - - [21/Aug/2025 15:52:40] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Aug/2025 15:52:46] "DELETE /123... HTTP/1.1" 204 -

9.2 文件上传服务(multipart/form-data)

文件 upload_server.py

python 复制代码
import cgi, os, tempfile
from http.server import HTTPServer, BaseHTTPRequestHandler

class UploadHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        html = b'''
        <form method="POST" enctype="multipart/form-data">
          <input name="file" type="file"/>
          <input type="submit"/>
        </form>
        '''
        self.send_response(200)
        self.send_header('Content-Type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(html)

    def do_POST(self):
        form = cgi.FieldStorage(fp=self.rfile, headers=self.headers,
                                environ={'REQUEST_METHOD': 'POST'})
        if 'file' in form and form['file'].filename:
            with tempfile.NamedTemporaryFile(delete=False, dir='.') as f:
                f.write(form['file'].file.read())
                saved = f.name
            body = f'Uploaded to {saved}'.encode()
        else:
            body = b'No file'
        self.send_response(200)
        self.end_headers()
        self.wfile.write(body)

server = HTTPServer(('localhost', 8009), UploadHandler)
print('Upload at http://localhost:8009/')
server.serve_forever()

运行结果:

arduino 复制代码
Upload at http://localhost:8009/
127.0.0.1 - - [21/Aug/2025 15:54:00] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Aug/2025 15:54:05] "POST / HTTP/1.1" 200 -

浏览器看到一个上传表单,选择文件后服务器保存到当前目录,并返回文件名。


结语

今天你已从零手敲 HTTP 服务器到能跑 RESTful API + 文件上传。
切记http.server 只是开发玩具,线上请交给专业选手。

最后感谢阅读!欢迎关注我,微信公众号: 倔强青铜三
点赞、收藏、关注 ,一键三连!!

欢迎 点击 【👍喜欢作者】 按钮进行 打赏💰💰,请我喝一杯咖啡☕️!

相关推荐
倔强青铜三3 小时前
苦练Python第70天:征服网络请求!揭开urllib.request的神秘面纱
人工智能·python·面试
倔强青铜三3 小时前
苦练Python第72天:colorsys 模块 10 分钟入门,让你的代码瞬间“好色”!
人工智能·python·面试
MicroTech20253 小时前
MLGO微算法科技发布多用户协同推理批处理优化系统,重构AI推理服务效率与能耗新标准
人工智能·科技·算法
说私域3 小时前
互联网企业外化能力与实体零售融合:基于定制开发开源AI智能名片S2B2C商城小程序的实践探索
人工智能·开源·零售
沫儿笙3 小时前
FANUC发那科焊接机器人薄板焊接节气
人工智能·机器人
IT_陈寒3 小时前
震惊!我用JavaScript实现了Excel的这5个核心功能,同事直呼内行!
前端·人工智能·后端
淞宇智能科技3 小时前
固态电池五大核心设备全解析
大数据·人工智能·自动化
AndrewHZ4 小时前
【图像处理基石】多波段图像融合算法入门:从概念到实践
图像处理·人工智能·算法·图像融合·遥感图像·多波段·变换域
胖哥真不错4 小时前
Python基于PyTorch实现多输入多输出进行BP神经网络回归预测项目实战
pytorch·python·毕业设计·论文·毕设·多输入多输出·bp神经网络回归预测