5.9 KiB
HTTP Mock Server for Integration Tests
本目录包å<EFBFBD>«ç”¨äº?HttpdnsNWHTTPClient 集æˆ<C3A6>测试çš?HTTP/HTTPS mock server,用于替ä»?httpbin.orgã€?
为什么需�Mock Server�
- **å<>¯é<C2AF> æ€?*: httpbin.org 在高并å<C2B6>‘测试下表现ä¸<C3A4>稳定,ç»<C3A7>常返回é<C5BE>žé¢„期çš?HTTP 状æ€<C3A6>ç <C3A7>(如 429 Too Many Requestsï¼?
- 速度: 本地æœ<C3A6>务器å“<C3A5>åº”æ›´å¿«ï¼Œç¼©çŸæµ‹è¯•执行时间
- 离线测试: æ— éœ€ç½‘ç»œè¿žæŽ¥å<C2A5>³å<C2B3>¯è¿<C3A8>行集æˆ<C3A6>测试
- **å<>¯æŽ§æ€?*: 完全掌控测试环境,便于调试和å¤<C3A5>现问题
快速开�
1. å<>¯åЍ Mock Server
# 进入测试目录
cd TrustHttpDNSTests/Network
# å<>¯åЍæœ<C3A6>åŠ¡å™¨ï¼ˆæ— éœ€ sudo æ<>ƒé™<C3A9>,使用é<C2A8>žç‰¹æ<C2B9>ƒç«¯å<C2AF>£ï¼?
python3 mock_server.py
注æ„<EFBFBD>:
- **æ— éœ€ root æ<>ƒé™<C3A9>**(使用é<C2A8>žç‰¹æ<C2B9>ƒç«¯å<C2AF>£ 11080/11443-11446ï¼?
- 首次è¿<EFBFBD>行会自动生æˆ<EFBFBD>自ç¾å<EFBFBD><EFBFBD>è¯<EFBFBD>书 (
server.pem) - �
Ctrl+Cå<>œæ¢æœ<C3A6>务å™?
2. è¿<C3A8>行集æˆ<C3A6>测试
在å<EFBFBD>¦ä¸€ä¸ªç»ˆç«¯çª—å<EFBFBD>?
cd ~/Project/iOS/Trust-ios-sdk-httpdns
# è¿<C3A8>行所有集æˆ<C3A6>测è¯?
xcodebuild test \
-workspace TrustHttpDNS.xcworkspace \
-scheme TrustHttpDNSTests \
-destination 'platform=iOS Simulator,name=iPhone 15' \
-only-testing:TrustHttpDNSTests/HttpdnsNWHTTPClientIntegrationTests
# è¿<C3A8>行å<C592>•个测试
xcodebuild test \
-workspace TrustHttpDNS.xcworkspace \
-scheme TrustHttpDNSTests \
-destination 'platform=iOS Simulator,name=iPhone 15' \
-only-testing:TrustHttpDNSTests/HttpdnsNWHTTPClientIntegrationTests/testConcurrency_ParallelRequestsSameHost_AllSucceed
支æŒ<EFBFBD>çš?Endpoints
Mock server 实现了以�httpbin.org 兼容�endpoints:
| Endpoint | 功能 | 示例 |
|---|---|---|
GET /get |
返回请求信æ<EFBFBD>¯ï¼ˆheaders, args, originï¼? | http://127.0.0.1:11080/get |
GET /status/{code} |
返回指定状æ€<EFBFBD>ç <EFBFBD>ï¼?00-599ï¼? | http://127.0.0.1:11080/status/404 |
GET /stream-bytes/{n} |
返回 chunked ç¼–ç <C3A7>çš?N å—节数æ<C2B0>® | http://127.0.0.1:11080/stream-bytes/1024 |
GET /delay/{seconds} |
延迟指定秒数å<EFBFBD>Žè¿”回(最å¤?0秒) | http://127.0.0.1:11080/delay/5 |
GET /headers |
返回所有请求头� | http://127.0.0.1:11080/headers |
GET /uuid |
返回éš<EFBFBD>机 UUID | http://127.0.0.1:11080/uuid |
GET /user-agent |
返回 User-Agent 头部 | http://127.0.0.1:11080/user-agent |
端å<EFBFBD>£é…<EFBFBD>ç½®:
- HTTP:
127.0.0.1:11080 - HTTPS:
127.0.0.1:11443,11444,11445,11446ï¼?个端å<C2AF>£ç”¨äºŽæµ‹è¯•è¿žæŽ¥æ± éš”ç¦»ï¼?
所æœ?endpoints åœ?HTTP å’?HTTPS 端å<C2AF>£ä¸Šå<C5A0>‡å<E280A1>¯è®¿é—®ã€?
实现细节
æž¶æž„
- **HTTP æœ<C3A6>务å™?*: 监å<E28098>¬
127.0.0.1:11080 - **HTTPS æœ<C3A6>务å™?*: 监å<E28098>¬
127.0.0.1:11443,11444,11445,11446ï¼?个端å<C2AF>£ï¼Œä½¿ç”¨è‡ªç¾å<C2BE><C3A5>è¯<C3A8>书) - **多端å<C2AF>£ç›®çš?*: æµ‹è¯•è¿žæŽ¥æ± çš„ç«¯å<C2AF>£éš”离机制,确ä¿<C3A4>ä¸<C3A4>å<EFBFBD>Œç«¯å<C2AF>£ä½¿ç”¨ç‹¬ç«‹çš„连接æ±?
- å¹¶å<EFBFBD>‘模型: 多线程(
ThreadingMixIn),支æŒ<EFBFBD>高并å<EFBFBD>‘请æ±?
TLS è¯<C3A8>书
- 自动生æˆ<EFBFBD>自ç¾å<EFBFBD><EFBFBD>è¯<EFBFBD>书(RSA 2048ä½<C3A4>,有效æœ?365 天)
- CN (Common Name):
localhost - è¯<EFBFBD>书文件:
server.pem(å<EFBFBD>Œæ—¶åŒ…å<EFBFBD>«å¯†é’¥å’Œè¯<EFBFBD>书ï¼?
é‡<EFBFBD>è¦<EFBFBD>: 集æˆ<C3A6>测试通过环境å<C692>˜é‡<C3A9> HTTPDNS_SKIP_TLS_VERIFY=1 跳过 TLS 验è¯<C3A8>ï¼Œè¿™æ˜¯å®‰å…¨çš„ï¼Œå› ä¸ºï¼š
- 仅在测试环境生效
- ä¸<EFBFBD>å½±å“<EFBFBD>生产代ç ?
- 连接é™<EFBFBD>制为本åœ?loopback (127.0.0.1)
å“<EFBFBD>åº”æ ¼å¼<EFBFBD>
所æœ?JSON å“<C3A5>应é<E2809D>µå¾ª httpbin.org æ ¼å¼<C3A5>,例å¦?
{
"args": {},
"headers": {
"Host": "127.0.0.1",
"User-Agent": "HttpdnsNWHTTPClient/1.0"
},
"origin": "127.0.0.1",
"url": "GET /get"
}
Chunked ç¼–ç <C3A7>å“<C3A5>应示例 (/stream-bytes/10):
HTTP/1.1 200 OK
Transfer-Encoding: chunked
a
XXXXXXXXXX
0
故障排除
端å<EFBFBD>£å·²è¢«å<EFBFBD> 用
错误信æ<EFBFBD>¯:
âœ?端å<C2AF>£ 80 已被å<C2AB> 用,请关é—å<C2AD> 用端å<C2AF>£çš„进程或使用其他端å<C2AF>£
解决方法:
- 查找å<EFBFBD> 用进程:
sudo lsof -i :80
sudo lsof -i :443
- 终æ¢å<EFBFBD> 用进程:
sudo kill -9 <PID>
- 或修æ”?mock_server.py 使用其他端å<C2AF>£:
# 修改端å<C2AF>£å<C2A3>·ï¼ˆå<CB86>Œæ—¶éœ€è¦<C3A8>更新测试代ç <C3A7>ä¸çš?URLï¼?
run_http_server(port=8080)
run_https_server(port=8443)
缺少 OpenSSL
错误信æ<EFBFBD>¯:
�未找�openssl 命令,请安装 OpenSSL
解决方法:
# macOS (通常已预�
brew install openssl
# Ubuntu/Debian
sudo apt-get install openssl
# CentOS/RHEL
sudo yum install openssl
æ<EFBFBD>ƒé™<EFBFBD>被拒ç»?
错误信æ<EFBFBD>¯:
âœ?错误: 需è¦?root æ<>ƒé™<C3A9>以绑å®?80/443 端å<C2AF>£
解决方法:
必须使用 sudo è¿<C3A8>行:
sudo python3 mock_server.py
切æ<EFBFBD>¢å›?httpbin.org
如需使用真实çš?httpbin.org 进行测试(例如验è¯<C3A8>兼容性):
- 编辑
HttpdnsNWHTTPClientIntegrationTests.m - 将所�
127.0.0.1替æ<C2BF>¢å›?httpbin.org - 注释æŽ?setUp/tearDown ä¸çš„环境å<C692>˜é‡<C3A9>设置
å¼€å<EFBFBD>‘与扩展
æ·»åŠ æ–?Endpoint
åœ?mock_server.py çš?MockHTTPHandler.do_GET() æ–¹æ³•ä¸æ·»åŠ?
def do_GET(self):
path = urlparse(self.path).path
if path == '/your-new-endpoint':
self._handle_your_endpoint()
# ... å…¶ä»– endpoints
def _handle_your_endpoint(self):
"""处ç<E2809E>†è‡ªå®šä¹?endpoint"""
data = {'custom': 'data'}
self._send_json(200, data)
调试模å¼<EFBFBD>
å<EFBFBD>–消注释 log_message 方法以å<C2A5>¯ç”¨è¯¦ç»†æ—¥å¿?
def log_message(self, format, *args):
print(f"[{self.address_string()}] {format % args}")
æŠ€æœ¯æ ˆ
- Python 3.7+ (æ ‡å‡†åº“ï¼Œæ— éœ€é¢<C3A9>外ä¾<C3A4>èµ–)
- http.server: HTTP æœ<C3A6>务器实çŽ?
- ssl: TLS/SSL 支æŒ<C3A6>
- socketserver.ThreadingMixIn: 多线程并å<C2B6>?
安全注æ„<EFBFBD>事项
- **仅用于测è¯?*: æ¤æœ<C3A6>务器设计用于本地测试,ä¸<C3A4>适å<E2809A>ˆç”Ÿäº§çŽ¯å¢ƒ
- **自ç¾å<C2BE><C3A5>è¯<C3A8>ä¹?*: HTTPS 使用ä¸<C3A4>å<EFBFBD>—信任的自ç¾å<C2BE><C3A5>è¯<C3A8>书
- **æ— èº«ä»½éªŒè¯?*: ä¸<C3A4>实现任何身份验è¯<C3A8>机åˆ?
- 本地绑定: æœ<C3A6>务器仅绑定åˆ?
127.0.0.1,ä¸<EFBFBD>接å<EFBFBD>—外部连接
**最å<E282AC>Žæ›´æ–?: 2025-11-01 **维护è€?: Claude Code