title: 浏览器调试示例 description: 在浏览器中直接调试 @cat-kit/http 的请求与插件能力 sidebarOrder: 4
Are you an LLM? You can read better optimized documentation at /cat-kit/packages/http/browser-debug.md for this page in Markdown format
浏览器调试示例
介绍
本页提供可直接运行的浏览器 Demo,用于快速验证 @cat-kit/http 的核心能力:
- 基础请求(GET / POST)
- 插件链路(Token、MethodOverride、自定义日志)
快速使用
- 启动文档站点:
pnpm --filter @cat-kit/docs dev - 打开
HTTP 请求 > 浏览器调试示例 - 点击示例按钮并在页面里观察请求结果
示例 1:基础请求调试
vue
基础请求调试
在浏览器里直接调试 GET / POST 请求与响应内容
请求方法
-请求地址
-状态码
-点击上方按钮发起请求
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
<template>
<div class="demo-box">
<div class="demo-header">
<h3>基础请求调试</h3>
<p>在浏览器里直接调试 GET / POST 请求与响应内容</p>
</div>
<div class="demo-controls">
<var-input
v-model="postTitle"
placeholder="POST 时使用的标题"
clearable
/>
<var-space>
<var-button type="primary" :loading="loading" @click="sendGetRequest">
调试 GET
</var-button>
<var-button type="success" :loading="loading" @click="sendPostRequest">
调试 POST
</var-button>
</var-space>
</div>
<div class="demo-result">
<div class="result-row">
<span class="label">请求方法</span>
<code>{{ lastMethod || '-' }}</code>
</div>
<div class="result-row">
<span class="label">请求地址</span>
<code>{{ lastUrl || '-' }}</code>
</div>
<div class="result-row">
<span class="label">状态码</span>
<code>{{ statusCode ?? '-' }}</code>
</div>
<div v-if="errorMessage" class="error-box">
{{ errorMessage }}
</div>
<pre v-else class="json-box">{{ formattedResponse }}</pre>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { HTTPClient } from '@cat-kit/http'
interface PostItem {
id: number
userId: number
title: string
body: string
}
const http = new HTTPClient('', {
timeout: 15000,
headers: {
'X-Demo-Source': 'cat-kit-docs'
}
})
const postTitle = ref('cat-kit browser demo')
const loading = ref(false)
const statusCode = ref<number | null>(null)
const lastMethod = ref('')
const lastUrl = ref('')
const errorMessage = ref('')
const responseData = ref<unknown>(null)
const formattedResponse = computed(() => {
if (!responseData.value) {
return '点击上方按钮发起请求'
}
return JSON.stringify(responseData.value, null, 2)
})
async function sendGetRequest() {
loading.value = true
errorMessage.value = ''
lastMethod.value = 'GET'
lastUrl.value = 'https://jsonplaceholder.typicode.com/posts/1?_t=debug'
try {
const response = await http.get<PostItem>(
'https://jsonplaceholder.typicode.com/posts/1',
{
query: { _t: 'debug' }
}
)
statusCode.value = response.code
responseData.value = response.data
} catch (error) {
errorMessage.value = error instanceof Error ? error.message : '请求失败'
} finally {
loading.value = false
}
}
async function sendPostRequest() {
loading.value = true
errorMessage.value = ''
lastMethod.value = 'POST'
lastUrl.value = 'https://jsonplaceholder.typicode.com/posts'
try {
const response = await http.post<PostItem>(
'https://jsonplaceholder.typicode.com/posts',
{
title: postTitle.value || 'cat-kit browser demo',
body: 'request from docs demo',
userId: 1
}
)
statusCode.value = response.code
responseData.value = response.data
} catch (error) {
errorMessage.value = error instanceof Error ? error.message : '请求失败'
} finally {
loading.value = false
}
}
</script>
<style scoped>
.demo-box {
display: flex;
flex-direction: column;
gap: 16px;
}
.demo-header h3 {
margin: 0 0 4px;
font-size: 16px;
}
.demo-header p {
margin: 0;
color: var(--vp-c-text-2);
font-size: 13px;
}
.demo-controls {
display: flex;
flex-direction: column;
gap: 12px;
}
.demo-result {
background: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
padding: 12px;
display: flex;
flex-direction: column;
gap: 8px;
}
.result-row {
display: flex;
gap: 10px;
align-items: center;
font-size: 13px;
}
.label {
min-width: 64px;
color: var(--vp-c-text-2);
}
.json-box {
margin: 0;
white-space: pre-wrap;
word-break: break-word;
max-height: 260px;
overflow: auto;
padding: 10px;
border-radius: 6px;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
}
.error-box {
padding: 10px;
border-radius: 6px;
color: var(--vp-c-red-1);
border: 1px solid var(--vp-c-red-3);
background: color-mix(in srgb, var(--vp-c-red-1) 10%, transparent);
}
</style>
示例 2:插件链路调试
vue
插件链路调试
调试 TokenPlugin、MethodOverridePlugin 与自定义日志插件
最终 method
-请求头
-响应状态
-暂无调试日志
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
<template>
<div class="demo-box">
<div class="demo-header">
<h3>插件链路调试</h3>
<p>调试 TokenPlugin、MethodOverridePlugin 与自定义日志插件</p>
</div>
<var-input
v-model="token"
clearable
placeholder="输入 token,观察请求头变化"
/>
<var-space>
<var-button type="primary" :loading="loading" @click="sendDelete">
调试 DELETE(会被重写)
</var-button>
<var-button @click="clearLogs">清空日志</var-button>
</var-space>
<div class="meta-box">
<div class="meta-row">
<span class="label">最终 method</span>
<code>{{ requestMeta.method || '-' }}</code>
</div>
<div class="meta-row">
<span class="label">请求头</span>
<code>{{ requestMeta.headers || '-' }}</code>
</div>
<div class="meta-row">
<span class="label">响应状态</span>
<code>{{ requestMeta.code ?? '-' }}</code>
</div>
</div>
<div class="log-box">
<div v-for="(log, index) in logs" :key="index" class="log-row">
{{ log }}
</div>
<div v-if="logs.length === 0" class="empty">暂无调试日志</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { HTTPClient, MethodOverridePlugin, TokenPlugin } from '@cat-kit/http'
const token = ref('debug-token-001')
const loading = ref(false)
const logs = ref<string[]>([])
const requestMeta = reactive<{
method: string
headers: string
code: number | null
}>({
method: '',
headers: '',
code: null
})
function appendLog(message: string) {
const time = new Date().toLocaleTimeString()
logs.value.unshift(`[${time}] ${message}`)
if (logs.value.length > 12) {
logs.value.pop()
}
}
const http = new HTTPClient('', {
timeout: 15000,
plugins: [
TokenPlugin({
getter: () => token.value,
authType: 'Bearer'
}),
MethodOverridePlugin({
methods: ['DELETE'],
overrideMethod: 'POST'
}),
{
beforeRequest(url, config) {
requestMeta.method = config.method ?? '-'
requestMeta.headers = JSON.stringify(config.headers ?? {})
appendLog(`beforeRequest -> ${config.method} ${url}`)
},
afterRespond(response) {
requestMeta.code = response.code
appendLog(`afterRespond -> code=${response.code}`)
return response
},
onError(error) {
const message = error instanceof Error ? error.message : 'unknown error'
appendLog(`onError -> ${message}`)
}
}
]
})
async function sendDelete() {
loading.value = true
requestMeta.code = null
try {
await http.delete('https://jsonplaceholder.typicode.com/posts/1')
} catch (error) {
appendLog(error instanceof Error ? error.message : '请求失败')
} finally {
loading.value = false
}
}
function clearLogs() {
logs.value = []
}
</script>
<style scoped>
.demo-box {
display: flex;
flex-direction: column;
gap: 14px;
}
.demo-header h3 {
margin: 0;
font-size: 16px;
}
.demo-header p {
margin: 4px 0 0;
color: var(--vp-c-text-2);
font-size: 13px;
}
.meta-box,
.log-box {
background: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
padding: 12px;
}
.meta-box {
display: flex;
flex-direction: column;
gap: 8px;
}
.meta-row {
display: flex;
gap: 8px;
align-items: center;
}
.label {
min-width: 72px;
color: var(--vp-c-text-2);
font-size: 13px;
}
.log-box {
max-height: 240px;
overflow: auto;
}
.log-row {
font-family: var(--vp-font-family-mono);
font-size: 12px;
padding: 4px 0;
border-bottom: 1px dashed var(--vp-c-divider);
}
.log-row:last-child {
border-bottom: none;
}
.empty {
text-align: center;
color: var(--vp-c-text-3);
font-size: 12px;
}
</style>
API参考
上述示例使用到的主要 API:
new HTTPClient(prefix?, config?)http.get(url, config?)http.post(url, body?, config?)http.delete(url, config?)TokenPlugin(options)MethodOverridePlugin(options?)
如需查看完整签名与参数说明,请继续阅读:
