API Echo 服务
项目简介
API Echo 是一个轻量级的API测试工具服务,用于测试HTTP请求和响应。该服务可以回显请求内容,帮助开发人员调试和测试API接口。
作者 : Johnny
创建时间 : 2022年7月5日
版本: v1
技术栈
- 后端框架: Flask 2.1.2
- 开发语言: Python 3.x
- 运行端口: 9999
- 监听地址: 0.0.0.0(支持外部访问)
核心功能
1. 主要特性
- ✅ 支持多种HTTP方法(GET、POST、PUT、DELETE)
- ✅ 请求内容回显(headers、body)
- ✅ 灵活的响应配置
- ✅ 布尔值和数字状态码返回
- ✅ Web界面访问
- ✅ 请求时间记录
- ✅ JSON格式支持
2. 业务实现
2.1 请求回显服务
核心功能是将接收到的HTTP请求信息进行记录和回显,包括:
- 请求方法(GET/POST/PUT/DELETE)
- 请求URL
- 请求头(Headers)
- 请求体(Body)
- 请求时间(UTC时间)
2.2 响应内容定制
- 自定义键值对返回
- 布尔值返回控制
- 状态码数字返回
- JSON格式响应
API接口文档
基础信息
- Base URL :
http://localhost:9999 - 响应格式: JSON
接口列表
| 接口名称 | 请求方法 | 接口路径 | 说明 |
|---|---|---|---|
| 主页 | GET | / |
返回API文档页面 |
| 接收消息 | POST/GET/PUT/DELETE | /apiecho/v1/sync |
请求内容回显 |
| 设置返回值 | POST/GET/PUT/DELETE | /apiecho/v1/config/<key>/<value> |
自定义键值对返回 |
| 返回布尔值 | POST/GET/PUT/DELETE | /apiecho/v1/bool/<key>/<value> |
返回布尔值(true/false) |
| 返回状态码 | POST/GET/PUT/DELETE | /apiecho/v1/code/<code>/<num> |
返回自定义状态码 |
| GET方法 | GET | /apiecho/v1/get |
标准GET请求测试 |
| POST方法 | POST | /apiecho/v1/post |
标准POST请求测试 |
| PUT方法 | PUT | /apiecho/v1/put |
标准PUT请求测试 |
| DELETE方法 | DELETE | /apiecho/v1/delete |
标准DELETE请求测试 |
接口详细说明
1. /apiecho/v1/sync - 同步回显接口
功能: 回显所有接收到的请求信息
支持方法: POST, GET, PUT, DELETE
响应示例:
json
{
"code": 200,
"success": true,
"method": "POST",
"url": "http://localhost:9999/apiecho/v1/sync",
"time": "2026-01-15 12:00:00.123456",
"body": {
"test": "data"
}
}
特殊情况:
- 无请求体时返回:
"message": "no body" - 非JSON格式请求体时返回:
"message": "body not json"
2. /apiecho/v1/config/<key>/<value> - 配置接口
功能: 返回自定义的键值对
支持方法: POST, GET, PUT, DELETE
路径参数:
key: 自定义键名(字符串)value: 自定义值(字符串)
请求示例:
GET /apiecho/v1/config/status/success
响应示例:
json
{
"code": 200,
"method": "GET",
"url": "http://localhost:9999/apiecho/v1/config/status/success",
"time": "2026-01-15 12:00:00.123456",
"status": "success"
}
3. /apiecho/v1/bool/<key>/<value> - 布尔值接口
功能: 返回布尔类型的值
支持方法: POST, GET, PUT, DELETE
路径参数:
key: 键名(字符串)value: 布尔值(只有"true"返回true,其他均返回false)
请求示例:
POST /apiecho/v1/bool/isActive/true
响应示例:
json
{
"code": 200,
"method": "POST",
"url": "http://localhost:9999/apiecho/v1/bool/isActive/true",
"time": "2026-01-15 12:00:00.123456",
"isActive": true
}
注意事项:
- GET和DELETE方法的body参数可选
- POST和PUT方法建议传递body
4. /apiecho/v1/code/<code>/<num> - 状态码接口
功能: 返回自定义状态码的数字
支持方法: POST, GET, PUT, DELETE
路径参数:
code: 键名(字符串)num: 数字值(必须是整数)
请求示例:
GET /apiecho/v1/code/status/200
响应示例:
json
{
"success": true,
"method": "GET",
"url": "http://localhost:9999/apiecho/v1/code/status/200",
"time": "2026-01-15 12:00:00.123456",
"status": 200
}
错误响应(非数字值):
json
{
"message": "Please input number",
"success": false
}
5. /apiecho/v1/get - GET测试接口
功能: 标准GET请求测试
支持方法: GET
响应示例:
json
{
"code": 200,
"Success": true,
"method": "GET",
"data": {
"author": "hw",
"desc": "This Api for TEST!"
},
"time": "2026-01-15 12:00:00.123456"
}
6. /apiecho/v1/post - POST测试接口
功能: 标准POST请求测试(必须传递body)
支持方法: POST
请求要求: 必须包含JSON格式的请求体
响应示例:
json
{
"code": 200,
"Success": true,
"method": "POST",
"url": "http://localhost:9999/apiecho/v1/post",
"time": "2026-01-15 12:00:00.123456",
"body": {
"test": "data"
}
}
错误响应(无body):
json
{
"code": 404,
"Success": false,
"message": "Please send body"
}
7. /apiecho/v1/put - PUT测试接口
功能: 标准PUT请求测试(必须传递body)
支持方法: PUT
行为与POST接口一致
8. /apiecho/v1/delete - DELETE测试接口
功能: 标准DELETE请求测试
支持方法: DELETE
响应示例:
json
{
"code": 200,
"Success": true,
"method": "DELETE",
"data": {
"author": "hw",
"desc": "This Api for TEST!"
},
"time": "2026-01-15 12:00:00.123456"
}
项目结构
apiecho/
├── app.py # Flask应用主文件,包含所有API端点
├── apiecho.html # API文档展示页面(Web界面)
├── requirements.txt # Python依赖包列表
├── run.sh # Linux/Mac启动脚本
└── README.md # 项目文档(本文件)
源码
app.py源码
python
#!/usr/bin/env python
# coding=utf-8
__author__ = "Johnny"
__date__ = "2022/7/5 "
__description__ = "api request and response echo"
import json
import logging
from datetime import datetime
import flask
from flask import request, render_template, send_from_directory
app = flask.Flask(__name__)
logger = logging.Logger(__name__)
@app.route("/")
def as_home():
return send_from_directory('', 'apiecho.html')
@app.route("/apiecho/v1/sync", methods=["POST", "GET", "PUT", "DELETE"])
def ae_sync():
response = {'code': 200, 'success': True, 'method': request.method, "url": request.url,
'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/sync ------------------------\n"))
print("TIME: ", str(datetime.now()))
print("Method: ", request.method)
# logger.info(request.method)
print("Headers: \n\n", request.headers)
if not request.content_length:
response['message'] = "no body"
else:
try:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
except:
print("Body: \n\n", request.data)
response['message'] = "body not json"
print("\nReturn Response:\n", response)
return response
@app.route("/apiecho/v1/config/<key>/<value>", methods=["POST", "GET", "PUT", "DELETE"])
def ae_config(key, value):
response = {'code': 200, 'method': request.method, "url": request.url, 'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/config ------------------------\n"))
print("TIME: ", str(datetime.now()))
print("Method: ", request.method)
print("Headers: \n\n", request.headers)
if value:
response[key] = str(value)
else:
response['message'] = "no value"
if not request.content_length:
response['message'] = "no body"
else:
try:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
except:
print("Body: \n\n", request.data)
response['message'] = "body not json"
print("\nReturn Response: \n", response)
return response
@app.route("/apiecho/v1/bool/<key>/<value>", methods=["POST", "GET", "PUT", "DELETE"])
def ae_bool(key, value):
"""
GET DELETE body选传
POST PUT 必须传body
:param key:
:param value:
:return:
"""
response = {'code': 200, 'method': request.method, "url": request.url, 'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/bool ------------------------\n"))
print("TIME: ", str(datetime.now()))
print("Method: ", request.method)
print("Headers: \n\n", request.headers)
try:
if str(value) == 'true':
response[key] = True
else:
response[key] = False
except:
response['message'] = "value must send"
response['code'] = 404
return response
if not request.content_length:
response['message'] = "no body"
else:
try:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
except:
print("Body: \n\n", request.data)
response['message'] = "body not json"
print("\nReturn Response: \n", response)
return response
@app.route("/apiecho/v1/code/<code>/<num>", methods=["POST", "GET", "PUT", "DELETE"])
def ae_code(code, num):
"""
GET DELETE body选传
POST PUT 必须传body
:param code:
:param num:
:return:
"""
response = {'success': True, 'method': request.method, 'url': request.url, 'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/code ------------------------\n"))
print("TIME: ", str(datetime.now()))
print("Method: ", request.method)
print("Headers: \n\n", request.headers)
try:
response[code] = int(num)
except ValueError:
response['message'] = "Please input number"
response['success'] = False
return response
if not request.content_length:
response['message'] = "no body"
else:
try:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
except:
print("Body: \n\n", request.data)
response['message'] = "body not json"
print("\nReturn Response: \n", response)
return response
@app.route("/apiecho/v1/get", methods=["GET"])
def ae_get():
response = {'code': 200, 'Success': True, 'method': request.method,
'data': {"author": "hw", "desc": "This Api for TEST!"}, 'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/get ------------------------\n"))
if not request.content_length:
response['message'] = "no body"
else:
try:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
except:
print("Body: \n\n", request.data)
response['message'] = "body not json"
print("\nReturn Response: \n", response)
return response
@app.route("/apiecho/v1/post", methods=["POST"])
def ae_post():
response = {'code': 200, 'Success': True, 'method': request.method, "url": request.url,
'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/post ------------------------\n"))
try:
if request.data:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
elif request.json:
print("Body: \n\n", request.json)
response['body'] = json.loads(request.json)
except:
return {'code': 404, 'Success': False, "message": "Please send body"}
print("\nReturn Response: \n", response)
return response
@app.route("/apiecho/v1/put", methods=["PUT"])
def ae_put():
response = {'code': 200, 'Success': True, 'method': request.method, "url": request.url,
'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/put ------------------------\n"))
try:
if request.data:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
elif request.json:
print("Body: \n\n", request.json)
response['body'] = json.loads(request.json)
except:
return {'code': 404, 'Success': False, "message": "Please send body"}
print("\nReturn Response: \n", response)
return response
@app.route("/apiecho/v1/delete", methods=["DELETE"])
def ae_delete():
response = {'code': 200, 'Success': True, 'method': request.method,
'data': {"author": "hw", "desc": "This Api for TEST!"}, 'time': str(datetime.utcnow())}
print(("\n--------------------- /apiecho/v1/delete ------------------------\n"))
if not request.content_length:
response['message'] = "no body"
else:
try:
print("Body: \n\n", json.loads(request.data))
response['body'] = json.loads(request.data)
except:
print("Body: \n\n", request.data)
response['message'] = "body not json"
print("\nReturn Response: \n", response)
return response
app.run(host="0.0.0.0", port=9999)
安装与运行
环境要求
- Python 3.6+
- pip包管理器
安装步骤
- 克隆或下载项目
bash
cd apiecho
- 安装依赖包
bash
pip install -r requirements.txt
运行方式
方式一:使用Python直接运行
bash
python app.py
方式二:使用启动脚本(Linux/Mac)
bash
chmod +x run.sh
./run.sh
方式三:Windows PowerShell
powershell
python -u app.py
访问服务
服务启动后,可通过以下方式访问:
- Web界面: http://localhost:9999
- API接口: http://localhost:9999/apiecho/v1/...
使用示例
cURL示例
1. 测试同步回显
bash
curl -X POST http://localhost:9999/apiecho/v1/sync \
-H "Content-Type: application/json" \
-d '{"name": "test", "value": 123}'
2. 配置返回值
bash
curl -X GET http://localhost:9999/apiecho/v1/config/status/ok
3. 获取布尔值
bash
curl -X POST http://localhost:9999/apiecho/v1/bool/isEnabled/true \
-H "Content-Type: application/json" \
-d '{"userId": 1}'
4. 设置状态码
bash
curl -X GET http://localhost:9999/apiecho/v1/code/httpStatus/404
Python requests示例
python
import requests
import json
# 1. POST请求测试
url = "http://localhost:9999/apiecho/v1/sync"
payload = {"username": "test", "password": "123456"}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
# 2. 配置接口测试
response = requests.get("http://localhost:9999/apiecho/v1/config/result/success")
print(response.json())
# 3. 布尔值测试
response = requests.post("http://localhost:9999/apiecho/v1/bool/isActive/true")
print(response.json())
JavaScript fetch示例
javascript
// POST请求示例
fetch('http://localhost:9999/apiecho/v1/sync', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'test',
value: 123
})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
设计特点
1. 架构设计
- 单体应用: 采用Flask轻量级框架,所有功能集中在一个文件中
- RESTful风格: API设计遵循REST规范
- 无状态服务: 每个请求独立处理,不依赖服务器状态
2. 日志与调试
服务在控制台输出详细的请求信息,便于调试:
- 请求时间
- HTTP方法
- 请求头信息
- 请求体内容
- 返回响应
控制台输出示例:
--------------------- /apiecho/v1/sync ------------------------
TIME: 2026-01-15 12:00:00.123456
Method: POST
Headers:
Host: localhost:9999
Content-Type: application/json
...
Body:
{'name': 'test', 'value': 123}
Return Response:
{'code': 200, 'success': True, 'method': 'POST', 'url': '...', 'time': '...', 'body': {'name': 'test', 'value': 123}}
3. 错误处理
- JSON解析异常处理
- 数字类型转换校验
- 请求体缺失提示
- 友好的错误消息返回
4. 扩展性
- 易于添加新的API端点
- 响应格式统一,便于前端集成
- 支持多种HTTP方法
应用场景
- API接口测试: 快速验证API调用是否正确
- Webhook调试: 接收并查看webhook推送的数据
- 客户端开发: 在后端API未完成时进行前端开发
- 接口文档演示: 提供实时的API调用示例
- 网络请求调试: 检查HTTP请求的headers和body
- 自动化测试: 作为测试环境的Mock服务
依赖包说明
| 包名 | 版本 | 用途 |
|---|---|---|
| Flask | 2.1.2 | Web框架 |
| click | 8.1.3 | 命令行工具(Flask依赖) |
| Jinja2 | 3.1.2 | 模板引擎(Flask依赖) |
| Werkzeug | 2.1.2 | WSGI工具库(Flask依赖) |
| itsdangerous | 2.1.2 | 数据签名(Flask依赖) |
| MarkupSafe | 2.1.1 | 字符串转义(Jinja2依赖) |
注意事项
- 生产环境使用: 本服务仅供开发测试使用,不建议在生产环境部署
- 安全性: 服务监听在0.0.0.0,外网可访问,注意防火墙配置
- 端口占用: 默认使用9999端口,确保端口未被占用
- JSON格式: 大部分接口期望接收JSON格式的请求体
- 时间格式: 返回的时间为UTC时间,非本地时间
常见问题
Q1: 服务启动后无法访问?
A: 检查防火墙设置,确保9999端口已开放。Windows用户可能需要允许Python通过防火墙。
Q2: POST请求返回"Please send body"错误?
A: POST和PUT接口必须携带请求体,且Content-Type应设置为application/json。
Q3: 如何修改服务端口?
A : 编辑app.py最后一行,将port=9999修改为其他端口号。
Q4: 接口返回"body not json"?
A: 请求体内容不是有效的JSON格式,请检查请求体格式是否正确。
Q5: 如何查看请求详情?
A: 查看运行服务的控制台窗口,所有请求信息都会实时打印。
更新日志
- v1.0 (2022-07-05): 初始版本发布
- 实现基础的API回显功能
- 支持多种HTTP方法
- 提供Web文档界面
- 添加配置、布尔值、状态码等灵活接口
许可证 MIT License
本项目仅供学习和测试使用。
联系方式
作者 : Johnny
创建日期: 2022年7月5日
Generated by API Echo Service - A Simple API Testing Tool