websocket frontend parse message

addon-dailer
lqqyt2423 4 years ago
parent abf0f36095
commit 6c1ec812b2

@ -7,7 +7,6 @@
"@testing-library/react": "^11.1.0", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"js-base64": "^3.6.0",
"react": "^17.0.1", "react": "^17.0.1",
"react-bootstrap": "^1.4.3", "react-bootstrap": "^1.4.3",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",

@ -1,6 +1,5 @@
import React from 'react' import React from 'react'
import Table from 'react-bootstrap/Table' import Table from 'react-bootstrap/Table'
import { Base64 } from 'js-base64'
import './App.css' import './App.css'
const isTextResponse = response => { const isTextResponse = response => {
@ -11,6 +10,49 @@ const isTextResponse = response => {
return /text|javascript|json/.test(response.header['Content-Type'].join('')) 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 { class App extends React.Component {
constructor(props) { constructor(props) {
@ -23,6 +65,7 @@ class App extends React.Component {
flowTab: 'Headers', // Headers, Preview, Response flowTab: 'Headers', // Headers, Preview, Response
} }
this.ws = null this.ws = null
this.flowsMap = new Map()
} }
componentDidMount() { componentDidMount() {
@ -39,27 +82,37 @@ class App extends React.Component {
if (this.ws) return if (this.ws) return
this.ws = new WebSocket("ws://localhost:9081/echo") this.ws = new WebSocket("ws://localhost:9081/echo")
this.ws.binaryType = 'arraybuffer'
this.ws.onopen = () => { console.log('OPEN') } this.ws.onopen = () => { console.log('OPEN') }
this.ws.onclose = () => { console.log('CLOSE') } this.ws.onclose = () => { console.log('CLOSE') }
this.ws.onmessage = evt => { this.ws.onmessage = evt => {
const data = JSON.parse(evt.data) const msg = parseMessage(evt.data)
console.log(data) if (!msg) {
console.error('parse error:', evt.data)
return
}
console.log('msg:', msg)
const flow = data.flow if (msg.type === 'request') {
const id = flow.id const flow = { id: msg.id, request: msg.content }
if (data.on === 'request') { this.flowsMap.set(msg.id, flow)
this.setState({ flows: this.state.flows.concat(flow) }) this.setState({ flows: this.state.flows.concat(flow) })
} }
else if (data.on === 'response') { else if (msg.type === 'response') {
const flows = this.state.flows.map(f => { const flow = this.flowsMap.get(msg.id)
if (f.id === id) return flow if (!flow) return
return f flow.response = msg.content
}) this.setState({ flows: this.state.flows })
this.setState({ 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 => { this.ws.onerror = evt => {
console.log('ERROR: ' + evt.data) console.log('ERROR:', evt)
} }
// this.ws.send('msg') // this.ws.send('msg')
@ -127,10 +180,10 @@ class App extends React.Component {
{ {
!(flowTab === 'Response') ? null : !(flowTab === 'Response') ? null :
!(response.body && response.body.length) ? <div>No response</div> : !(response.body && response.body.byteLength) ? <div>No response</div> :
!(isTextResponse(response)) ? <div>Not text response</div> : !(isTextResponse(response)) ? <div>Not text response</div> :
<div> <div>
{Base64.decode(response.body)} {new TextDecoder().decode(response.body)}
</div> </div>
} }
</div> </div>
@ -150,6 +203,7 @@ class App extends React.Component {
<th>Path</th> <th>Path</th>
<th>Method</th> <th>Method</th>
<th>Status</th> <th>Status</th>
<th>Size</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -170,6 +224,7 @@ class App extends React.Component {
<td>{path}</td> <td>{path}</td>
<td>{request.method}</td> <td>{request.method}</td>
<td>{response.statusCode || '(pending)'}</td> <td>{response.statusCode || '(pending)'}</td>
<td>{getSize(response)}</td>
</tr> </tr>
) )
}) })

@ -6650,11 +6650,6 @@ jest@26.6.0:
import-local "^3.0.2" import-local "^3.0.2"
jest-cli "^26.6.0" 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: "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

Loading…
Cancel
Save