import React from 'react' import Table from 'react-bootstrap/Table' import Form from 'react-bootstrap/Form' import Button from 'react-bootstrap/Button' import { FlowManager } from './flow' import './App.css' const isTextResponse = response => { if (!response) return false if (!response.header) return false if (!response.header['Content-Type']) return false 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 < 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 (![1, 2, 3].includes(type)) return null const id = new TextDecoder().decode(data.slice(3, 39)) const resp = { type: ['request', 'response', 'responseBody'][type-1], id, waitIntercept: meta[2] === 1, } if (data.byteLength === 39) return resp if (type === 3) { 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 */ 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 } class App extends React.Component { constructor(props) { super(props) this.flowMgr = new FlowManager() this.state = { flows: this.flowMgr.showList(), flow: null, flowTab: 'Headers', // Headers, Preview, Response interceptUriInputing: '', interceptUri: '', } this.ws = null } componentDidMount() { this.initWs() } componentWillUnmount() { if (this.ws) { this.ws.close() } } initWs() { if (this.ws) return let host; if (process.env.NODE_ENV === 'development') { host = 'localhost:9081' } else { host = new URL(document.URL).host } this.ws = new WebSocket(`ws://${host}/echo`) this.ws.binaryType = 'arraybuffer' this.ws.onopen = () => { console.log('OPEN') } this.ws.onclose = () => { console.log('CLOSE') } this.ws.onmessage = evt => { const msg = parseMessage(evt.data) if (!msg) { console.error('parse error:', evt.data) return } console.log('msg:', msg) if (msg.type === 'request') { const flow = { id: msg.id, request: msg.content, waitIntercept: msg.waitIntercept } this.flowMgr.add(flow) this.setState({ flows: this.flowMgr.showList() }) } else if (msg.type === 'response') { const flow = this.flowMgr.get(msg.id) if (!flow) return flow.waitIntercept = msg.waitIntercept flow.response = msg.content this.setState({ flows: this.state.flows }) } else if (msg.type === 'responseBody') { const flow = this.flowMgr.get(msg.id) if (!flow || !flow.response) return flow.waitIntercept = msg.waitIntercept flow.response.body = msg.content this.setState({ flows: this.state.flows }) } } this.ws.onerror = evt => { console.log('ERROR:', evt) } // this.ws.send('msg') // this.ws.close() } renderFlow() { const { flow, flowTab } = this.state if (!flow) return null const request = flow.request const response = flow.response || {} return (
General
Request URL: {request.url}
Request Method: {request.method}
Status Code: {`${response.statusCode || '(pending)'}`}
Response Headers
{key}: {response.header[key].join(' ')}
) }) }Request Headers
{key}: {request.header[key].join(' ')}
) }) }No | Host | Path | Method | Status | Size |
---|---|---|---|---|---|
{f.no} | {host} | {path} | {request.method} | {response.statusCode || '(pending)'} | {getSize(response)} |