
简介这是一款面向前端开发者与接口调试人员的Http自动回复请求软件即一键Mock工具主要解决后端接口尚未完成时前端开发受阻、传统Mock服务器搭建繁琐的问题。软件提供直观界面可快速创建、编辑和管理模拟接口支持依据接口文档配置模拟数据并一键启动服务无需外部插件即可完成接口即时调试与测试。资源包共33个文件以15个dll动态库、10个xml配置说明、2个pdf使用与更新文档、2个log日志、2个config配置文件及1个db数据库、1个exe主程序为主压缩包约5.36MB运行于Win10 x64依赖.NET Framework 4.6.2。目前已有491人学习下载。借助该工具读者可省去搭建Mock服务的繁琐流程快速获得可运行的接口模拟环境结合使用说明与更新文档能高效完成接口联调、模拟数据测试与项目开发任务。1. Http自动回复请求软件一键Mock工具到底在解决什么联调接口时最怕的不是报错而是对面服务根本没准备好。前端页面写完了后端接口还在联调环境里挂着第三方支付回调地址只能填公网可访问的域名测试同学想复现一个「订单超时未支付」的状态却要手动改数据库。这时候一个能拦截 HTTP 请求、按规则返回预设响应的 Http自动回复请求软件就是整个研发流程里的止血带。一键Mock工具的核心价值不在于「造假数据」而在于把「依赖外部服务」这件事从关键路径上摘出去让前端、测试、甚至后端自己都能独立推进。这类工具通常工作在两种模式一种是本地起一个 HTTP 服务把请求地址从真实域名改成127.0.0.1:端口另一种是作为中间层通过配置 hosts 或代理把流量引过来。前者适合新项目从零搭 Mock后者适合已有项目做局部替换。它解决的问题很具体接口文档还没定稿时先跑通页面逻辑、第三方回调无法在本地触发时模拟回调、压测时避免打挂真实下游。适合的人群包括前端开发、测试工程师、以及需要做本地联调的后端。理解 http协议 的基本结构——请求行、请求头、请求体、响应状态码——是用好这类工具的前提因为 Mock 的本质就是「按你写的规则伪造一个符合协议规范的响应」。2. 从零搭一个能用的 Mock 服务路由、匹配与响应体2.1 为什么选轻量 HTTP 服务而不是重型框架很多人第一反应是上 Spring Boot 或 Express 写几个接口但 Mock 工具的需求和业务服务完全不同它不需要数据库连接池、不需要事务、不需要复杂的依赖注入。常见做法是用 Python 的http.server模块或 Node 的http模块起一个单文件服务启动时间控制在 1 秒以内改完规则立即生效。重型框架的启动开销和配置复杂度反而会成为负担尤其是当你需要同时 Mock 十几个不同域名的接口时。选型的另一个维度是「规则热更新」。业务服务改代码要重启Mock 服务如果也要重启联调节奏就被打断了。所以规则最好放在外部文件里服务监听文件变化后自动重载。下面是一个最小可用的 Python 实现用标准库完成路由匹配和 JSON 响应不引入任何第三方依赖。# mock_server.py import json import re from http.server import BaseHTTPRequestHandler, HTTPServer # 规则文件每条规则包含 method、path 正则、status、headers、body with open(rules.json, r, encodingutf-8) as f: RULES json.load(f) class MockHandler(BaseHTTPRequestHandler): def _match(self, method, path): for rule in RULES: if rule[method] ! method: continue # 用正则匹配路径支持 /api/user/\d 这类动态段 if re.fullmatch(rule[path], path): return rule return None def _respond(self, rule): status rule.get(status, 200) body json.dumps(rule.get(body, {}), ensure_asciiFalse).encode(utf-8) self.send_response(status) # 默认返回 JSONContent-Type 必须显式设置 self.send_header(Content-Type, rule.get(content_type, application/json; charsetutf-8)) self.send_header(Content-Length, str(len(body))) for k, v in rule.get(headers, {}).items(): self.send_header(k, v) self.end_headers() self.wfile.write(body) def do_GET(self): rule self._match(GET, self.path) if rule: self._respond(rule) else: self.send_error(404, No mock rule matched) def do_POST(self): length int(self.headers.get(Content-Length, 0)) # 读取请求体后续可按 body 内容做更细粒度匹配 _ self.rfile.read(length) rule self._match(POST, self.path) if rule: self._respond(rule) else: self.send_error(404, No mock rule matched) if __name__ __main__: server HTTPServer((0.0.0.0, 8080), MockHandler) print(Mock server running on http://0.0.0.0:8080) server.serve_forever()这段代码的逻辑很直白启动时加载rules.json每个请求进来后先按 method 过滤再用re.fullmatch匹配路径。匹配成功就按规则里的 status、headers、body 组装响应。参数说明上path字段写正则表达式比如/api/order/\d能匹配/api/order/123content_type不填时默认 JSON如果 Mock 的是文件下载或 XML 接口必须手动指定。headers字段用来模拟自定义响应头比如分页接口里的X-Total-Count。2.2 规则文件怎么写才能覆盖真实场景规则文件的结构决定了 Mock 的灵活度。一个常见的误区是只按路径匹配结果同一个路径在不同参数下需要返回不同结果时就抓瞎。比如/api/user?roleadmin和/api/user?roleguest应该返回不同权限的数据。解决办法是在规则里增加query字段做键值对匹配或者把整个 URL 包括查询串一起写进正则。[ { method: GET, path: /api/user, query: {role: admin}, status: 200, body: {id: 1, name: admin, permissions: [read, write]} }, { method: GET, path: /api/user, query: {role: guest}, status: 200, body: {id: 2, name: guest, permissions: [read]} }, { method: POST, path: /api/order/create, status: 201, headers: {Location: /api/order/1001}, body: {order_id: 1001, status: created} } ]这里query字段的匹配逻辑需要在代码里补上解析self.path中的查询串和规则里的query做包含判断。注意POST请求的 201 状态码和Location响应头这是 RESTful 接口的常见约定Mock 时如果漏掉前端可能拿不到跳转地址。另一个细节是Content-Type如果接口返回的是application/xml或text/plain必须在规则里显式声明否则前端按 JSON 解析会直接抛异常。2.3 启动、验证与端口冲突处理服务写完后用python mock_server.py启动默认监听 8080。验证时不要只开浏览器访问因为浏览器会缓存而且 GET 请求的调试信息不如命令行直观。用curl带完整参数请求能看到响应头和状态码# 验证 GET 规则匹配 curl -i http://127.0.0.1:8080/api/user?roleadmin # 验证 POST 规则带 JSON body curl -i -X POST http://127.0.0.1:8080/api/order/create \ -H Content-Type: application/json \ -d {product_id: 5, count: 2}-i参数让 curl 输出响应头方便确认Content-Type和自定义头是否正确。如果返回 404先检查rules.json里的path正则是否写成了re.fullmatch能匹配的形式——/api/user不会匹配/api/user?roleadmin因为查询串在self.path里是包含的。端口冲突是另一个高频问题8080 常被其他服务占用启动时报Address already in use时换 9090 或 18080 即可。如果想让局域网内其他机器访问把HTTPServer的绑定地址从127.0.0.1改成0.0.0.0同时确认防火墙放行对应端口。3. 请求匹配的进阶玩法动态参数、延迟与状态码3.1 路径参数与正则捕获组真实接口里路径参数很常见比如/api/order/1001/detail和/api/order/1002/detail应该返回不同订单号的数据。如果为每个订单号写一条规则规则文件会膨胀到无法维护。正确做法是用正则捕获组提取参数然后在响应体里动态替换。Python 的re.fullmatch返回的 match 对象可以通过group(1)拿到捕获内容。# 在 _match 方法中返回 match 对象而非布尔值 def _match(self, method, path): for rule in RULES: if rule[method] ! method: continue m re.fullmatch(rule[path], path) if m: return rule, m return None, None # 在 _respond 中做模板替换 def _respond(self, rule, match): body_str json.dumps(rule.get(body, {}), ensure_asciiFalse) # 把 body 里的 {{1}} 替换成第一个捕获组的内容 for i, g in enumerate(match.groups(), start1): body_str body_str.replace({{%d}} % i, g) body body_str.encode(utf-8) # ... 后续发送逻辑不变规则文件里把path写成/api/order/(\d)/detailbody里写{order_id: {{1}}, status: paid}。这样请求/api/order/1001/detail时返回的order_id就是1001。注意替换顺序要从大到小避免{{1}}被{{10}}的前缀误伤不过捕获组一般不会超过个位数实际影响很小。3.2 模拟网络延迟和超时前端做 loading 状态和超时重试逻辑时Mock 服务如果秒回这些分支根本跑不到。所以需要能人为制造延迟。在_respond里加一个time.sleep延迟时间从规则里读import time def _respond(self, rule, match): delay rule.get(delay_ms, 0) if delay 0: time.sleep(delay / 1000.0) # ... 后续发送逻辑规则里加delay_ms: 3000就能模拟 3 秒延迟。测试超时逻辑时把延迟设成比前端timeout配置更大的值比如前端设 5 秒超时Mock 延迟设 8000 毫秒就能稳定触发超时分支。注意time.sleep会阻塞当前线程如果并发请求多需要换成多线程的ThreadingHTTPServer否则一个慢请求会把后续请求全部堵住。3.3 状态码与错误响应的覆盖只 Mock 200 成功响应是不够的接口的异常分支才是 bug 高发区。401 未授权、403 禁止访问、500 服务端错误、502 网关错误这些都需要能按需触发。规则里的status字段直接控制状态码配合body返回错误信息{ method: GET, path: /api/protected, status: 401, headers: {WWW-Authenticate: Bearer}, body: {error: unauthorized, message: token expired} }前端拿到 401 后应该跳转登录页或刷新 token这个逻辑在真实接口不可控的时候很难验证。用 Mock 规则把 401 稳定复现出来前端同学就能安心写拦截器。500 错误同理返回一个{error: internal server error}的 JSON 体观察前端是否有兜底提示。注意WWW-Authenticate头在 401 响应里是 HTTP 规范建议的虽然前端不一定读但加上更贴近真实服务。4. 避坑与排查Mock 服务最容易翻车的五个地方4.1 现象curl 能通浏览器请求却报 CORS 错误原因Mock 服务没有返回跨域响应头。浏览器对跨域请求会先发OPTIONS预检Mock 服务如果没有处理do_OPTIONS预检直接 501后续真实请求就不会发出。解决在 Handler 里增加do_OPTIONS方法返回 204 并带上Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers三个头。如果不想区分环境直接在_respond里给所有响应都加上Access-Control-Allow-Origin: *但注意带 cookie 的请求不能使用通配符。4.2 现象POST 请求的 body 读不到规则匹配失败原因BaseHTTPRequestHandler不会自动读取请求体必须在do_POST里根据Content-Length手动读self.rfile。如果规则匹配依赖 body 内容而读取发生在匹配之后就会拿不到数据。解决把读取 body 的逻辑提到_match之前把 body 作为参数传给匹配函数。另外注意Content-Length可能不存在比如 chunked 编码需要做兼容判断缺省时按 0 处理。4.3 现象修改 rules.json 后必须重启服务才生效原因规则在模块加载时一次性读入内存后续文件变化不会触发重载。解决在_match里每次请求都重新读文件或者用os.path.getmtime判断文件修改时间变了才重读。每次请求都读文件在低并发下没问题高并发时建议加一个后台线程定时检查。更简单的做法是用watchdog库监听文件变化但会引入第三方依赖看团队接受度。4.4 现象响应中文乱码原因json.dumps默认ensure_asciiTrue会把中文转成\uXXXX转义序列虽然协议上没问题但调试时肉眼不可读。更严重的是如果Content-Type没带charsetutf-8浏览器可能按 ISO-8859-1 解析。解决json.dumps加ensure_asciiFalseContent-Type写成application/json; charsetutf-8。如果返回的是 HTML 或纯文本同样要显式声明字符集。4.5 现象并发请求时响应错乱或连接被重置原因默认的HTTPServer是单线程的一个请求处理完才处理下一个。如果某个规则配了长延迟后续请求全部排队客户端可能等不及主动断开。解决改用ThreadingHTTPServer每个请求一个线程。但要注意线程安全规则文件的重载如果发生在请求处理过程中可能读到半截文件。稳妥做法是重载时先读入临时变量确认解析成功后再替换全局引用。5. 把 Mock 工具接进日常研发流程的几个具体技巧5.1 用环境变量切换 Mock 与真实服务不要让开发同学手动改代码里的 baseURL。常见做法是在前端项目的.env.development里配VITE_API_BASEhttp://127.0.0.1:8080生产环境配真实域名。后端联调时同理把下游服务的地址抽成配置项。这样切换 Mock 只需要改环境变量不用动业务代码。如果团队用 Docker Compose可以把 Mock 服务作为一个 container 起在同一个网络里其他服务通过服务名访问连端口映射都省了。5.2 把规则文件纳入版本管理rules.json应该和代码一起提交到仓库而不是放在某个人本地。接口契约变更时先改规则文件再改业务代码规则文件就成了「可执行的接口文档」。新人拉下代码后启动 Mock 服务前端页面直接能跑不需要等后端环境。规则文件里的注释字段可以写清楚每条规则对应的需求单号或接口文档链接方便追溯。5.3 用脚本做规则文件的语法校验规则文件写错一个逗号服务启动就报 JSON 解析错误。在 CI 里加一步校验用python -m json.tool rules.json检查语法再写个简单的 schema 校验确保每条规则都有method和path字段。这样规则文件的修改不会因为低级错误阻塞联调。如果团队用 Git hooks可以在 pre-commit 里跑这个校验把问题拦在提交之前。5.4 记录请求日志用于排查Mock 服务最好把每个进来的请求 method、path、headers、body 打到日志里。当前端同学说「接口没返回我想要的」看一眼日志就知道请求有没有打到 Mock 服务、路径是否匹配、body 是否符合预期。日志格式用一行 JSON 方便后续用jq过滤。注意不要记录敏感头如Authorization的完整值打印前几个字符即可。5.5 用 http连接复用 减少联调时的连接开销如果 Mock 服务和调用方在同一台机器每次请求都新建 TCP 连接其实开销不大。但如果 Mock 服务部署在测试环境调用方在本地频繁的短连接会受网络抖动影响。在调用方开启 HTTP keep-alive让连接复用能减少握手次数。Python 的requests库用Session对象自动复用连接前端axios默认也开启 keep-alive。Mock 服务这边要确保protocol_version设为HTTP/1.1否则默认 1.0 不支持长连接。from http.server import ThreadingHTTPServer class MockServer(ThreadingHTTPServer): # 开启 HTTP/1.1 以支持 keep-alive protocol_version HTTP/1.1 if __name__ __main__: server MockServer((0.0.0.0, 8080), MockHandler) server.serve_forever()注意开启 HTTP/1.1 后每个响应必须带正确的Content-Length否则客户端会一直等连接关闭。上面的代码里已经通过send_header(Content-Length, ...)保证了这一点。如果某个响应没有 body比如 204也要显式设置Content-Length: 0。5.6 一个我踩过的坑路径匹配别用 startswith最早写匹配逻辑时图省事用path.startswith(rule[path])结果/api/user的规则把/api/user/delete也匹配了返回了错误的用户数据。后来改成re.fullmatch才解决。正则虽然写起来麻烦一点但边界清晰不会出现前缀误匹配。如果确实需要前缀匹配在规则里显式写/api/user/.*让意图更明确。这套方案我从三年前开始用中间换过语言、换过框架但核心思路没变规则外置、热更新、覆盖异常分支。每次新项目启动先把 Mock 服务跑起来前端和后端就能并行开工联调时再逐个把 Mock 规则替换成真实接口。希望帮到你。本文还有配套的精品资源点击获取