From 6c1ec812b2c97ba0a2b7909ee8921bd7dbed275e Mon Sep 17 00:00:00 2001 From: lqqyt2423 <974923609@qq.com> Date: Wed, 10 Feb 2021 00:14:15 +0800 Subject: [PATCH] websocket frontend parse message --- addon/web/client/package.json | 1 - addon/web/client/src/App.js | 85 ++++++++++++++++++++++++++++------- addon/web/client/yarn.lock | 5 --- 3 files changed, 70 insertions(+), 21 deletions(-) diff --git a/addon/web/client/package.json b/addon/web/client/package.json index 5700cef..6f39ebf 100644 --- a/addon/web/client/package.json +++ b/addon/web/client/package.json @@ -7,7 +7,6 @@ "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "bootstrap": "^4.6.0", - "js-base64": "^3.6.0", "react": "^17.0.1", "react-bootstrap": "^1.4.3", "react-dom": "^17.0.1", diff --git a/addon/web/client/src/App.js b/addon/web/client/src/App.js index 6e3bf66..03faf56 100644 --- a/addon/web/client/src/App.js +++ b/addon/web/client/src/App.js @@ -1,6 +1,5 @@ import React from 'react' import Table from 'react-bootstrap/Table' -import { Base64 } from 'js-base64' import './App.css' const isTextResponse = response => { @@ -11,6 +10,49 @@ const isTextResponse = response => { return /text|javascript|json/.test(response.header['Content-Type'].join('')) } +const getSize = response => { + if (!response) return '0' + if (!response.header) return '0' + if (!response.header['Content-Length']) return '0' + const len = parseInt(response.header['Content-Length'][0]) + if (isNaN(len)) return '0' + if (len <= 0) return '0' + + if (len < 1024) return `${len} B` + if (len < 1024*1024) return `${(len/1024).toFixed(2)} KB` + return `${(len/(1024*1024)).toFixed(2)} MB` +} + +const parseMessage = data => { + if (data.byteLength < 38) return null + const meta = new Int8Array(data.slice(0, 2)) + const version = meta[0] + if (version !== 1) return null + const type = meta[1] + if (![1, 2, 3].includes(type)) return null + const id = new TextDecoder().decode(data.slice(2, 38)) + + const resp = { + type: ['request', 'response', 'responseBody'][type-1], + id, + } + if (data.byteLength === 38) return resp + if (type === 3) { + resp.content = data.slice(38) + return resp + } + + let content = new TextDecoder().decode(data.slice(38)) + try { + content = JSON.parse(content) + } catch (err) { + return null + } + + resp.content = content + return resp +} + class App extends React.Component { constructor(props) { @@ -23,6 +65,7 @@ class App extends React.Component { flowTab: 'Headers', // Headers, Preview, Response } this.ws = null + this.flowsMap = new Map() } componentDidMount() { @@ -39,27 +82,37 @@ class App extends React.Component { if (this.ws) return this.ws = new WebSocket("ws://localhost:9081/echo") + this.ws.binaryType = 'arraybuffer' this.ws.onopen = () => { console.log('OPEN') } this.ws.onclose = () => { console.log('CLOSE') } this.ws.onmessage = evt => { - const data = JSON.parse(evt.data) - console.log(data) + const msg = parseMessage(evt.data) + if (!msg) { + console.error('parse error:', evt.data) + return + } + console.log('msg:', msg) - const flow = data.flow - const id = flow.id - if (data.on === 'request') { + if (msg.type === 'request') { + const flow = { id: msg.id, request: msg.content } + this.flowsMap.set(msg.id, flow) this.setState({ flows: this.state.flows.concat(flow) }) } - else if (data.on === 'response') { - const flows = this.state.flows.map(f => { - if (f.id === id) return flow - return f - }) - this.setState({ flows }) + else if (msg.type === 'response') { + const flow = this.flowsMap.get(msg.id) + if (!flow) return + flow.response = msg.content + this.setState({ flows: this.state.flows }) + } + else if (msg.type === 'responseBody') { + const flow = this.flowsMap.get(msg.id) + if (!flow || !flow.response) return + flow.response.body = msg.content + this.setState({ flows: this.state.flows }) } } this.ws.onerror = evt => { - console.log('ERROR: ' + evt.data) + console.log('ERROR:', evt) } // this.ws.send('msg') @@ -127,10 +180,10 @@ class App extends React.Component { { !(flowTab === 'Response') ? null : - !(response.body && response.body.length) ?
No response
: + !(response.body && response.body.byteLength) ?
No response
: !(isTextResponse(response)) ?
Not text response
:
- {Base64.decode(response.body)} + {new TextDecoder().decode(response.body)}
} @@ -150,6 +203,7 @@ class App extends React.Component { Path Method Status + Size @@ -170,6 +224,7 @@ class App extends React.Component { {path} {request.method} {response.statusCode || '(pending)'} + {getSize(response)} ) }) diff --git a/addon/web/client/yarn.lock b/addon/web/client/yarn.lock index 7f654ce..dd51f5b 100644 --- a/addon/web/client/yarn.lock +++ b/addon/web/client/yarn.lock @@ -6650,11 +6650,6 @@ jest@26.6.0: import-local "^3.0.2" jest-cli "^26.6.0" -js-base64@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.6.0.tgz#773e1de628f4f298d65a7e9842c50244751f5756" - integrity sha512-wVdUBYQeY2gY73RIlPrysvpYx+2vheGo8Y1SNQv/BzHToWpAZzJU7Z6uheKMAe+GLSBig5/Ps2nxg/8tRB73xg== - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"