chore: websocket message protocol frontend

addon-dailer
liqiang 4 years ago
parent c07adef09c
commit 12449760f4

@ -5,7 +5,8 @@ import Button from 'react-bootstrap/Button'
import './App.css'
import { FlowManager } from './flow'
import { isTextResponse, getSize, parseMessage, buildMessage } from './utils'
import { isTextResponse, getSize } from './utils'
import { parseMessage, sendMessageEnum, buildMessageEdit, buildMessageMeta } from './message'
class App extends React.Component {
@ -20,6 +21,7 @@ class App extends React.Component {
flowTab: 'Headers', // Headers, Preview, Response
// TODO: change to rules
interceptUriInputing: '',
interceptUri: '',
}
@ -40,7 +42,7 @@ class App extends React.Component {
initWs() {
if (this.ws) return
let host;
let host
if (process.env.NODE_ENV === 'development') {
host = 'localhost:9081'
} else {
@ -107,7 +109,7 @@ class App extends React.Component {
!flow.waitIntercept ? null :
<div className="flow-wait-area">
<Button size="sm" onClick={() => {
const msg = buildMessage(11, flow.id, JSON.stringify(flow.request))
const msg = buildMessageEdit(sendMessageEnum.changeRequest, flow)
this.ws.send(msg)
flow.waitIntercept = false
this.setState({ flows: this.state.flows })
@ -220,7 +222,11 @@ class App extends React.Component {
}}></Form.Control>
<Button size="sm" onClick={() => {
this.setState({ interceptUri: interceptUriInputing })
const msg = buildMessage(21, '00000000-0000-0000-0000-000000000000', interceptUriInputing)
const rules = []
if (interceptUriInputing) {
rules.push({ method: 'ALL', url: interceptUriInputing, action: 1 })
}
const msg = buildMessageMeta(sendMessageEnum.changeBreakPointRules, rules)
this.ws.send(msg)
}}>Set</Button>
{

@ -0,0 +1,105 @@
const messageEnum = {
'request': 1,
'requestBody': 2,
'response': 3,
'responseBody': 4,
}
const allMessageBytes = Object.keys(messageEnum).map(k => messageEnum[k])
const messageByteMap = Object.keys(messageEnum).reduce((m, k) => {
m[messageEnum[k]] = k
return m
}, {})
// type: 1/2/3/4
// messageFlow
// version 1 byte + type 1 byte + id 36 byte + waitIntercept 1 byte + content left bytes
export const parseMessage = data => {
if (data.byteLength < 39) return null
const meta = new Int8Array(data.slice(0, 39))
const version = meta[0]
if (version !== 1) return null
const type = meta[1]
if (!allMessageBytes.includes(type)) return null
const id = new TextDecoder().decode(data.slice(2, 38))
const waitIntercept = meta[38] === 1
const resp = {
type: messageByteMap[type],
id,
waitIntercept,
}
if (data.byteLength === 39) return resp
if (type === messageEnum['requestBody'] || type === messageEnum['responseBody']) {
resp.content = data.slice(39)
return resp
}
let content = new TextDecoder().decode(data.slice(39))
try {
content = JSON.parse(content)
} catch (err) {
return null
}
resp.content = content
return resp
}
export const sendMessageEnum = {
'changeRequest': 11,
'changeResponse': 12,
'changeBreakPointRules': 21,
}
// type: 11/12
// messageEdit
// version 1 byte + type 1 byte + id 36 byte + header len 4 byte + header content bytes + body len 4 byte + [body content bytes]
export const buildMessageEdit = (messageType, flow) => {
let header, body
if (messageType === sendMessageEnum.changeRequest) {
({ body, ...header } = flow.request)
} else if (messageType === sendMessageEnum.changeResponse) {
({ body, ...header } = flow.response)
} else {
throw new Error('invalid message type')
}
const headerBytes = new TextEncoder().encode(JSON.stringify(header))
const len = 2 + 36 + 4 + headerBytes.byteLength + 4 + body.byteLength
const data = new ArrayBuffer(len)
const view = new Uint8Array(data)
view[0] = 1
view[1] = messageType
view.set(new TextEncoder().encode(flow.id), 3)
view.set(headerBytes, 2 + 36 + 4)
view.set(body, 2 + 36 + 4 + headerBytes.byteLength + 4)
const view2 = new DataView(data)
view2.setUint32(2 + 36, headerBytes.byteLength)
view2.setUint32(2 + 36 + 4 + headerBytes.byteLength, body.byteLength)
return view
}
// type: 21
// messageMeta
// version 1 byte + type 1 byte + content left bytes
export const buildMessageMeta = (messageType, rules) => {
if (messageType !== sendMessageEnum.changeBreakPointRules) {
throw new Error('invalid message type')
}
const rulesBytes = new TextEncoder().encode(JSON.stringify(rules))
const view = new Uint8Array(2 + rulesBytes.byteLength)
view[0] = 1
view[1] = messageType
view.set(rulesBytes, 2)
return view
}

@ -24,65 +24,3 @@ export const getSize = response => {
if (len < 1024*1024) return `${(len/1024).toFixed(2)} KB`
return `${(len/(1024*1024)).toFixed(2)} MB`
}
const messageEnum = {
'request': 1,
'requestBody': 2,
'response': 3,
'responseBody': 4,
}
const allMessageBytes = Object.keys(messageEnum).map(k => messageEnum[k])
const messageByteMap = Object.keys(messageEnum).reduce((m, k) => {
m[messageEnum[k]] = k
return m
}, {})
export const parseMessage = data => {
if (data.byteLength < 39) return null
const meta = new Int8Array(data.slice(0, 3))
const version = meta[0]
if (version !== 1) return null
const type = meta[1]
if (!allMessageBytes.includes(type)) return null
const id = new TextDecoder().decode(data.slice(3, 39))
const resp = {
type: messageByteMap[type],
id,
waitIntercept: meta[2] === 1,
}
if (data.byteLength === 39) return resp
if (type === messageEnum['requestBody'] || type === messageEnum['responseBody']) {
resp.content = data.slice(39)
return resp
}
let content = new TextDecoder().decode(data.slice(39))
try {
content = JSON.parse(content)
} catch (err) {
return null
}
resp.content = content
return resp
}
/**
*
* @param {number} messageType
* @param {string} id
* @param {string} content
*/
export const buildMessage = (messageType, id, content) => {
content = new TextEncoder().encode(content)
const data = new Uint8Array(39 + content.byteLength)
data[0] = 1
data[1] = messageType
data[2] = 0
data.set(new TextEncoder().encode(id), 3)
data.set(content, 39)
return data
}

Loading…
Cancel
Save