Skip to content

Commit

Permalink
feat,dep: add response handling and UI layout
Browse files Browse the repository at this point in the history
  • Loading branch information
TimeBather authored and ilharp committed Oct 30, 2024
1 parent 61b94a3 commit e6d7c17
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 19 deletions.
6 changes: 3 additions & 3 deletions client/components/HttpTools.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ watch(mode,(m)=>console.info(m));
</script>

<template>
<div style="display: flex;flex-direction: column;height:100%">
<div style="display: flex;flex-direction: column;flex: 1 1 0">
<Toast />
<MainMenu v-model:mode="mode" v-model="current" :unsaved="unsaved"/>
<div style="display: flex;flex-direction: row;height:100%">
<Splitter style="height: 100%;width: 100%">
<div style="display: flex;flex-direction: row;flex: 1 1 0;overflow: hidden;">
<Splitter style="flex: 1 1 0;width: 100%">
<SplitterPanel :size="20" style="min-width: 300px">
<RequestList :requests="mode == 'capture' ? capturedRequests : userRequests" v-model="current"/>
</SplitterPanel>
Expand Down
12 changes: 6 additions & 6 deletions client/components/editors/HttpEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const method = computed({
</script>

<template>
<div style="display: flex;flex-direction: column;gap: 5px;height:100%">
<div style="display: flex;flex-direction: column;gap: 5px;overflow: hidden;height: 100%">
<div style="padding: 8px 20px;">
<InputGroup>
<Select
Expand Down Expand Up @@ -65,18 +65,18 @@ const method = computed({
Cache Miss
</span>
</div>
<Tabs value="0" style="flex:1">
<Tabs value="0" style="flex: 1 1 0;overflow: hidden;">
<TabList>
<Tab value="0">请求</Tab>
<Tab value="1">响应</Tab>
<Tab value="2">选项</Tab>
</TabList>
<TabPanels style="padding: 0;flex:1;">
<TabPanel value="0" style="padding: 1rem">
<TabPanels style="padding: 0;flex:1;display: flex;overflow: hidden;width: 100%">
<TabPanel value="0" style="padding: 1rem;flex:1;width: 100%">
<HttpRequestEditor v-model="model"/>
</TabPanel>
<TabPanel value="1" style="padding: 0;height:100%">
<HttpResponsePreviewer v-model:identifier="identifier"/>
<TabPanel value="1" style="padding: 0;flex:1;display: flex;width: 100%">
<HttpResponsePreviewer v-model:identifier="identifier" v-model="model"/>
</TabPanel>
<TabPanel value="2">

Expand Down
2 changes: 1 addition & 1 deletion client/components/editors/HttpEditorProxy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@

<template>
<HttpEditor v-if="data" v-model="data" v-model:identifier="model"/>
<div style="height:100%;width: 100%;display: flex;flex-direction: column" v-else>
<div style="flex:1;display: flex;flex-direction: column" v-else>
<div style="display: flex;flex-direction: column;gap: 5px">
<div style="padding: 8px 20px;">
<Skeleton height="2.5rem" width="100%"></Skeleton>
Expand Down
18 changes: 15 additions & 3 deletions client/components/editors/http/HttpResponsePreviewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import {ref,computed,watch} from "vue";
import Menu from "primevue/menu";
import {MenuItem} from "primevue/menuitem";
import History from "./response/History.vue";
import StackTrace from "./response/StackTrace.vue";
import ResponseHeader from "./response/ResponseHeader.vue";
import ScrollPanel from "primevue/scrollpanel";
import ResponseBody from "./response/ResponseBody.vue";
const model = defineModel();
const identifier = defineModel<any>('identifier');
Expand Down Expand Up @@ -46,7 +51,7 @@ const items = computed(
</script>

<template>
<div class="flex" style="height: 100%">
<div class="flex" style="flex:1">
<Menu :model="items" style="height: 100%; border-left: none;border-top:none;border-bottom: none;border-radius: 0">
<template #item="{ item, props }">
<a v-ripple class="flex items-center" v-bind="props.action">
Expand All @@ -56,8 +61,15 @@ const items = computed(
</a>
</template>
</Menu>
<div class="flex-1">
<History v-if="current == 'history'"/>
<div class="flex-1 flex">
<div style="height: 100%;width: 100%">
<ScrollPanel style="height: 100%;width: 100%">
<ResponseHeader v-if="current == 'header'" v-model="model"/>
<ResponseBody v-if="current == 'body'" v-model="model"/>
<History v-if="current == 'history'"/>
<StackTrace v-else-if="current == 'stack'"/>
</ScrollPanel>
</div>
</div>
</div>
</template>
Expand Down
16 changes: 16 additions & 0 deletions client/components/editors/http/response/ResponseBody.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
import {computed} from 'vue'
const model = defineModel<any>()
const body = computed(()=>atob(model.value?.responseBody))
</script>

<template>
<div>
{{ body }}123
</div>
</template>

<style scoped>
</style>
25 changes: 25 additions & 0 deletions client/components/editors/http/response/ResponseHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script setup lang="ts">
import {computed} from 'vue'
import Column from "primevue/column";
import DataTable from "primevue/datatable";
const model = defineModel<any>();
const headers = computed(()=>Object.entries(model.value?.responseHeaders ?? {}).map(t=>({
name:t[0],
value:t[1]
})))
</script>

<template>
<div>
<DataTable :value="headers">
<Column field="name" header="Name"></Column>
<Column field="value" header="Value"></Column>
</DataTable>
</div>
</template>

<style scoped>
</style>
24 changes: 24 additions & 0 deletions client/components/editors/http/response/StackTrace.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import DataTable from "primevue/datatable";
import Column from "primevue/column";
import {computed} from 'vue'
const stackTrace = ` at REPL31:1:7
at ContextifyScript.runInThisContext (node:vm:121:12)
at REPLServer.defaultEval (node:repl:599:22)
at bound (node:domain:432:15)
at REPLServer.runBound (node:domain:443:12)
at REPLServer.p [as eval] (file:///C:/Users/TimeBather/AppData/Roaming/npm/node_modules/tsx/dist/loader.mjs:1:786)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)`
const stack = computed(()=>stackTrace.split('\n').map(t=>({name:t})))
</script>

<template>
<DataTable :value="stack">
<Column field="name" header="Name"></Column>
</DataTable>
</template>

<style scoped>
</style>
1 change: 1 addition & 0 deletions client/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ import HttpTools from "./components/HttpTools.vue";
<style>
#app,body,html{
height:100%;
overflow: hidden;
}
</style>
3 changes: 3 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare module '@cordisjs/plugin-webui' {
'http/request'(param: {type: string; id: number}): Promise<Request | undefined>
'http/request.create'(request: Request): Promise<number | undefined>
'http/request.save'(request: Request): Promise<number | undefined>
'http/request.delete'(request: any): Promise<void>
}
}

Expand Down Expand Up @@ -48,13 +49,15 @@ export namespace HttpApi{
return {
...request,
requestBody: request.requestBody ? Buffer.from(request.requestBody as ArrayBuffer).toString('base64') : undefined,
responseBody: request.responseBody ? Buffer.from(request.responseBody as ArrayBuffer).toString('base64') : undefined,
}
}

function deserializeBinary(request: Request): Request {
return {
...request,
requestBody: request.requestBody ? Buffer.from(request.requestBody as string, 'base64') as Buffer : undefined,
responseBody: request.responseBody ? Buffer.from(request.responseBody as string, 'base64') as Buffer : undefined,
}
}
}
Expand Down
41 changes: 37 additions & 4 deletions src/capture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export namespace HttpToolCaptureModule{
if (!ctx['http/data'].captureEnabled) { return }

const body = serializeBody(init)
ctx['http/data'].capture({
ctx['http/data'].capture(init, {
method: init.method ?? 'GET',
requestHeaders: config.headers ?? {},
host: url.host,
Expand All @@ -17,6 +17,39 @@ export namespace HttpToolCaptureModule{
requestBody: ('then' in body) ? null : body,
})
})
ctx.on('http/after-fetch', (data) => {
const endTime = Date.now()
if (data.result) {
ctx['http/data'].fillCapture(data.init, {
responseCode: data.result.status,
responseStatus: data.result.statusText,
responseHeaders: Object.fromEntries((() => {
const h = []
data.result.headers.forEach((value, key) => h.push([key, value]))
return h
})()),
responseBody: null,
endTime,
})
data.result.clone().arrayBuffer().then((body) => {
ctx['http/data'].fillCapture(data.init, {
responseBody: body,
})
})
} else if (ctx.http.isError(data.error)) {
ctx['http/data'].fillCapture(data.init, {
responseCode: -1,
responseStatus: data.error.code,
endTime,
})
} else {
ctx['http/data'].fillCapture(data.init, {
responseCode: -1,
responseStatus: 'E_UNKNOWN',
endTime,
})
}
})
}

function serializeBody(requestInit?: RequestInit): ArrayBuffer | Promise<ArrayBuffer> {
Expand All @@ -40,7 +73,7 @@ export namespace HttpToolCaptureModule{
return requestInit.body.arrayBuffer()
}
if (requestInit.body instanceof FormData) {
return encodeFormData(requestInit.body)
return encodeFormData(requestInit.body)!
}
if (requestInit.body instanceof URLSearchParams) {
return encodeTextToBuffer(requestInit.body.toString())
Expand All @@ -56,7 +89,7 @@ export namespace HttpToolCaptureModule{
return textEncoder.encode(str)
}

function encodeFormData(body: FormData): ArrayBuffer {

function encodeFormData(body: FormData): ArrayBuffer | null {
return null
}
}
10 changes: 9 additions & 1 deletion src/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class HttpDataService extends Service {
}
}

capture(request: Request) {
capture(init: object, request: Request) {
request.id = this.idCounter++
this.captured.unshift(request)
const data = {
Expand All @@ -69,6 +69,7 @@ export class HttpDataService extends Service {
path: request.path,
startTime: request.startTime,
}
this.initMap.set(init, request)
this.capturedSummary.unshift(data)
this.entry?.refresh()
}
Expand Down Expand Up @@ -159,4 +160,11 @@ export class HttpDataService extends Service {
this.entry?.refresh()
}
}

fillCapture(init: object, request: Partial<Request>) {
const targetObject = this.initMap.get(init)
if (!targetObject) { return }
Object.assign(targetObject, request)
this.entry?.refresh()
}
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function apply(ctx: Context) {
ctx.plugin(HttpToolCaptureModule)
ctx.inject(['http'], (ctx) => {
let i = 0
console.info(ctx.http.post('https://www.timebather.cn/my-url-address' + (i++), { p: 1 }, {
console.info(ctx.http.get('https://www.baidu.com/', {
headers: {
'User-Agent': 'NodeJS',
},
Expand Down
8 changes: 8 additions & 0 deletions src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export interface Request extends RequestSummary{
url: string
requestHeaders: Record<string, any>
requestBody: ArrayBuffer | string
responseHeaders?: Record<string, any>
responseBody?: ArrayBuffer | string
endTime?: number
}

declare module 'minato'{
Expand All @@ -24,7 +27,12 @@ export namespace HttpToolsStorage{
path: 'string',
requestHeaders: 'json',
requestBody: 'binary',
responseCode: 'integer',
responseStatus: 'string',
responseHeaders: 'json',
responseBody: 'binary',
startTime: 'unsigned',
endTime: 'unsigned',
}, {
primary: 'id',
autoInc: true,
Expand Down

0 comments on commit e6d7c17

Please sign in to comment.