<?php
// 如果是OPTIONS请求,直接返回
if ($_GET['act'] != '') {
header('Content-Type: application/json');
// 允许跨域请求
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// 获取请求数据
$input = json_decode(file_get_contents('php://input'), true);
if (!isset($input['url'])) {
echo json_encode(['error' => '缺少URL参数']);
exit;
}
$url = $input['url'];
$method = $input['method'] ?? 'GET';
$headers = $input['headers'] ?? [];
$data = $input['data'] ?? [];
// 初始化CURL
$ch = curl_init();
// 设置CURL选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// 设置请求方法
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
// 设置请求头
if (!empty($headers)) {
$headerArray = [];
foreach ($headers as $key => $value) {
$headerArray[] = "$key: $value";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);
}
// 获取响应头
$responseHeaders = [];
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$responseHeaders) {
$len = strlen($header);
$header = explode(':', $header, 2);
if (count($header) < 2) {
return $len;
}
$responseHeaders[trim($header[0])] = trim($header[1]);
return $len;
});
// 执行请求
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch);
$error = curl_error($ch);
curl_close($ch);
// 返回结果
echo json_encode([
'status' => $httpCode['http_code'],
'headers' => $responseHeaders,
'response' => $response,
'error' => $error ?: null,
'info' => [
'total_time' => $httpCode['total_time'],
'size_download' => $httpCode['size_download'],
'speed_download' => $httpCode['speed_download'],
'content_type' => $httpCode['content_type']
]
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
exit();
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API测试工具</title>
<style>
:root{--primary-color:#4CAF50;--danger-color:#f44336;--border-color:#ddd;}
*{margin:0;padding:0;box-sizing:border-box;}
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;line-height:1.6;padding:20px;background:#f5f5f5;}
.container{max-width:1200px;margin:0 auto;background:white;padding:20px;border-radius:8px;box-shadow:0 2px 4px rgba(0,0,0,0.1);}
h1{text-align:center;color:#333;margin-bottom:30px;}
.form-group{margin-bottom:20px;}
label{display:block;margin-bottom:5px;color:#666;}
input[type="text"],input[type="url"],textarea{width:100%;padding:8px 12px;border:1px solid var(--border-color);border-radius:4px;font-size:14px;}
textarea{min-height:100px;resize:vertical;}
.btn{display:inline-block;padding:8px 16px;border:none;border-radius:4px;background:var(--primary-color);color:white;cursor:pointer;font-size:14px;transition:background 0.3s;}
.btn:hover{opacity:0.9;}
.btn-danger{background:var(--danger-color);}
.param-group{display:flex;gap:10px;margin-bottom:10px;}
.param-group input{flex:1;}
.param-group button{flex-shrink:0;}
.tabs{display:flex;margin-bottom:20px;border-bottom:1px solid var(--border-color);}
.tab{padding:10px 20px;cursor:pointer;border:1px solid transparent;border-bottom:none;margin-bottom:-1px;}
.tab.active{background:white;border-color:var(--border-color);border-radius:4px 4px 0 0;}
.tab-content{display:none;}
.tab-content.active{display:block;}
#response{margin-top:20px;padding:15px;background:#f8f9fa;border-radius:4px;white-space:pre-wrap;font-family:monospace;}
@media (max-width:768px){body{padding:10px;}
.container{padding:15px;}
.param-group{flex-direction:column;gap:5px;}
.tabs{flex-wrap:wrap;}
.tab{flex:1;text-align:center;padding:8px;}
}
</style>
</head>
<body>
<div class="container">
<h1>API测试工具</h1>
<div class="form-group">
<label>请求URL</label>
<input type="url" id="url" placeholder="https://example.com/api" value="http://asp.96448.cn/weixin/chengji.asp">
</div>
<div class="tabs">
<div class="tab active" data-tab="params">GET参数</div>
<div class="tab" data-tab="post">POST数据</div>
<div class="tab" data-tab="headers">请求头</div>
<div class="tab" data-tab="cookies">Cookie</div>
<div class="tab" data-tab="info">客户端信息</div>
</div>
<div class="tab-content active" id="params">
<div id="get-params">
<div class="param-group">
<input type="text" placeholder="参数名" value="getti">
<input type="text" placeholder="参数值" value="getval">
<button class="btn btn-danger">删除</button>
</div>
</div>
<button class="btn" onclick="addParam('get')">添加GET参数</button>
</div>
<div class="tab-content" id="post">
<div id="post-params">
<div class="param-group">
<input type="text" placeholder="参数名" value="postti">
<input type="text" placeholder="参数值" value="postval">
<button class="btn btn-danger">删除</button>
</div>
</div>
<button class="btn" onclick="addParam('post')">添加POST参数</button>
</div>
<div class="tab-content" id="headers">
<div id="header-params">
<div class="param-group">
<input type="text" placeholder="参数名" value="headti">
<input type="text" placeholder="参数值" value="headval">
<button class="btn btn-danger">删除</button>
</div>
</div>
<button class="btn" onclick="addParam('header')">添加请求头</button>
</div>
<div class="tab-content" id="cookies">
<div id="cookie-params">
<div class="param-group">
<input type="text" placeholder="参数名" value="cookti">
<input type="text" placeholder="参数值" value="cookval">
<button class="btn btn-danger">删除</button>
</div>
</div>
<button class="btn" onclick="addParam('cookie')">添加Cookie</button>
</div>
<div class="tab-content" id="info">
<div class="form-group">
<label>Referer (来路)</label>
<input type="text" id="referer" placeholder="https://example.com" value="https://example.com">
</div>
<div class="form-group">
<label>User Agent</label>
<input type="text" id="user-agent" value="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36">
</div>
</div>
<div style="margin-top: 20px;">
<button class="btn" onclick="sendRequest()">发送请求</button>
<button class="btn btn-danger" onclick="clearAll()">清空所有</button>
</div>
<div id="response"></div>
</div>
<script>
// 参数处理函数
const getParams = (type) => {
const params = {};
document.querySelectorAll(`#${type}-params .param-group`).forEach(group => {
const [key, value] = group.querySelectorAll('input');
if (key.value) {
params[key.value] = value.value;
}
});
return params;
};
// 添加参数行
const addParam = (type) => {
const container = document.getElementById(`${type}-params`);
const group = document.createElement('div');
group.className = 'param-group';
const keyInput = document.createElement('input');
keyInput.type = 'text';
keyInput.placeholder = '参数名';
const valueInput = document.createElement('input');
valueInput.type = 'text';
valueInput.placeholder = '参数值';
const removeBtn = document.createElement('button');
removeBtn.className = 'btn btn-danger';
removeBtn.textContent = '删除';
removeBtn.onclick = () => group.remove();
group.appendChild(keyInput);
group.appendChild(valueInput);
group.appendChild(removeBtn);
container.appendChild(group);
};
// 清空所有
const clearAll = () => {
['get', 'post', 'header', 'cookie'].forEach(type => {
document.getElementById(`${type}-params`).innerHTML = '';
});
document.getElementById('url').value = '';
document.getElementById('referer').value = '';
document.getElementById('user-agent').value = '';
document.getElementById('response').textContent = '';
};
// 发送请求
const sendRequest = async () => {
const url = document.getElementById('url').value;
if (!url) {
alert('请输入URL');
return;
}
try {
const getParamsObj = getParams('get');
const getParamsStr = new URLSearchParams(getParamsObj).toString();
const finalUrl = getParamsStr ? `${url}?${getParamsStr}` : url;
const headers = {
'Content-Type': 'application/json',
...getParams('header')
};
const referer = document.getElementById('referer').value;
const userAgent = document.getElementById('user-agent').value;
if (referer) headers['Referer'] = referer;
if (userAgent) headers['User-Agent'] = userAgent;
// 设置Cookie
const cookies = getParams('cookie');
if (Object.keys(cookies).length > 0) {
headers['Cookie'] = Object.entries(cookies)
.map(([key, value]) => `${key}=${value}`)
.join('; ');
}
const response = await fetch('?act=api_proxy', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: finalUrl,
method: Object.keys(getParams('post')).length > 0 ? 'POST' : 'GET',
headers,
data: getParams('post')
})
});
const result = await response.json();
document.getElementById('response').textContent = JSON.stringify(result, null, 2);
} catch (error) {
document.getElementById('response').textContent = `错误: ${error.message}`;
}
};
// 初始化
(() => {
// 切换标签页
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
tab.classList.add('active');
document.getElementById(tab.dataset.tab).classList.add('active');
});
});
// 设置默认User-Agent
document.getElementById('user-agent').value = navigator.userAgent;
})();
</script>
</body>
</html>