You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1 line
48 KiB
Plaintext
1 line
48 KiB
Plaintext
{"version":3,"sources":["message.ts","components/BreakPoint.tsx","utils.ts","components/EditFlow.tsx","components/FlowPreview.tsx","flow.ts","App.tsx","reportWebVitals.ts","index.tsx"],"names":["MessageType","BreakPoint","props","state","show","rule","method","url","action","haveRules","handleClose","bind","handleShow","handleSave","this","setState","rules","push","onSave","length","variant","Button","size","onClick","Modal","onHide","Header","closeButton","Title","Body","Form","Group","as","Row","Label","column","sm","Col","Control","value","onChange","e","target","parseInt","Footer","React","Component","isTextBody","payload","header","test","join","Flow","msg","no","id","waitIntercept","request","response","_host","_path","_size","curNo","content","URL","body","host","path","statusCode","String","slice","pathname","search","len","byteLength","isNaN","toFixed","getSize","SendMessageType","allMessageBytes","REQUEST","REQUEST_BODY","RESPONSE","RESPONSE_BODY","buildMessageEdit","messageType","flow","DROP_REQUEST","DROP_RESPONSE","view","Uint8Array","set","TextEncoder","encode","CHANGE_REQUEST","CHANGE_RESPONSE","Error","ArrayBuffer","bodyLen","headerBytes","JSON","stringify","data","view2","DataView","setUint32","EditFlow","alertMsg","firstLine","headerLines","Object","keys","map","key","valstr","bodyLines","TextDecoder","decode","stringifyRequest","stringifyResponse","when","firstIndex","indexOf","split","secondIndex","vals","proto","parseRequest","showAlert","onChangeRequest","parseResponse","onChangeResponse","className","msgType","onMessage","rows","Alert","FlowPreview","nextProps","isSelected","objA","objB","keysA","keysB","i","undefined","shallowEqual","fp","classNames","onShowDetail","FlowManager","items","_map","filterText","filterTimer","num","max","Map","filter","item","includes","oldest","shift","delete","get","text","callback","clearTimeout","setTimeout","App","flowMgr","ws","flows","showList","flowTab","initWs","close","document","WebSocket","binaryType","onopen","console","log","onclose","onmessage","evt","meta","Int8Array","type","resp","contentStr","parse","err","parseMessage","add","addRequestBody","addResponse","addResponseBody","error","onerror","send","style","padding","clear","placeholder","changeFilterLazy","CHANGE_BREAK_POINT_RULES","rulesBytes","buildMessageMeta","Table","striped","bordered","f","preview","renderFlow","reportWebVitals","onPerfEntry","Function","then","getCLS","getFID","getFCP","getLCP","getTTFB","ReactDOM","render","StrictMode","getElementById"],"mappings":"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","file":"static/js/main.4248f977.chunk.js","sourcesContent":["import { getSize } from './utils'\n\nexport enum MessageType {\n REQUEST = 1,\n REQUEST_BODY = 2,\n RESPONSE = 3,\n RESPONSE_BODY = 4,\n}\n\nexport type Header = Record<string, string[]>\n\nexport interface IRequest {\n method: string\n url: string\n proto: string\n header: Header\n body?: ArrayBuffer\n}\n\nexport interface IResponse {\n statusCode: number\n header: Header\n body?: ArrayBuffer\n}\n\nexport interface IMessage {\n type: MessageType\n id: string\n waitIntercept: boolean\n content?: ArrayBuffer | IRequest | IResponse\n}\n\nexport interface IFlowPreview {\n no: number\n id: string\n waitIntercept: boolean\n host: string\n path: string\n method: string\n statusCode: string\n size: string\n}\n\nexport class Flow {\n public no: number\n public id: string\n public waitIntercept: boolean\n public request: IRequest\n public response: IResponse | null = null\n\n private url: URL\n private _host = ''\n private _path = ''\n private _size = ''\n\n public static curNo = 0\n\n constructor(msg: IMessage) {\n this.no = ++Flow.curNo\n this.id = msg.id\n this.waitIntercept = msg.waitIntercept\n this.request = msg.content as IRequest\n\n this.url = new URL(this.request.url)\n }\n\n public addRequestBody(msg: IMessage): Flow {\n this.waitIntercept = msg.waitIntercept\n this.request.body = msg.content as ArrayBuffer\n return this\n }\n\n public addResponse(msg: IMessage): Flow {\n this.waitIntercept = msg.waitIntercept\n this.response = msg.content as IResponse\n return this\n }\n\n public addResponseBody(msg: IMessage): Flow {\n this.waitIntercept = msg.waitIntercept\n if (this.response) this.response.body = msg.content as ArrayBuffer\n return this\n }\n\n public preview(): IFlowPreview {\n return {\n no: this.no,\n id: this.id,\n waitIntercept: this.waitIntercept,\n host: this.host,\n path: this.path,\n method: this.request.method,\n statusCode: this.response ? String(this.response.statusCode) : '(pending)',\n size: this.size,\n }\n }\n\n private get host(): string {\n if (this._host) return this._host\n let _host = this.url.host\n if (_host.length > 35) _host = _host.slice(0, 35) + '...'\n this._host = _host\n return _host\n }\n\n private get path(): string {\n if (this._path) return this._path\n let _path = this.url.pathname + this.url.search\n if (_path.length > 65) _path = _path.slice(0, 65) + '...'\n this._path = _path\n return _path\n }\n\n private get size(): string {\n if (!this.response) return '0'\n if (!this.response.header) return '0'\n if (this._size) return this._size\n\n this._size = getSize(this.response)\n return this._size\n }\n}\n\nconst allMessageBytes = [\n MessageType.REQUEST,\n MessageType.REQUEST_BODY,\n MessageType.RESPONSE,\n MessageType.RESPONSE_BODY,\n]\n\n\n// type: 1/2/3/4\n// messageFlow\n// version 1 byte + type 1 byte + id 36 byte + waitIntercept 1 byte + content left bytes\nexport const parseMessage = (data: ArrayBuffer): IMessage | null => {\n if (data.byteLength < 39) return null\n const meta = new Int8Array(data.slice(0, 39))\n const version = meta[0]\n if (version !== 1) return null\n const type = meta[1] as MessageType\n if (!allMessageBytes.includes(type)) return null\n const id = new TextDecoder().decode(data.slice(2, 38))\n const waitIntercept = meta[38] === 1\n\n const resp: IMessage = {\n type,\n id,\n waitIntercept,\n }\n if (data.byteLength === 39) return resp\n if (type === MessageType.REQUEST_BODY || type === MessageType.RESPONSE_BODY) {\n resp.content = data.slice(39)\n return resp\n }\n\n const contentStr = new TextDecoder().decode(data.slice(39))\n let content: any\n try {\n content = JSON.parse(contentStr)\n } catch (err) {\n return null\n }\n\n resp.content = content\n return resp\n}\n\n\nexport enum SendMessageType {\n CHANGE_REQUEST = 11,\n CHANGE_RESPONSE = 12,\n DROP_REQUEST = 13,\n DROP_RESPONSE = 14,\n CHANGE_BREAK_POINT_RULES = 21,\n}\n\n// type: 11/12/13/14\n// messageEdit\n// version 1 byte + type 1 byte + id 36 byte + header len 4 byte + header content bytes + body len 4 byte + [body content bytes]\nexport const buildMessageEdit = (messageType: SendMessageType, flow: Flow) => {\n if (messageType === SendMessageType.DROP_REQUEST || messageType === SendMessageType.DROP_RESPONSE) {\n const view = new Uint8Array(38)\n view[0] = 1\n view[1] = messageType\n view.set(new TextEncoder().encode(flow.id), 2)\n return view\n }\n\n let header: Omit<IRequest, 'body'> | Omit<IResponse, 'body'>\n let body: ArrayBuffer | Uint8Array | undefined\n\n if (messageType === SendMessageType.CHANGE_REQUEST) {\n ({ body, ...header } = flow.request)\n } else if (messageType === SendMessageType.CHANGE_RESPONSE) {\n ({ body, ...header } = flow.response as IResponse)\n } else {\n throw new Error('invalid message type')\n }\n\n if (body instanceof ArrayBuffer) body = new Uint8Array(body)\n const bodyLen = (body && body.byteLength) ? body.byteLength : 0\n\n if ('Content-Encoding' in header.header) delete header.header['Content-Encoding']\n if ('Transfer-Encoding' in header.header) delete header.header['Transfer-Encoding']\n header.header['Content-Length'] = [String(bodyLen)]\n\n const headerBytes = new TextEncoder().encode(JSON.stringify(header))\n const len = 2 + 36 + 4 + headerBytes.byteLength + 4 + bodyLen\n const data = new ArrayBuffer(len)\n const view = new Uint8Array(data)\n view[0] = 1\n view[1] = messageType\n view.set(new TextEncoder().encode(flow.id), 2)\n view.set(headerBytes, 2 + 36 + 4)\n if (bodyLen) view.set(body as Uint8Array, 2 + 36 + 4 + headerBytes.byteLength + 4)\n\n const view2 = new DataView(data)\n view2.setUint32(2 + 36, headerBytes.byteLength)\n view2.setUint32(2 + 36 + 4 + headerBytes.byteLength, bodyLen)\n\n return view\n}\n\n\n// type: 21\n// messageMeta\n// version 1 byte + type 1 byte + content left bytes\nexport const buildMessageMeta = (messageType: SendMessageType, rules: any) => {\n if (messageType !== SendMessageType.CHANGE_BREAK_POINT_RULES) {\n throw new Error('invalid message type')\n }\n\n const rulesBytes = new TextEncoder().encode(JSON.stringify(rules))\n const view = new Uint8Array(2 + rulesBytes.byteLength)\n view[0] = 1\n view[1] = messageType\n view.set(rulesBytes, 2)\n\n return view\n}\n","import React from 'react'\nimport Button from 'react-bootstrap/Button'\nimport Modal from 'react-bootstrap/Modal'\nimport Form from 'react-bootstrap/Form'\nimport Row from 'react-bootstrap/Row'\nimport Col from 'react-bootstrap/Col'\n\ntype Method = 'ALL' | 'GET' | 'POST' | 'PUT' | 'DELETE' | ''\ntype Action = 1 | 2 | 3\ninterface IRule {\n method: Method\n url: string\n action: Action\n}\n\ninterface IState {\n show: boolean\n rule: IRule\n haveRules: boolean\n}\n\ninterface IProps {\n onSave: (rules: IRule[]) => void\n}\n\nclass BreakPoint extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props)\n\n this.state = {\n show: false,\n\n rule: {\n method: 'ALL',\n url: '',\n action: 1,\n },\n\n haveRules: false,\n }\n\n this.handleClose = this.handleClose.bind(this)\n this.handleShow = this.handleShow.bind(this)\n this.handleSave = this.handleSave.bind(this)\n }\n\n handleClose() {\n this.setState({ show: false })\n }\n\n handleShow() {\n this.setState({ show: true })\n }\n\n handleSave() {\n const { rule } = this.state\n const rules: IRule[] = []\n if (rule.url) {\n rules.push({\n method: rule.method === 'ALL' ? '' : rule.method,\n url: rule.url,\n action: rule.action,\n })\n }\n\n this.props.onSave(rules)\n this.handleClose()\n\n this.setState({ haveRules: rules.length ? true : false })\n }\n\n render() {\n const { rule, haveRules } = this.state\n const variant = haveRules ? 'success' : 'primary'\n\n return (\n <div>\n <Button variant={variant} size=\"sm\" onClick={this.handleShow}>BreakPoint</Button>\n\n <Modal show={this.state.show} onHide={this.handleClose}>\n <Modal.Header closeButton>\n <Modal.Title>Set BreakPoint</Modal.Title>\n </Modal.Header>\n\n <Modal.Body>\n <Form.Group as={Row}>\n <Form.Label column sm={2}>Method</Form.Label>\n <Col sm={10}>\n <Form.Control as=\"select\" value={rule.method} onChange={e => { this.setState({ rule: { ...rule, method: e.target.value as Method } }) }}>\n <option>ALL</option>\n <option>GET</option>\n <option>POST</option>\n <option>PUT</option>\n <option>DELETE</option>\n </Form.Control>\n </Col>\n </Form.Group>\n\n <Form.Group as={Row}>\n <Form.Label column sm={2}>URL</Form.Label>\n <Col sm={10}><Form.Control value={rule.url} onChange={e => { this.setState({ rule: { ...rule, url: e.target.value } }) }} /></Col>\n </Form.Group>\n\n <Form.Group as={Row}>\n <Form.Label column sm={2}>Action</Form.Label>\n <Col sm={10}>\n <Form.Control as=\"select\" value={rule.action} onChange={e => { this.setState({ rule: { ...rule, action: parseInt(e.target.value) as Action } }) }}>\n <option value=\"1\">Request</option>\n <option value=\"2\">Response</option>\n <option value=\"3\">Both</option>\n </Form.Control>\n </Col>\n </Form.Group>\n </Modal.Body>\n\n <Modal.Footer>\n <Button variant=\"secondary\" onClick={this.handleClose}>\n Close\n </Button>\n <Button variant=\"primary\" onClick={this.handleSave}>\n Save\n </Button>\n </Modal.Footer>\n </Modal>\n </div>\n )\n }\n}\n\nexport default BreakPoint\n","import { IRequest, IResponse } from './message'\n\nexport const isTextBody = (payload: IRequest | IResponse) => {\n if (!payload) return false\n if (!payload.header) return false\n if (!payload.header['Content-Type']) return false\n\n return /text|javascript|json/.test(payload.header['Content-Type'].join(''))\n}\n\nexport const getSize = (response: IResponse) => {\n if (!response) return '0'\n if (!response.header) return '0'\n\n let len\n if (response.header['Content-Length']) {\n len = parseInt(response.header['Content-Length'][0])\n } else if (response && response.body) {\n len = response.body.byteLength\n }\n if (!len) return '0'\n if (isNaN(len)) return '0'\n if (len <= 0) return '0'\n\n if (len < 1024) return `${len} B`\n if (len < 1024*1024) return `${(len/1024).toFixed(2)} KB`\n return `${(len/(1024*1024)).toFixed(2)} MB`\n}\n\nexport const shallowEqual = (objA: any, objB: any) => {\n if (objA === objB) return true\n\n const keysA = Object.keys(objA)\n const keysB = Object.keys(objB)\n if (keysA.length !== keysB.length) return false\n\n for (let i = 0; i < keysA.length; i++) {\n const key = keysA[i]\n if (objB[key] === undefined || objA[key] !== objB[key]) return false\n }\n return true\n}\n","import React from 'react'\nimport Button from 'react-bootstrap/Button'\nimport Modal from 'react-bootstrap/Modal'\nimport Form from 'react-bootstrap/Form'\nimport Alert from 'react-bootstrap/Alert'\n\nimport { SendMessageType, buildMessageEdit, IRequest, IResponse, Header, Flow } from '../message'\nimport { isTextBody } from '../utils'\n\n\nconst stringifyRequest = (request: IRequest) => {\n const firstLine = `${request.method} ${request.url}`\n const headerLines = Object.keys(request.header).map(key => {\n const valstr = request.header[key].join(' \\t ') // for parse convenience\n return `${key}: ${valstr}`\n }).join('\\n')\n\n let bodyLines = ''\n if (request.body && isTextBody(request)) bodyLines = new TextDecoder().decode(request.body)\n\n return `${firstLine}\\n\\n${headerLines}\\n\\n${bodyLines}`\n}\n\nconst parseRequest = (content: string): IRequest | undefined => {\n const firstIndex = content.indexOf('\\n\\n')\n if (firstIndex <= 0) return\n\n const firstLine = content.slice(0, firstIndex)\n const [method, url] = firstLine.split(' ')\n if (!method || !url) return\n\n const secondIndex = content.indexOf('\\n\\n', firstIndex + 2)\n if (secondIndex <= 0) return\n const headerLines = content.slice(firstIndex + 2, secondIndex)\n const header: Header = {}\n for (const line of headerLines.split('\\n')) {\n const [key, vals] = line.split(': ')\n if (!key || !vals) return\n header[key] = vals.split(' \\t ')\n }\n\n const bodyLines = content.slice(secondIndex + 2)\n let body: ArrayBuffer | undefined\n if (bodyLines) body = new TextEncoder().encode(bodyLines)\n\n return {\n method,\n url,\n proto: '',\n header,\n body,\n }\n}\n\nconst stringifyResponse = (response: IResponse) => {\n const firstLine = `${response.statusCode}`\n const headerLines = Object.keys(response.header).map(key => {\n const valstr = response.header[key].join(' \\t ') // for parse convenience\n return `${key}: ${valstr}`\n }).join('\\n')\n\n let bodyLines = ''\n if (response.body && isTextBody(response)) bodyLines = new TextDecoder().decode(response.body)\n\n return `${firstLine}\\n\\n${headerLines}\\n\\n${bodyLines}`\n}\n\nconst parseResponse = (content: string): IResponse | undefined => {\n const firstIndex = content.indexOf('\\n\\n')\n if (firstIndex <= 0) return\n\n const firstLine = content.slice(0, firstIndex)\n const statusCode = parseInt(firstLine)\n if (isNaN(statusCode)) return\n\n const secondIndex = content.indexOf('\\n\\n', firstIndex + 2)\n if (secondIndex <= 0) return\n const headerLines = content.slice(firstIndex + 2, secondIndex)\n const header: Header = {}\n for (const line of headerLines.split('\\n')) {\n const [key, vals] = line.split(': ')\n if (!key || !vals) return\n header[key] = vals.split(' \\t ')\n }\n\n const bodyLines = content.slice(secondIndex + 2)\n let body: ArrayBuffer | undefined\n if (bodyLines) body = new TextEncoder().encode(bodyLines)\n\n return {\n statusCode,\n header,\n body,\n }\n}\n\n\ninterface IProps {\n flow: Flow\n onChangeRequest: (request: IRequest) => void\n onChangeResponse: (response: IResponse) => void\n onMessage: (msg: ArrayBufferLike) => void\n}\n\ninterface IState {\n show: boolean\n alertMsg: string\n content: string\n}\n\nclass EditFlow extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props)\n\n this.state = {\n show: false,\n alertMsg: '',\n content: '',\n }\n\n this.handleClose = this.handleClose.bind(this)\n this.handleShow = this.handleShow.bind(this)\n this.handleSave = this.handleSave.bind(this)\n }\n\n showAlert(msg: string) {\n this.setState({ alertMsg: msg })\n }\n\n handleClose() {\n this.setState({ show: false })\n }\n\n handleShow() {\n const { flow } = this.props\n const when = flow.response ? 'response' : 'request'\n\n let content = ''\n if (when === 'request') {\n content = stringifyRequest(flow.request)\n } else {\n content = stringifyResponse(flow.response as IResponse)\n }\n\n this.setState({ show: true, alertMsg: '', content })\n }\n\n handleSave() {\n const { flow } = this.props\n const when = flow.response ? 'response' : 'request'\n\n const { content } = this.state\n\n if (when === 'request') {\n const request = parseRequest(content)\n if (!request) {\n this.showAlert('parse error')\n return\n }\n\n this.props.onChangeRequest(request)\n this.handleClose()\n } else {\n const response = parseResponse(content)\n if (!response) {\n this.showAlert('parse error')\n return\n }\n\n this.props.onChangeResponse(response)\n this.handleClose()\n }\n }\n\n render() {\n const { flow } = this.props\n if (!flow.waitIntercept) return null\n\n const { alertMsg } = this.state\n\n const when = flow.response ? 'response' : 'request'\n\n return (\n <div className=\"flow-wait-area\">\n\n <Button size=\"sm\" onClick={this.handleShow}>Edit</Button>\n\n <Button size=\"sm\" onClick={() => {\n const msgType = when === 'response' ? SendMessageType.CHANGE_RESPONSE : SendMessageType.CHANGE_REQUEST\n const msg = buildMessageEdit(msgType, flow)\n this.props.onMessage(msg)\n }}>Continue</Button>\n\n <Button size=\"sm\" onClick={() => {\n const msgType = when === 'response' ? SendMessageType.DROP_RESPONSE : SendMessageType.DROP_REQUEST\n const msg = buildMessageEdit(msgType, flow)\n this.props.onMessage(msg)\n }}>Drop</Button>\n\n\n <Modal size=\"lg\" show={this.state.show} onHide={this.handleClose}>\n <Modal.Header closeButton>\n <Modal.Title>Edit {when === 'request' ? 'Request' : 'Response'}</Modal.Title>\n </Modal.Header>\n\n <Modal.Body>\n <Form.Group>\n <Form.Control as=\"textarea\" rows={10} value={this.state.content} onChange={e => { this.setState({ content: e.target.value }) }} />\n </Form.Group>\n {\n !alertMsg ? null : <Alert variant=\"danger\">{alertMsg}</Alert>\n }\n </Modal.Body>\n\n <Modal.Footer>\n <Button variant=\"secondary\" onClick={this.handleClose}>\n Close\n </Button>\n <Button variant=\"primary\" onClick={this.handleSave}>\n Save\n </Button>\n </Modal.Footer>\n </Modal>\n\n </div>\n )\n }\n}\n\nexport default EditFlow\n","import React from 'react'\nimport { IFlowPreview } from '../message'\nimport { shallowEqual } from '../utils'\n\ninterface IProps {\n flow: IFlowPreview\n isSelected: boolean\n onShowDetail: () => void\n}\n\nclass FlowPreview extends React.Component<IProps> {\n shouldComponentUpdate(nextProps: IProps) {\n if (nextProps.isSelected === this.props.isSelected && shallowEqual(nextProps.flow, this.props.flow)) {\n return false\n }\n return true\n }\n\n render() {\n const fp = this.props.flow\n\n const classNames = []\n if (this.props.isSelected) classNames.push('tr-selected')\n if (fp.waitIntercept) classNames.push('tr-wait-intercept')\n\n return (\n <tr className={classNames.length ? classNames.join(' ') : undefined}\n onClick={() => {\n this.props.onShowDetail()\n }}\n >\n <td>{fp.no}</td>\n <td>{fp.host}</td>\n <td>{fp.path}</td>\n <td>{fp.method}</td>\n <td>{fp.statusCode}</td>\n <td>{fp.size}</td>\n </tr>\n )\n }\n}\n\nexport default FlowPreview\n","import { Flow } from './message'\n\nexport class FlowManager {\n private items: Flow[]\n private _map: Map<string, Flow>\n private filterText: string\n private filterTimer: number | null\n private num: number\n private max: number\n\n constructor() {\n this.items = []\n this._map = new Map()\n this.filterText = ''\n this.filterTimer = null\n this.num = 0\n\n this.max = 1000\n }\n\n showList() {\n if (!this.filterText) return this.items\n return this.items.filter(item => {\n return item.request.url.includes(this.filterText)\n })\n }\n\n add(item: Flow) {\n item.no = ++this.num\n this.items.push(item)\n this._map.set(item.id, item)\n\n if (this.items.length > this.max) {\n const oldest = this.items.shift()\n if (oldest) this._map.delete(oldest.id)\n }\n }\n\n get(id: string) {\n return this._map.get(id)\n }\n\n changeFilter(text: string) {\n this.filterText = text\n }\n\n changeFilterLazy(text: string, callback: () => void) {\n if (this.filterTimer) {\n clearTimeout(this.filterTimer)\n this.filterTimer = null\n }\n\n this.filterTimer = setTimeout(() => {\n this.filterText = text\n callback()\n }, 300) as any\n }\n\n clear() {\n this.items = []\n this._map = new Map()\n }\n}\n","import React from 'react'\nimport Table from 'react-bootstrap/Table'\nimport Form from 'react-bootstrap/Form'\nimport Button from 'react-bootstrap/Button'\nimport './App.css'\n\nimport BreakPoint from './components/BreakPoint'\nimport EditFlow from './components/EditFlow'\nimport FlowPreview from './components/FlowPreview'\n\nimport { FlowManager } from './flow'\nimport { isTextBody } from './utils'\nimport { parseMessage, SendMessageType, buildMessageMeta, Flow, MessageType, IResponse } from './message'\n\ninterface IState {\n flows: Flow[]\n flow: Flow | null\n flowTab: 'Headers' | 'Preview' | 'Response'\n}\n\nclass App extends React.Component<any, IState> {\n private flowMgr: FlowManager\n private ws: WebSocket | null\n\n constructor(props: any) {\n super(props)\n\n this.flowMgr = new FlowManager()\n\n this.state = {\n flows: this.flowMgr.showList(),\n flow: null,\n\n flowTab: 'Headers', // Headers, Preview, Response\n }\n\n this.ws = null\n }\n\n componentDidMount() {\n this.initWs()\n }\n\n componentWillUnmount() {\n if (this.ws) {\n this.ws.close()\n }\n }\n\n initWs() {\n if (this.ws) return\n\n let host\n if (process.env.NODE_ENV === 'development') {\n host = 'localhost:9081'\n } else {\n host = new URL(document.URL).host\n }\n this.ws = new WebSocket(`ws://${host}/echo`)\n this.ws.binaryType = 'arraybuffer'\n this.ws.onopen = () => { console.log('OPEN') }\n this.ws.onclose = () => { console.log('CLOSE') }\n this.ws.onmessage = evt => {\n const msg = parseMessage(evt.data)\n if (!msg) {\n console.error('parse error:', evt.data)\n return\n }\n // console.log('msg:', msg)\n\n if (msg.type === MessageType.REQUEST) {\n const flow = new Flow(msg)\n this.flowMgr.add(flow)\n this.setState({ flows: this.flowMgr.showList() })\n }\n else if (msg.type === MessageType.REQUEST_BODY) {\n const flow = this.flowMgr.get(msg.id)\n if (!flow) return\n flow.addRequestBody(msg)\n this.setState({ flows: this.state.flows })\n }\n else if (msg.type === MessageType.RESPONSE) {\n const flow = this.flowMgr.get(msg.id)\n if (!flow) return\n flow.addResponse(msg)\n this.setState({ flows: this.state.flows })\n }\n else if (msg.type === MessageType.RESPONSE_BODY) {\n const flow = this.flowMgr.get(msg.id)\n if (!flow || !flow.response) return\n flow.addResponseBody(msg)\n this.setState({ flows: this.state.flows })\n }\n }\n this.ws.onerror = evt => {\n console.log('ERROR:', evt)\n }\n }\n\n renderFlow() {\n const { flow, flowTab } = this.state\n if (!flow) return null\n\n const request = flow.request\n const response: IResponse = (flow.response || {}) as any\n\n return (\n <div className=\"flow-detail\">\n <div className=\"header-tabs\">\n <span onClick={() => { this.setState({ flow: null }) }}>x</span>\n <span className={flowTab === 'Headers' ? 'selected' : undefined} onClick={() => { this.setState({ flowTab: 'Headers' }) }}>Headers</span>\n <span className={flowTab === 'Preview' ? 'selected' : undefined} onClick={() => { this.setState({ flowTab: 'Preview' }) }}>Preview</span>\n <span className={flowTab === 'Response' ? 'selected' : undefined} onClick={() => { this.setState({ flowTab: 'Response' }) }}>Response</span>\n\n <EditFlow\n flow={flow}\n onChangeRequest={request => {\n flow.request.method = request.method\n flow.request.url = request.url\n flow.request.header = request.header\n if (isTextBody(flow.request)) flow.request.body = request.body\n this.setState({ flows: this.state.flows })\n }}\n onChangeResponse={response => {\n if (!flow.response) flow.response = {} as IResponse\n\n flow.response.statusCode = response.statusCode\n flow.response.header = response.header\n if (isTextBody(flow.response)) flow.response.body = response.body\n this.setState({ flows: this.state.flows })\n }}\n onMessage={msg => {\n if (this.ws) this.ws.send(msg)\n flow.waitIntercept = false\n this.setState({ flows: this.state.flows })\n }}\n />\n\n </div>\n\n <div style={{ padding: '20px' }}>\n {\n !(flowTab === 'Headers') ? null :\n <div>\n <div className=\"header-block\">\n <p>General</p>\n <div className=\"header-block-content\">\n <p>Request URL: {request.url}</p>\n <p>Request Method: {request.method}</p>\n <p>Status Code: {`${response.statusCode || '(pending)'}`}</p>\n </div>\n </div>\n\n {\n !(response.header) ? null :\n <div className=\"header-block\">\n <p>Response Headers</p>\n <div className=\"header-block-content\">\n {\n Object.keys(response.header).map(key => {\n return (\n <p key={key}>{key}: {response.header[key].join(' ')}</p>\n )\n })\n }\n </div>\n </div>\n }\n\n <div className=\"header-block\">\n <p>Request Headers</p>\n <div className=\"header-block-content\">\n {\n !(request.header) ? null :\n Object.keys(request.header).map(key => {\n return (\n <p key={key}>{key}: {request.header[key].join(' ')}</p>\n )\n })\n }\n </div>\n </div>\n\n {\n !(request.body && request.body.byteLength) ? null :\n <div className=\"header-block\">\n <p>Request Body</p>\n <div className=\"header-block-content\">\n <p>\n {\n !(isTextBody(request)) ? 'Not text' :\n new TextDecoder().decode(request.body)\n }\n </p>\n </div>\n </div>\n }\n\n </div>\n }\n\n {\n !(flowTab === 'Response') ? null :\n !(response.body && response.body.byteLength) ? <div>No response</div> :\n !(isTextBody(response)) ? <div>Not text response</div> :\n <div>\n {new TextDecoder().decode(response.body)}\n </div>\n }\n </div>\n\n </div>\n )\n }\n\n render() {\n const { flows } = this.state\n return (\n <div className=\"main-table-wrap\">\n <div className=\"top-control\">\n <div><Button size=\"sm\" onClick={() => {\n this.flowMgr.clear()\n this.setState({ flows: this.flowMgr.showList(), flow: null })\n }}>Clear</Button></div>\n <div>\n <Form.Control\n size=\"sm\" placeholder=\"Filter\"\n onChange={(e) => {\n const value = e.target.value\n this.flowMgr.changeFilterLazy(value, () => {\n this.setState({ flows: this.flowMgr.showList() })\n })\n }}\n >\n </Form.Control>\n </div>\n\n <BreakPoint onSave={rules => {\n const msg = buildMessageMeta(SendMessageType.CHANGE_BREAK_POINT_RULES, rules)\n if (this.ws) this.ws.send(msg)\n }} />\n </div>\n\n <Table striped bordered size=\"sm\">\n <thead>\n <tr>\n <th>No</th>\n <th>Host</th>\n <th>Path</th>\n <th>Method</th>\n <th>Status</th>\n <th>Size</th>\n </tr>\n </thead>\n <tbody>\n {\n flows.map(f => {\n const fp = f.preview()\n\n return (\n <FlowPreview\n key={fp.id}\n flow={fp}\n isSelected={(this.state.flow && this.state.flow.id === fp.id) ? true : false}\n onShowDetail={() => {\n this.setState({ flow: f })\n }}\n />\n )\n })\n }\n </tbody>\n </Table>\n\n {this.renderFlow()}\n </div>\n )\n }\n}\n\nexport default App\n","import { ReportHandler } from 'web-vitals'\n\nconst reportWebVitals = (onPerfEntry?: ReportHandler) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry)\n getFID(onPerfEntry)\n getFCP(onPerfEntry)\n getLCP(onPerfEntry)\n getTTFB(onPerfEntry)\n })\n }\n}\n\nexport default reportWebVitals\n","import React from 'react'\nimport ReactDOM from 'react-dom'\nimport 'bootstrap/dist/css/bootstrap.min.css'\nimport App from './App'\nimport reportWebVitals from './reportWebVitals'\n\nReactDOM.render(\n <React.StrictMode>\n <App />\n </React.StrictMode>,\n document.getElementById('root')\n)\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals()\n"],"sourceRoot":""} |