用html写一个类似于postman可以发送请求

用html写一个类似于postman可以发送请求

效果图

代码

java 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API请求工具 - Postman风格</title>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Roboto', sans-serif;
        }
        
        :root {
            --primary: #ff6b35;
            --secondary: #2d5d7b;
            --dark: #1e2a38;
            --light: #f5f7fa;
            --success: #4caf50;
            --warning: #ff9800;
            --danger: #f44336;
            --gray: #78909c;
        }
        
        body {
            background-color: #f0f2f5;
            color: #333;
            line-height: 1.6;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        
        header {
            background: linear-gradient(135deg, var(--dark), var(--secondary));
            color: white;
            padding: 15px 0;
            margin-bottom: 30px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }
        
        .header-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 0 20px;
        }
        
        .logo {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .logo i {
            font-size: 28px;
            color: var(--primary);
        }
        
        .logo h1 {
            font-size: 24px;
            font-weight: 700;
        }
        
        .request-controls {
            display: flex;
            gap: 20px;
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
            margin-bottom: 25px;
        }
        
        .method-select {
            width: 120px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            background-color: white;
            font-weight: 500;
            color: var(--secondary);
        }
        
        .url-input {
            flex: 1;
            padding: 10px 15px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 16px;
        }
        
        .send-btn {
            padding: 10px 25px;
            background: linear-gradient(135deg, var(--primary), #ff5722);
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s ease;
            box-shadow: 0 2px 4px rgba(255, 107, 53, 0.3);
        }
        
        .send-btn:hover {
            background: linear-gradient(135deg, #ff5722, var(--primary));
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(255, 107, 53, 0.4);
        }
        
        .send-btn:active {
            transform: translateY(0);
        }
        
        .section {
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
            margin-bottom: 25px;
            overflow: hidden;
        }
        
        .section-header {
            background-color: var(--light);
            padding: 12px 20px;
            font-weight: 600;
            color: var(--secondary);
            border-bottom: 1px solid #eee;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .section-content {
            padding: 20px;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        .form-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: var(--dark);
        }
        
        textarea {
            width: 100%;
            min-height: 150px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
            font-family: monospace;
            resize: vertical;
        }
        
        .response-info {
            display: flex;
            gap: 20px;
            margin-bottom: 20px;
        }
        
        .status-badge {
            padding: 6px 12px;
            background-color: var(--success);
            color: white;
            border-radius: 4px;
            font-weight: 600;
            font-size: 14px;
        }
        
        .size-info {
            color: var(--gray);
            font-size: 14px;
            display: flex;
            align-items: center;
            gap: 5px;
        }
        
        .response-view {
            position: relative;
            border: 1px solid #eee;
            border-radius: 4px;
            overflow: hidden;
        }
        
        .response-content {
            padding: 15px;
            font-family: monospace;
            font-size: 14px;
            background-color: #fafafa;
            white-space: pre-wrap;
            word-break: break-all;
            min-height: 200px;
            max-height: 500px;
            overflow-y: auto;
        }
        
        .copy-btn {
            position: absolute;
            top: 10px;
            right: 10px;
            padding: 6px 10px;
            background-color: white;
            border: 1px solid #ddd;
            border-radius: 4px;
            cursor: pointer;
            color: var(--gray);
            transition: all 0.2s;
        }
        
        .copy-btn:hover {
            background-color: var(--light);
            color: var(--secondary);
        }
        
        .input-row {
            display: flex;
            gap: 15px;
            margin-bottom: 15px;
        }
        
        .input-row .form-group {
            flex: 1;
            margin-bottom: 0;
        }
        
        .input-row input {
            width: 100%;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        
        .instructions {
            background-color: #fff8e1;
            padding: 15px;
            border-radius: 6px;
            font-size: 14px;
            color: #333;
            margin-top: 25px;
            border-left: 4px solid var(--warning);
        }
        
        .instructions h3 {
            margin-bottom: 10px;
            color: var(--dark);
        }
        
        .instructions ul {
            margin-left: 20px;
        }
        
        .instructions li {
            margin-bottom: 8px;
        }
        
        @media (max-width: 768px) {
            .header-content {
                flex-direction: column;
                gap: 15px;
                text-align: center;
            }
            
            .request-controls {
                flex-direction: column;
            }
            
            .input-row {
                flex-direction: column;
                gap: 10px;
            }
        }
        
        .footer {
            text-align: center;
            padding: 20px;
            color: var(--gray);
            font-size: 14px;
            margin-top: 30px;
        }
    </style>
</head>
<body>
    <header>
        <div class="header-content">
            <div class="logo">
                <i class="fas fa-bolt"></i>
                <h1>API请求工具</h1>
            </div>
            <p>模拟Postman的HTTP请求测试工具</p>
        </div>
    </header>
    
    <div class="container">
        <div class="request-controls">
            <select class="method-select" id="method-select">
                <option value="GET">GET</option>
                <option value="POST">POST</option>
                <option value="PUT">PUT</option>
                <option value="DELETE">DELETE</option>
                <option value="PATCH">PATCH</option>
            </select>
            <input 
                type="url" 
                class="url-input" 
                id="url-input" 
                placeholder="输入请求URL..." 
                value=""
            >
            <button class="send-btn" id="send-btn">
                <i class="fas fa-paper-plane"></i> 发送请求
            </button>
        </div>
        
        <div class="section">
            <div class="section-header">
                <i class="fas fa-edit"></i>
                <span>请求头</span>
            </div>
            <div class="section-content">
                <div class="input-row">
                    <div class="form-group">
                        <label>Header Key</label>
                        <input type="text" id="header-key" placeholder="例如: Content-Type">
                    </div>
                    <div class="form-group">
                        <label>Header Value</label>
                        <input type="text" id="header-value" placeholder="例如: application/json">
                    </div>
                </div>
            </div>
        </div>
        
        <div class="section">
            <div class="section-header">
                <i class="fas fa-code"></i>
                <span>请求体 (JSON格式)</span>
            </div>
            <div class="section-content">
                <div class="form-group">
                    <textarea id="request-body" placeholder='{
    "key1": "value1",
    "key2": "value2"
}'></textarea>
                </div>
            </div>
        </div>
        
        <div class="section">
            <div class="section-header">
                <i class="fas fa-reply"></i>
                <span>响应内容</span>
            </div>
            <div class="section-content">
                <div class="response-info">
                    <div class="status-badge" id="status-code">等待请求...</div>
                    <div class="size-info" id="response-size">
                        <i class="fas fa-weight-hanging"></i> <span>0 Bytes</span>
                    </div>
                </div>
                
                <div class="response-view">
                    <div class="response-content" id="response-content">
                        // 请求结果将显示在这里
                    </div>
                    <button class="copy-btn" id="copy-btn">
                        <i class="fas fa-copy"></i> 复制
                    </button>
                </div>
            </div>
        </div>
        
        <div class="instructions">
            <h3><i class="fas fa-info-circle"></i> 使用说明</h3>
            <ul>
                <li>选择请求方法(默认为GET),输入URL地址</li>
                <li>可以添加自定义请求头(可选)</li>
                <li>对于POST/PUT请求,可以在请求体区域输入JSON格式数据</li>
                <li>点击"发送请求"按钮提交API请求</li>
                <li>响应区域将显示状态码、响应大小和返回内容</li>
                <li>使用"复制"按钮可以快速复制响应内容</li>
            </ul>
        </div>
    </div>
    
    <div class="footer">
        <p>© 2023 API请求工具 | 模拟Postman风格接口测试工具</p>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const sendBtn = document.getElementById('send-btn');
            const copyBtn = document.getElementById('copy-btn');
            const urlInput = document.getElementById('url-input');
            const methodSelect = document.getElementById('method-select');
            const requestBody = document.getElementById('request-body');
            const responseContent = document.getElementById('response-content');
            const statusCode = document.getElementById('status-code');
            const responseSize = document.querySelector('#response-size span');
            const headerKey = document.getElementById('header-key');
            const headerValue = document.getElementById('header-value');
            
            // 初始禁用请求体的提示(仅用于GET请求)
            updateBodyPlaceholder();
            
            // 监听方法选择变化
            methodSelect.addEventListener('change', updateBodyPlaceholder);
            
            function updateBodyPlaceholder() {
                if(methodSelect.value === 'GET') {
                    requestBody.placeholder = "GET请求不需要请求体";
                    requestBody.disabled = true;
                } else {
                    requestBody.placeholder = '{\n    "key1": "value1",\n    "key2": "value2"\n}';
                    requestBody.disabled = false;
                }
            }
            
            // 发送请求
            sendBtn.addEventListener('click', async function() {
                const method = methodSelect.value;
                const url = urlInput.value;
                const headers = {};
                
                // 如果有请求头
                if(headerKey.value && headerValue.value) {
                    headers[headerKey.value] = headerValue.value;
                }
                
                // 处理请求体
                let data = null;
                if(method !== 'GET' && requestBody.value.trim() !== '') {
                    try {
                        data = JSON.parse(requestBody.value);
                    } catch (e) {
                        displayErrorResponse("请求体JSON格式错误: " + e.message);
                        return;
                    }
                }
                
                // 显示加载状态
                responseContent.textContent = "发送请求中...";
                statusCode.textContent = "请求中...";
                statusCode.style.backgroundColor = '#ff9800';
                sendBtn.disabled = true;
                sendBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 发送中...';
                
                try {
                    // 使用axios发送请求
                    const response = await axios({
                        method: method,
                        url: url,
                        data: data,
                        headers: headers
                    });
                    
                    // 更新UI
                    updateResponseUI(response);
                } catch (error) {
                    // 处理错误
                    if (error.response) {
                        // 服务器返回了错误的响应状态(4xx, 5xx)
                        updateResponseUI(error.response);
                    } else {
                        // 请求未发出(网络错误等)
                        displayErrorResponse("请求失败: " + error.message);
                    }
                } finally {
                    sendBtn.disabled = false;
                    sendBtn.innerHTML = '<i class="fas fa-paper-plane"></i> 发送请求';
                }
            });
            
            function updateResponseUI(response) {
                // 显示响应状态
                const status = response.status;
                statusCode.textContent = `${status} ${response.statusText}`;
                
                // 根据状态码设置颜色
                if (status >= 200 && status < 300) {
                    statusCode.style.backgroundColor = '#4caf50'; // 成功 - 绿色
                } else if (status >= 300 && status < 400) {
                    statusCode.style.backgroundColor = '#ff9800'; // 重定向 - 橙色
                } else if (status >= 400 && status < 500) {
                    statusCode.style.backgroundColor = '#f44336'; // 客户端错误 - 红色
                } else if (status >= 500) {
                    statusCode.style.backgroundColor = '#9c27b0'; // 服务端错误 - 紫色
                }
                
                // 显示响应大小
                let size = 0;
                if (response.data) {
                    size = JSON.stringify(response.data).length;
                }
                
                // 转换为更易读的大小
                let readableSize = size + " Bytes";
                if (size > 1024) {
                    readableSize = (size / 1024).toFixed(2) + " KB";
                }
                responseSize.textContent = readableSize;
                
                // 格式化JSON响应
                let formattedResponse;
                if (typeof response.data === 'object') {
                    formattedResponse = JSON.stringify(response.data, null, 2);
                } else if (typeof response.data === 'string') {
                    try {
                        // 尝试解析为JSON
                        formattedResponse = JSON.stringify(JSON.parse(response.data), null, 2);
                    } catch (e) {
                        formattedResponse = response.data;
                    }
                } else {
                    formattedResponse = response.data;
                }
                
                responseContent.textContent = formattedResponse;
            }
            
            function displayErrorResponse(message) {
                statusCode.textContent = "错误";
                statusCode.style.backgroundColor = '#f44336';
                responseContent.textContent = message;
            }
            
            // 复制响应内容
            copyBtn.addEventListener('click', function() {
                const textToCopy = responseContent.textContent;
                navigator.clipboard.writeText(textToCopy).then(() => {
                    // 显示复制成功消息
                    const originalText = copyBtn.innerHTML;
                    copyBtn.innerHTML = '<i class="fas fa-check"></i> 已复制';
                    
                    setTimeout(() => {
                        copyBtn.innerHTML = originalText;
                    }, 2000);
                });
            });
        });
    </script>
</body>
</html>
相关推荐
该用户已不存在5 分钟前
人人都爱的开发工具,但不一定合适自己
前端·后端
ZzMemory17 分钟前
JavaScript 类数组:披着数组外衣的 “伪装者”?
前端·javascript·面试
梁萌28 分钟前
前端UI组件库
前端·ui
鲸渔32 分钟前
CSS高频属性速查指南
前端·css·css3
小高00732 分钟前
🌐AST(抽象语法树):前端开发的“代码编译器”
前端·javascript·面试
蓝易云33 分钟前
Git stash命令的详细使用说明及案例分析。
前端·git·后端
GIS瞧葩菜35 分钟前
Cesium 中拾取 3DTiles 交点坐标
前端·javascript·cesium
Allen Bright35 分钟前
【JS-7-ajax】AJAX技术:现代Web开发的异步通信核心
前端·javascript·ajax
轻语呢喃40 分钟前
Mock : 没有后端也能玩的虚拟数据
前端·javascript·react.js
Dnui_King44 分钟前
Oracle 在线重定义
java·服务器·前端