this.max){var t=this.items.shift();this._map.delete(t.id)}}},{key:"get",value:function(e){return this._map.get(e)}},{key:"changeFilter",value:function(e){this.filterText=e}},{key:"changeFilterLazy",value:function(e,t){var n=this;this.filterTimer&&(clearTimeout(this.filterTimer),this.filterTimer=null),this.filterTimer=setTimeout((function(){n.filterText=e,t()}),300)}},{key:"clear",value:function(){this.items=[],this._map=new Map}}]),e}(),y=function(e){return!!e&&(!!e.header&&(!!e.header["Content-Type"]&&/text|javascript|json/.test(e.header["Content-Type"].join(""))))},g=function(e){return e&&e.header?(e.header["Content-Length"]?t=parseInt(e.header["Content-Length"][0]):e&&e.body&&(t=e.body.byteLength),t?isNaN(t)||t<=0?"0":t<1024?"".concat(t," B"):t<1048576?"".concat((t/1024).toFixed(2)," KB"):"".concat((t/1048576).toFixed(2)," MB"):"0"):"0";var t},k=n(23),C={request:1,requestBody:2,response:3,responseBody:4},S=Object.keys(C).map((function(e){return C[e]})),L=Object.keys(C).reduce((function(e,t){return e[C[t]]=t,e}),{}),T=11,N=12,M=21,R=function(e){Object(o.a)(n,e);var t=Object(d.a)(n);function n(e){var s;return Object(a.a)(this,n),(s=t.call(this,e)).flowMgr=new m,s.state={flows:s.flowMgr.showList(),flow:null,flowTab:"Headers"},s.ws=null,s}return Object(l.a)(n,[{key:"componentDidMount",value:function(){this.initWs()}},{key:"componentWillUnmount",value:function(){this.ws&&this.ws.close()}},{key:"initWs",value:function(){var e,t=this;this.ws||(e=new URL(document.URL).host,this.ws=new WebSocket("ws://".concat(e,"/echo")),this.ws.binaryType="arraybuffer",this.ws.onopen=function(){console.log("OPEN")},this.ws.onclose=function(){console.log("CLOSE")},this.ws.onmessage=function(e){var n=function(e){if(e.byteLength<39)return null;var t=new Int8Array(e.slice(0,39));if(1!==t[0])return null;var n=t[1];if(!S.includes(n))return null;var s=(new TextDecoder).decode(e.slice(2,38)),r=1===t[38],i={type:L[n],id:s,waitIntercept:r};if(39===e.byteLength)return i;if(n===C.requestBody||n===C.responseBody)return i.content=e.slice(39),i;var c=(new TextDecoder).decode(e.slice(39));try{c=JSON.parse(c)}catch(a){return null}return i.content=c,i}(e.data);if(n){if("request"===n.type){var s={id:n.id,request:n.content,waitIntercept:n.waitIntercept};t.flowMgr.add(s),t.setState({flows:t.flowMgr.showList()})}else if("requestBody"===n.type){var r=t.flowMgr.get(n.id);if(!r)return;r.waitIntercept=n.waitIntercept,r.request.body=n.content,t.setState({flows:t.state.flows})}else if("response"===n.type){var i=t.flowMgr.get(n.id);if(!i)return;i.waitIntercept=n.waitIntercept,i.response=n.content,t.setState({flows:t.state.flows})}else if("responseBody"===n.type){var c=t.flowMgr.get(n.id);if(!c||!c.response)return;c.waitIntercept=n.waitIntercept,c.response.body=n.content,t.setState({flows:t.state.flows})}}else console.error("parse error:",e.data)},this.ws.onerror=function(e){console.log("ERROR:",e)})}},{key:"renderFlow",value:function(){var e=this,t=this.state,n=t.flow,s=t.flowTab;if(!n)return null;var r=n.request,i=n.response||{};return Object(x.jsxs)("div",{className:"flow-detail",children:[Object(x.jsxs)("div",{className:"header-tabs",children:[Object(x.jsx)("span",{onClick:function(){e.setState({flow:null})},children:"x"}),Object(x.jsx)("span",{className:"Headers"===s?"selected":null,onClick:function(){e.setState({flowTab:"Headers"})},children:"Headers"}),Object(x.jsx)("span",{className:"Preview"===s?"selected":null,onClick:function(){e.setState({flowTab:"Preview"})},children:"Preview"}),Object(x.jsx)("span",{className:"Response"===s?"selected":null,onClick:function(){e.setState({flowTab:"Response"})},children:"Response"}),n.waitIntercept?Object(x.jsxs)("div",{className:"flow-wait-area",children:[Object(x.jsx)(u.a,{size:"sm",onClick:function(){var t=function(e,t){var n,s;if(e===T){var r=t.request;s=r.body,n=Object(k.a)(r,["body"])}else{if(e!==N)throw new Error("invalid message type");var i=t.response;s=i.body,n=Object(k.a)(i,["body"])}var c=s&&s.byteLength?s.byteLength:0,a=(new TextEncoder).encode(JSON.stringify(n)),l=42+a.byteLength+4+c,o=new ArrayBuffer(l),d=new Uint8Array(o);d[0]=1,d[1]=e,d.set((new TextEncoder).encode(t.id),2),d.set(a,42),c&&d.set(s,42+a.byteLength+4);var h=new DataView(o);return h.setUint32(38,a.byteLength),h.setUint32(42+a.byteLength,c),d}(T,n);e.ws.send(t),n.waitIntercept=!1,e.setState({flows:e.state.flows})},children:"Continue"}),Object(x.jsx)(u.a,{size:"sm",children:"Drop"})]}):null]}),Object(x.jsxs)("div",{style:{padding:"20px"},children:["Headers"!==s?null:Object(x.jsxs)("div",{children:[Object(x.jsxs)("div",{className:"header-block",children:[Object(x.jsx)("p",{children:"General"}),Object(x.jsxs)("div",{className:"header-block-content",children:[Object(x.jsxs)("p",{children:["Request URL: ",r.url]}),Object(x.jsxs)("p",{children:["Request Method: ",r.method]}),Object(x.jsxs)("p",{children:["Status Code: ","".concat(i.statusCode||"(pending)")]})]})]}),i.header?Object(x.jsxs)("div",{className:"header-block",children:[Object(x.jsx)("p",{children:"Response Headers"}),Object(x.jsx)("div",{className:"header-block-content",children:Object.keys(i.header).map((function(e){return Object(x.jsxs)("p",{children:[e,": ",i.header[e].join(" ")]},e)}))})]}):null,Object(x.jsxs)("div",{className:"header-block",children:[Object(x.jsx)("p",{children:"Request Headers"}),Object(x.jsx)("div",{className:"header-block-content",children:r.header?Object.keys(r.header).map((function(e){return Object(x.jsxs)("p",{children:[e,": ",r.header[e].join(" ")]},e)})):null})]}),r.body&&r.body.byteLength?Object(x.jsxs)("div",{className:"header-block",children:[Object(x.jsx)("p",{children:"Request Body"}),Object(x.jsx)("div",{className:"header-block-content",children:Object(x.jsx)("p",{children:y(r)?(new TextDecoder).decode(r.body):"Not text"})})]}):null]}),"Response"!==s?null:i.body&&i.body.byteLength?y(i)?Object(x.jsx)("div",{children:(new TextDecoder).decode(i.body)}):Object(x.jsx)("div",{children:"Not text response"}):Object(x.jsx)("div",{children:"No response"})]})]})}},{key:"render",value:function(){var e=this,t=this.state.flows;return Object(x.jsxs)("div",{className:"main-table-wrap",children:[Object(x.jsxs)("div",{className:"top-control",children:[Object(x.jsx)("div",{children:Object(x.jsx)(u.a,{size:"sm",onClick:function(){e.flowMgr.clear(),e.setState({flows:e.flowMgr.showList(),flow:null})},children:"Clear"})}),Object(x.jsx)("div",{children:Object(x.jsx)(j.a.Control,{size:"sm",placeholder:"Filter",onChange:function(t){var n=t.target.value;e.flowMgr.changeFilterLazy(n,(function(){e.setState({flows:e.flowMgr.showList()})}))}})}),Object(x.jsx)(v,{onSave:function(t){var n=function(e,t){if(e!==M)throw new Error("invalid message type");var n=(new TextEncoder).encode(JSON.stringify(t)),s=new Uint8Array(2+n.byteLength);return s[0]=1,s[1]=e,s.set(n,2),s}(M,t);e.ws.send(n)}})]}),Object(x.jsxs)(h.a,{striped:!0,bordered:!0,size:"sm",children:[Object(x.jsx)("thead",{children:Object(x.jsxs)("tr",{children:[Object(x.jsx)("th",{children:"No"}),Object(x.jsx)("th",{children:"Host"}),Object(x.jsx)("th",{children:"Path"}),Object(x.jsx)("th",{children:"Method"}),Object(x.jsx)("th",{children:"Status"}),Object(x.jsx)("th",{children:"Size"})]})}),Object(x.jsx)("tbody",{children:t.map((function(t){var n=t.request.url,s=new URL(n),r=s.host;r.length>35&&(r=r.slice(0,35)+"...");var i=s.pathname+s.search;i.length>65&&(i=i.slice(0,65)+"...");var c=t.request,a=t.response||{},l=[];return e.state.flow&&e.state.flow.id===t.id&&l.push("tr-selected"),t.waitIntercept&&l.push("tr-wait-intercept"),Object(x.jsxs)("tr",{className:l.length?l.join(" "):null,onClick:function(){e.setState({flow:t})},children:[Object(x.jsx)("td",{children:t.no}),Object(x.jsx)("td",{children:r}),Object(x.jsx)("td",{children:i}),Object(x.jsx)("td",{children:c.method}),Object(x.jsx)("td",{children:a.statusCode||"(pending)"}),Object(x.jsx)("td",{children:g(a)})]},t.id)}))})]}),this.renderFlow()]})}}]),n}(r.a.Component),B=function(e){e&&e instanceof Function&&n.e(3).then(n.bind(null,37)).then((function(t){var n=t.getCLS,s=t.getFID,r=t.getFCP,i=t.getLCP,c=t.getTTFB;n(e),s(e),r(e),i(e),c(e)}))};c.a.render(Object(x.jsx)(r.a.StrictMode,{children:Object(x.jsx)(R,{})}),document.getElementById("root")),B()}},[[35,1,2]]]);
-//# sourceMappingURL=main.37b6cc16.chunk.js.map
\ No newline at end of file
diff --git a/addon/web/client/build/static/js/main.37b6cc16.chunk.js.map b/addon/web/client/build/static/js/main.37b6cc16.chunk.js.map
deleted file mode 100644
index eea72e4..0000000
--- a/addon/web/client/build/static/js/main.37b6cc16.chunk.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["components/BreakPoint.js","flow.js","utils.js","message.js","App.js","reportWebVitals.js","index.js"],"names":["BreakPoint","props","state","show","rule","method","url","action","handleClose","bind","handleShow","handleSave","this","setState","rules","push","parseInt","onSave","Button","size","onClick","Modal","onHide","Header","closeButton","Title","Body","Form","Group","as","Row","Label","column","sm","Col","Control","value","onChange","e","target","Footer","variant","React","Component","FlowManager","items","_map","Map","filterText","filterTimer","num","max","filter","item","request","includes","no","set","id","length","oldest","shift","delete","get","text","callback","clearTimeout","setTimeout","isTextResponse","response","header","test","join","getSize","len","body","byteLength","isNaN","toFixed","messageEnum","allMessageBytes","Object","keys","map","k","messageByteMap","reduce","m","sendMessageEnum","App","flowMgr","flows","showList","flow","flowTab","ws","initWs","close","host","URL","document","WebSocket","binaryType","onopen","console","log","onclose","onmessage","evt","msg","data","meta","Int8Array","slice","type","TextDecoder","decode","waitIntercept","resp","content","JSON","parse","err","parseMessage","add","error","onerror","className","messageType","Error","bodyLen","headerBytes","TextEncoder","encode","stringify","ArrayBuffer","view","Uint8Array","view2","DataView","setUint32","buildMessageEdit","send","style","padding","statusCode","key","clear","placeholder","changeFilterLazy","rulesBytes","buildMessageMeta","Table","striped","bordered","f","u","path","pathname","search","classNames","renderFlow","reportWebVitals","onPerfEntry","Function","then","getCLS","getFID","getFCP","getLCP","getTTFB","ReactDOM","render","StrictMode","getElementById"],"mappings":"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","file":"static/js/main.37b6cc16.chunk.js","sourcesContent":["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\nclass BreakPoint extends React.Component {\n constructor(props) {\n super(props)\n\n this.state = {\n show: false,\n\n rule: {\n method: 'ALL',\n url: '',\n action: '1',\n }\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 = []\n if (rule.url) {\n rules.push({\n method: rule.method === 'ALL' ? '' : rule.method,\n url: rule.url,\n action: parseInt(rule.action)\n })\n }\n\n this.props.onSave(rules)\n this.handleClose()\n }\n\n render() {\n const { rule } = this.state\n\n return (\n \n \n\n \n \n Set BreakPoint\n \n\n \n \n Method\n \n { this.setState({ rule: { ...rule, method: e.target.value } }) }}>\n \n \n \n \n \n \n \n \n\n \n URL\n { this.setState({ rule: { ...rule, url: e.target.value } }) }} />\n \n\n \n Action\n \n { this.setState({ rule: { ...rule, action: e.target.value } }) }}>\n \n \n \n \n \n \n \n \n\n \n \n \n \n \n
\n )\n }\n}\n\nexport default BreakPoint\n","export class FlowManager {\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) {\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 this._map.delete(oldest.id)\n }\n }\n\n get(id) {\n return this._map.get(id)\n }\n\n changeFilter(text) {\n this.filterText = text\n }\n\n changeFilterLazy(text, callback) {\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)\n }\n\n clear() {\n this.items = []\n this._map = new Map()\n }\n}\n","export const isTextResponse = response => {\n if (!response) return false\n if (!response.header) return false\n if (!response.header['Content-Type']) return false\n\n return /text|javascript|json/.test(response.header['Content-Type'].join(''))\n}\n\nexport const getSize = response => {\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","const messageEnum = {\n 'request': 1,\n 'requestBody': 2,\n 'response': 3,\n 'responseBody': 4,\n}\n\nconst allMessageBytes = Object.keys(messageEnum).map(k => messageEnum[k])\n\nconst messageByteMap = Object.keys(messageEnum).reduce((m, k) => {\n m[messageEnum[k]] = k\n return m\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 => {\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]\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 = {\n type: messageByteMap[type],\n id,\n waitIntercept,\n }\n if (data.byteLength === 39) return resp\n if (type === messageEnum['requestBody'] || type === messageEnum['responseBody']) {\n resp.content = data.slice(39)\n return resp\n }\n\n let content = new TextDecoder().decode(data.slice(39))\n try {\n content = JSON.parse(content)\n } catch (err) {\n return null\n }\n\n resp.content = content\n return resp\n}\n\n\nexport const sendMessageEnum = {\n 'changeRequest': 11,\n 'changeResponse': 12,\n 'changeBreakPointRules': 21,\n}\n\n// type: 11/12\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, flow) => {\n let header, body\n \n if (messageType === sendMessageEnum.changeRequest) {\n ({ body, ...header } = flow.request)\n } else if (messageType === sendMessageEnum.changeResponse) {\n ({ body, ...header } = flow.response)\n } else {\n throw new Error('invalid message type')\n }\n \n const bodyLen = (body && body.byteLength) ? body.byteLength : 0\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, 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, rules) => {\n if (messageType !== sendMessageEnum.changeBreakPointRules) {\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 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'\n\nimport { FlowManager } from './flow'\nimport { isTextResponse, getSize } from './utils'\nimport { parseMessage, sendMessageEnum, buildMessageEdit, buildMessageMeta } from './message'\n\nclass App extends React.Component {\n\n constructor(props) {\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 === 'request') {\n const flow = { id: msg.id, request: msg.content, waitIntercept: msg.waitIntercept }\n this.flowMgr.add(flow)\n this.setState({ flows: this.flowMgr.showList() })\n }\n else if (msg.type === 'requestBody') {\n const flow = this.flowMgr.get(msg.id)\n if (!flow) return\n flow.waitIntercept = msg.waitIntercept\n flow.request.body = msg.content\n this.setState({ flows: this.state.flows })\n }\n else if (msg.type === 'response') {\n const flow = this.flowMgr.get(msg.id)\n if (!flow) return\n flow.waitIntercept = msg.waitIntercept\n flow.response = msg.content\n this.setState({ flows: this.state.flows })\n }\n else if (msg.type === 'responseBody') {\n const flow = this.flowMgr.get(msg.id)\n if (!flow || !flow.response) return\n flow.waitIntercept = msg.waitIntercept\n flow.response.body = msg.content\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 = flow.response || {}\n\n return (\n \n
\n
{ this.setState({ flow: null }) }}>x\n
{ this.setState({ flowTab: 'Headers' }) }}>Headers\n
{ this.setState({ flowTab: 'Preview' }) }}>Preview\n
{ this.setState({ flowTab: 'Response' }) }}>Response\n {\n !flow.waitIntercept ? null :\n
\n \n \n
\n }\n
\n\n
\n {\n !(flowTab === 'Headers') ? null :\n
\n
\n
General
\n
\n
Request URL: {request.url}
\n
Request Method: {request.method}
\n
Status Code: {`${response.statusCode || '(pending)'}`}
\n
\n
\n\n {\n !(response.header) ? null :\n
\n
Response Headers
\n
\n {\n Object.keys(response.header).map(key => {\n return (\n
{key}: {response.header[key].join(' ')}
\n )\n })\n }\n
\n
\n }\n\n
\n
Request Headers
\n
\n {\n !(request.header) ? null :\n Object.keys(request.header).map(key => {\n return (\n
{key}: {request.header[key].join(' ')}
\n )\n })\n }\n
\n
\n\n {\n !(request.body && request.body.byteLength) ? null :\n
\n
Request Body
\n
\n
\n {\n !(isTextResponse(request)) ? \"Not text\" :\n new TextDecoder().decode(request.body)\n }\n
\n
\n
\n }\n\n
\n }\n\n {\n !(flowTab === 'Response') ? null :\n !(response.body && response.body.byteLength) ?
No response
:\n !(isTextResponse(response)) ?
Not text response
:\n
\n {new TextDecoder().decode(response.body)}\n
\n }\n
\n\n
\n )\n }\n \n render() {\n const { flows } = this.state\n return (\n \n
\n
\n
\n
{\n const value = e.target.value\n this.flowMgr.changeFilterLazy(value, () => {\n this.setState({ flows: this.flowMgr.showList() })\n })\n }}\n >\n \n \n\n
{\n const msg = buildMessageMeta(sendMessageEnum.changeBreakPointRules, rules)\n this.ws.send(msg)\n }} />\n \n\n
\n \n \n No | \n Host | \n Path | \n Method | \n Status | \n Size | \n
\n \n \n {\n flows.map(f => {\n const url = f.request.url\n const u = new URL(url)\n let host = u.host\n if (host.length > 35) host = host.slice(0, 35) + '...'\n let path = u.pathname + u.search\n if (path.length > 65) path = path.slice(0, 65) + '...'\n\n const request = f.request\n const response = f.response || {}\n\n const classNames = []\n if (this.state.flow && this.state.flow.id === f.id) classNames.push('tr-selected')\n if (f.waitIntercept) classNames.push('tr-wait-intercept')\n\n return (\n {\n this.setState({ flow: f })\n }}\n >\n {f.no} | \n {host} | \n {path} | \n {request.method} | \n {response.statusCode || '(pending)'} | \n {getSize(response)} | \n
\n )\n })\n }\n \n
\n\n {this.renderFlow()}\n
\n )\n }\n}\n\nexport default App\n","const reportWebVitals = onPerfEntry => {\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 \n \n ,\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":""}
\ No newline at end of file
diff --git a/addon/web/client/build/static/js/main.6b681f56.chunk.js b/addon/web/client/build/static/js/main.6b681f56.chunk.js
new file mode 100644
index 0000000..b33b912
--- /dev/null
+++ b/addon/web/client/build/static/js/main.6b681f56.chunk.js
@@ -0,0 +1,2 @@
+(this.webpackJsonpclient=this.webpackJsonpclient||[]).push([[0],{48:function(e,t,n){},53:function(e,t,n){"use strict";n.r(t);var s=n(0),r=n.n(s),a=n(18),c=n.n(a),o=(n(47),n(15)),i=n(16),l=n(21),d=n(20),h=n(41),u=n(7),j=n(9),b=(n(48),n(19)),f=n(13),p=n(10),O=n(34),v=n(24),w=n(1),x=function(e){Object(l.a)(n,e);var t=Object(d.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).state={show:!1,rule:{method:"ALL",url:"",action:"1"},haveRules:!1},s.handleClose=s.handleClose.bind(Object(f.a)(s)),s.handleShow=s.handleShow.bind(Object(f.a)(s)),s.handleSave=s.handleSave.bind(Object(f.a)(s)),s}return Object(i.a)(n,[{key:"handleClose",value:function(){this.setState({show:!1})}},{key:"handleShow",value:function(){this.setState({show:!0})}},{key:"handleSave",value:function(){var e=this.state.rule,t=[];e.url&&t.push({method:"ALL"===e.method?"":e.method,url:e.url,action:parseInt(e.action)}),this.props.onSave(t),this.handleClose(),this.setState({haveRules:!!t.length})}},{key:"render",value:function(){var e=this,t=this.state,n=t.rule,s=t.haveRules?"success":"primary";return Object(w.jsxs)("div",{children:[Object(w.jsx)(j.a,{variant:s,size:"sm",onClick:this.handleShow,children:"BreakPoint"}),Object(w.jsxs)(p.a,{show:this.state.show,onHide:this.handleClose,children:[Object(w.jsx)(p.a.Header,{closeButton:!0,children:Object(w.jsx)(p.a.Title,{children:"Set BreakPoint"})}),Object(w.jsxs)(p.a.Body,{children:[Object(w.jsxs)(u.a.Group,{as:O.a,children:[Object(w.jsx)(u.a.Label,{column:!0,sm:2,children:"Method"}),Object(w.jsx)(v.a,{sm:10,children:Object(w.jsxs)(u.a.Control,{as:"select",value:n.method,onChange:function(t){e.setState({rule:Object(b.a)(Object(b.a)({},n),{},{method:t.target.value})})},children:[Object(w.jsx)("option",{children:"ALL"}),Object(w.jsx)("option",{children:"GET"}),Object(w.jsx)("option",{children:"POST"}),Object(w.jsx)("option",{children:"PUT"}),Object(w.jsx)("option",{children:"DELETE"})]})})]}),Object(w.jsxs)(u.a.Group,{as:O.a,children:[Object(w.jsx)(u.a.Label,{column:!0,sm:2,children:"URL"}),Object(w.jsx)(v.a,{sm:10,children:Object(w.jsx)(u.a.Control,{value:n.url,onChange:function(t){e.setState({rule:Object(b.a)(Object(b.a)({},n),{},{url:t.target.value})})}})})]}),Object(w.jsxs)(u.a.Group,{as:O.a,children:[Object(w.jsx)(u.a.Label,{column:!0,sm:2,children:"Action"}),Object(w.jsx)(v.a,{sm:10,children:Object(w.jsxs)(u.a.Control,{as:"select",value:n.action,onChange:function(t){e.setState({rule:Object(b.a)(Object(b.a)({},n),{},{action:t.target.value})})},children:[Object(w.jsx)("option",{value:"1",children:"Request"}),Object(w.jsx)("option",{value:"2",children:"Response"}),Object(w.jsx)("option",{value:"3",children:"Both"})]})})]})]}),Object(w.jsxs)(p.a.Footer,{children:[Object(w.jsx)(j.a,{variant:"secondary",onClick:this.handleClose,children:"Close"}),Object(w.jsx)(j.a,{variant:"primary",onClick:this.handleSave,children:"Save"})]})]})]})}}]),n}(r.a.Component),y=n(39),m=n(26),g=n(42),C=n(40),S={request:1,requestBody:2,response:3,responseBody:4},k=Object.keys(S).map((function(e){return S[e]})),T=Object.keys(S).reduce((function(e,t){return e[S[t]]=t,e}),{}),L=11,q=12,N=13,R=14,M=21,B=function(e,t){if(e===N||e===R){var n=new Uint8Array(38);return n[0]=1,n[1]=e,n.set((new TextEncoder).encode(t.id),2),n}var s,r;if(e===L){var a=t.request;r=a.body,s=Object(C.a)(a,["body"])}else{if(e!==q)throw new Error("invalid message type");var c=t.response;r=c.body,s=Object(C.a)(c,["body"])}var o=r&&r.byteLength?r.byteLength:0,i=(new TextEncoder).encode(JSON.stringify(s)),l=42+i.byteLength+4+o,d=new ArrayBuffer(l),h=new Uint8Array(d);h[0]=1,h[1]=e,h.set((new TextEncoder).encode(t.id),2),h.set(i,42),o&&h.set(r,42+i.byteLength+4);var u=new DataView(d);return u.setUint32(38,i.byteLength),u.setUint32(42+i.byteLength,o),h},E=function(e){return!!e&&(!!e.header&&(!!e.header["Content-Type"]&&/text|javascript|json/.test(e.header["Content-Type"].join(""))))},I=function(e){return e&&e.header?(e.header["Content-Length"]?t=parseInt(e.header["Content-Length"][0]):e&&e.body&&(t=e.body.byteLength),t?isNaN(t)||t<=0?"0":t<1024?"".concat(t," B"):t<1048576?"".concat((t/1024).toFixed(2)," KB"):"".concat((t/1048576).toFixed(2)," MB"):"0"):"0";var t},F=function(e){Object(l.a)(n,e);var t=Object(d.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).state={show:!1,alertMsg:"",content:""},s.handleClose=s.handleClose.bind(Object(f.a)(s)),s.handleShow=s.handleShow.bind(Object(f.a)(s)),s.handleSave=s.handleSave.bind(Object(f.a)(s)),s}return Object(i.a)(n,[{key:"showAlert",value:function(e){this.setState({alertMsg:e})}},{key:"handleClose",value:function(){this.setState({show:!1})}},{key:"handleShow",value:function(){var e=this.props.flow,t="";t="request"===(e.response?"response":"request")?function(e){var t="".concat(e.method," ").concat(e.url),n=Object.keys(e.header).map((function(t){var n=e.header[t].join(" \t ");return"".concat(t,": ").concat(n)})).join("\n"),s="";return e.body&&E(e)&&(s=(new TextDecoder).decode(e.body)),"".concat(t,"\n\n").concat(n,"\n\n").concat(s)}(e.request):function(e){var t="".concat(e.statusCode),n=Object.keys(e.header).map((function(t){var n=e.header[t].join(" \t ");return"".concat(t,": ").concat(n)})).join("\n"),s="";return e.body&&E(e)&&(s=(new TextDecoder).decode(e.body)),"".concat(t,"\n\n").concat(n,"\n\n").concat(s)}(e.response),this.setState({show:!0,alertMsg:"",content:t})}},{key:"handleSave",value:function(){var e=this.props.flow.response?"response":"request",t=this.state.content;if("request"===e){var n=function(e){var t=e.split("\n\n");if(3===t.length){var n=Object(m.a)(t,3),s=n[0],r=n[1],a=n[2],c=s.split(" "),o=Object(m.a)(c,2),i=o[0],l=o[1];if(i&&l){var d,h={},u=Object(y.a)(r.split("\n"));try{for(u.s();!(d=u.n()).done;){var j=d.value.split(": "),b=Object(m.a)(j,2),f=b[0],p=b[1];if(!f||!p)return;h[f]=p.split(" \t ")}}catch(v){u.e(v)}finally{u.f()}var O=null;return a&&(O=(new TextEncoder).encode(a)),{method:i,url:l,header:h,body:O}}}}(t);if(!n)return void this.showAlert("parse error");this.props.onChangeRequest(n),this.handleClose()}else{var s=function(e){var t=e.split("\n\n");if(3===t.length){var n=Object(m.a)(t,3),s=n[0],r=n[1],a=n[2],c=parseInt(s);if(!isNaN(c)){var o,i={},l=Object(y.a)(r.split("\n"));try{for(l.s();!(o=l.n()).done;){var d=o.value.split(": "),h=Object(m.a)(d,2),u=h[0],j=h[1];if(!u||!j)return;i[u]=j.split(" \t ")}}catch(f){l.e(f)}finally{l.f()}var b=null;return a&&(b=(new TextEncoder).encode(a)),{statusCode:c,header:i,body:b}}}}(t);if(!s)return void this.showAlert("parse error");this.props.onChangeResponse(s),this.handleClose()}}},{key:"render",value:function(){var e=this,t=this.props.flow;if(!t.waitIntercept)return null;var n=this.state.alertMsg,s=t.response?"response":"request";return Object(w.jsxs)("div",{className:"flow-wait-area",children:[Object(w.jsx)(j.a,{size:"sm",onClick:this.handleShow,children:"Edit"}),Object(w.jsx)(j.a,{size:"sm",onClick:function(){var n=B("response"===s?q:L,t);e.props.onMessage(n)},children:"Continue"}),Object(w.jsx)(j.a,{size:"sm",onClick:function(){var n=B("response"===s?R:N,t);e.props.onMessage(n)},children:"Drop"}),Object(w.jsxs)(p.a,{size:"lg",show:this.state.show,onHide:this.handleClose,children:[Object(w.jsx)(p.a.Header,{closeButton:!0,children:Object(w.jsxs)(p.a.Title,{children:["Edit ","request"===s?"Request":"Response"]})}),Object(w.jsxs)(p.a.Body,{children:[Object(w.jsx)(u.a.Group,{children:Object(w.jsx)(u.a.Control,{as:"textarea",rows:10,value:this.state.content,onChange:function(t){e.setState({content:t.target.value})}})}),n?Object(w.jsx)(g.a,{variant:"danger",children:n}):null]}),Object(w.jsxs)(p.a.Footer,{children:[Object(w.jsx)(j.a,{variant:"secondary",onClick:this.handleClose,children:"Close"}),Object(w.jsx)(j.a,{variant:"primary",onClick:this.handleSave,children:"Save"})]})]})]})}}]),n}(r.a.Component),A=function(){function e(){Object(o.a)(this,e),this.items=[],this._map=new Map,this.filterText="",this.filterTimer=null,this.num=0,this.max=1e3}return Object(i.a)(e,[{key:"showList",value:function(){var e=this;return this.filterText?this.items.filter((function(t){return t.request.url.includes(e.filterText)})):this.items}},{key:"add",value:function(e){if(e.no=++this.num,this.items.push(e),this._map.set(e.id,e),this.items.length>this.max){var t=this.items.shift();this._map.delete(t.id)}}},{key:"get",value:function(e){return this._map.get(e)}},{key:"changeFilter",value:function(e){this.filterText=e}},{key:"changeFilterLazy",value:function(e,t){var n=this;this.filterTimer&&(clearTimeout(this.filterTimer),this.filterTimer=null),this.filterTimer=setTimeout((function(){n.filterText=e,t()}),300)}},{key:"clear",value:function(){this.items=[],this._map=new Map}}]),e}(),H=function(e){Object(l.a)(n,e);var t=Object(d.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).flowMgr=new A,s.state={flows:s.flowMgr.showList(),flow:null,flowTab:"Headers"},s.ws=null,s}return Object(i.a)(n,[{key:"componentDidMount",value:function(){this.initWs()}},{key:"componentWillUnmount",value:function(){this.ws&&this.ws.close()}},{key:"initWs",value:function(){var e,t=this;this.ws||(e=new URL(document.URL).host,this.ws=new WebSocket("ws://".concat(e,"/echo")),this.ws.binaryType="arraybuffer",this.ws.onopen=function(){console.log("OPEN")},this.ws.onclose=function(){console.log("CLOSE")},this.ws.onmessage=function(e){var n=function(e){if(e.byteLength<39)return null;var t=new Int8Array(e.slice(0,39));if(1!==t[0])return null;var n=t[1];if(!k.includes(n))return null;var s=(new TextDecoder).decode(e.slice(2,38)),r=1===t[38],a={type:T[n],id:s,waitIntercept:r};if(39===e.byteLength)return a;if(n===S.requestBody||n===S.responseBody)return a.content=e.slice(39),a;var c=(new TextDecoder).decode(e.slice(39));try{c=JSON.parse(c)}catch(o){return null}return a.content=c,a}(e.data);if(n){if("request"===n.type){var s={id:n.id,request:n.content,waitIntercept:n.waitIntercept};t.flowMgr.add(s),t.setState({flows:t.flowMgr.showList()})}else if("requestBody"===n.type){var r=t.flowMgr.get(n.id);if(!r)return;r.waitIntercept=n.waitIntercept,r.request.body=n.content,t.setState({flows:t.state.flows})}else if("response"===n.type){var a=t.flowMgr.get(n.id);if(!a)return;a.waitIntercept=n.waitIntercept,a.response=n.content,t.setState({flows:t.state.flows})}else if("responseBody"===n.type){var c=t.flowMgr.get(n.id);if(!c||!c.response)return;c.waitIntercept=n.waitIntercept,c.response.body=n.content,t.setState({flows:t.state.flows})}}else console.error("parse error:",e.data)},this.ws.onerror=function(e){console.log("ERROR:",e)})}},{key:"renderFlow",value:function(){var e=this,t=this.state,n=t.flow,s=t.flowTab;if(!n)return null;var r=n.request,a=n.response||{};return Object(w.jsxs)("div",{className:"flow-detail",children:[Object(w.jsxs)("div",{className:"header-tabs",children:[Object(w.jsx)("span",{onClick:function(){e.setState({flow:null})},children:"x"}),Object(w.jsx)("span",{className:"Headers"===s?"selected":null,onClick:function(){e.setState({flowTab:"Headers"})},children:"Headers"}),Object(w.jsx)("span",{className:"Preview"===s?"selected":null,onClick:function(){e.setState({flowTab:"Preview"})},children:"Preview"}),Object(w.jsx)("span",{className:"Response"===s?"selected":null,onClick:function(){e.setState({flowTab:"Response"})},children:"Response"}),Object(w.jsx)(F,{flow:n,onChangeRequest:function(t){n.request.method=t.method,n.request.url=t.url,n.request.header=t.header,E(n.request)&&(n.request.body=t.body),e.setState({flows:e.state.flows})},onChangeResponse:function(t){n.response.statusCode=t.statusCode,n.response.header=t.header,E(n.response)&&(n.response.body=t.body),e.setState({flows:e.state.flows})},onMessage:function(t){e.ws.send(t),n.waitIntercept=!1,e.setState({flows:e.state.flows})}})]}),Object(w.jsxs)("div",{style:{padding:"20px"},children:["Headers"!==s?null:Object(w.jsxs)("div",{children:[Object(w.jsxs)("div",{className:"header-block",children:[Object(w.jsx)("p",{children:"General"}),Object(w.jsxs)("div",{className:"header-block-content",children:[Object(w.jsxs)("p",{children:["Request URL: ",r.url]}),Object(w.jsxs)("p",{children:["Request Method: ",r.method]}),Object(w.jsxs)("p",{children:["Status Code: ","".concat(a.statusCode||"(pending)")]})]})]}),a.header?Object(w.jsxs)("div",{className:"header-block",children:[Object(w.jsx)("p",{children:"Response Headers"}),Object(w.jsx)("div",{className:"header-block-content",children:Object.keys(a.header).map((function(e){return Object(w.jsxs)("p",{children:[e,": ",a.header[e].join(" ")]},e)}))})]}):null,Object(w.jsxs)("div",{className:"header-block",children:[Object(w.jsx)("p",{children:"Request Headers"}),Object(w.jsx)("div",{className:"header-block-content",children:r.header?Object.keys(r.header).map((function(e){return Object(w.jsxs)("p",{children:[e,": ",r.header[e].join(" ")]},e)})):null})]}),r.body&&r.body.byteLength?Object(w.jsxs)("div",{className:"header-block",children:[Object(w.jsx)("p",{children:"Request Body"}),Object(w.jsx)("div",{className:"header-block-content",children:Object(w.jsx)("p",{children:E(r)?(new TextDecoder).decode(r.body):"Not text"})})]}):null]}),"Response"!==s?null:a.body&&a.body.byteLength?E(a)?Object(w.jsx)("div",{children:(new TextDecoder).decode(a.body)}):Object(w.jsx)("div",{children:"Not text response"}):Object(w.jsx)("div",{children:"No response"})]})]})}},{key:"render",value:function(){var e=this,t=this.state.flows;return Object(w.jsxs)("div",{className:"main-table-wrap",children:[Object(w.jsxs)("div",{className:"top-control",children:[Object(w.jsx)("div",{children:Object(w.jsx)(j.a,{size:"sm",onClick:function(){e.flowMgr.clear(),e.setState({flows:e.flowMgr.showList(),flow:null})},children:"Clear"})}),Object(w.jsx)("div",{children:Object(w.jsx)(u.a.Control,{size:"sm",placeholder:"Filter",onChange:function(t){var n=t.target.value;e.flowMgr.changeFilterLazy(n,(function(){e.setState({flows:e.flowMgr.showList()})}))}})}),Object(w.jsx)(x,{onSave:function(t){var n=function(e,t){if(e!==M)throw new Error("invalid message type");var n=(new TextEncoder).encode(JSON.stringify(t)),s=new Uint8Array(2+n.byteLength);return s[0]=1,s[1]=e,s.set(n,2),s}(M,t);e.ws.send(n)}})]}),Object(w.jsxs)(h.a,{striped:!0,bordered:!0,size:"sm",children:[Object(w.jsx)("thead",{children:Object(w.jsxs)("tr",{children:[Object(w.jsx)("th",{children:"No"}),Object(w.jsx)("th",{children:"Host"}),Object(w.jsx)("th",{children:"Path"}),Object(w.jsx)("th",{children:"Method"}),Object(w.jsx)("th",{children:"Status"}),Object(w.jsx)("th",{children:"Size"})]})}),Object(w.jsx)("tbody",{children:t.map((function(t){var n=t.request.url,s=new URL(n),r=s.host;r.length>35&&(r=r.slice(0,35)+"...");var a=s.pathname+s.search;a.length>65&&(a=a.slice(0,65)+"...");var c=t.request,o=t.response||{},i=[];return e.state.flow&&e.state.flow.id===t.id&&i.push("tr-selected"),t.waitIntercept&&i.push("tr-wait-intercept"),Object(w.jsxs)("tr",{className:i.length?i.join(" "):null,onClick:function(){e.setState({flow:t})},children:[Object(w.jsx)("td",{children:t.no}),Object(w.jsx)("td",{children:r}),Object(w.jsx)("td",{children:a}),Object(w.jsx)("td",{children:c.method}),Object(w.jsx)("td",{children:o.statusCode||"(pending)"}),Object(w.jsx)("td",{children:I(o)})]},t.id)}))})]}),this.renderFlow()]})}}]),n}(r.a.Component),U=function(e){e&&e instanceof Function&&n.e(3).then(n.bind(null,55)).then((function(t){var n=t.getCLS,s=t.getFID,r=t.getFCP,a=t.getLCP,c=t.getTTFB;n(e),s(e),r(e),a(e),c(e)}))};c.a.render(Object(w.jsx)(r.a.StrictMode,{children:Object(w.jsx)(H,{})}),document.getElementById("root")),U()}},[[53,1,2]]]);
+//# sourceMappingURL=main.6b681f56.chunk.js.map
\ No newline at end of file
diff --git a/addon/web/client/build/static/js/main.6b681f56.chunk.js.map b/addon/web/client/build/static/js/main.6b681f56.chunk.js.map
new file mode 100644
index 0000000..82b4baf
--- /dev/null
+++ b/addon/web/client/build/static/js/main.6b681f56.chunk.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["components/BreakPoint.js","message.js","utils.js","components/EditFlow.js","flow.js","App.js","reportWebVitals.js","index.js"],"names":["BreakPoint","props","state","show","rule","method","url","action","haveRules","handleClose","bind","handleShow","handleSave","this","setState","rules","push","parseInt","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","Footer","React","Component","messageEnum","allMessageBytes","Object","keys","map","k","messageByteMap","reduce","m","sendMessageEnum","buildMessageEdit","messageType","flow","view","Uint8Array","set","TextEncoder","encode","id","header","body","request","Error","response","bodyLen","byteLength","headerBytes","JSON","stringify","len","data","ArrayBuffer","view2","DataView","setUint32","isTextBody","payload","test","join","getSize","isNaN","toFixed","EditFlow","alertMsg","content","msg","firstLine","headerLines","key","valstr","bodyLines","TextDecoder","decode","stringifyRequest","statusCode","stringifyResponse","when","sections","split","vals","parseRequest","showAlert","onChangeRequest","parseResponse","onChangeResponse","waitIntercept","className","onMessage","rows","Alert","FlowManager","items","_map","Map","filterText","filterTimer","num","max","filter","item","includes","no","oldest","shift","delete","get","text","callback","clearTimeout","setTimeout","App","flowMgr","flows","showList","flowTab","ws","initWs","close","host","URL","document","WebSocket","binaryType","onopen","console","log","onclose","onmessage","evt","meta","Int8Array","slice","type","resp","parse","err","parseMessage","add","error","onerror","send","style","padding","clear","placeholder","changeFilterLazy","rulesBytes","buildMessageMeta","Table","striped","bordered","f","u","path","pathname","search","classNames","renderFlow","reportWebVitals","onPerfEntry","Function","then","getCLS","getFID","getFCP","getLCP","getTTFB","ReactDOM","render","StrictMode","getElementById"],"mappings":"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","file":"static/js/main.6b681f56.chunk.js","sourcesContent":["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\nclass BreakPoint extends React.Component {\n constructor(props) {\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 = []\n if (rule.url) {\n rules.push({\n method: rule.method === 'ALL' ? '' : rule.method,\n url: rule.url,\n action: parseInt(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 \n \n\n \n \n Set BreakPoint\n \n\n \n \n Method\n \n { this.setState({ rule: { ...rule, method: e.target.value } }) }}>\n \n \n \n \n \n \n \n \n\n \n URL\n { this.setState({ rule: { ...rule, url: e.target.value } }) }} />\n \n\n \n Action\n \n { this.setState({ rule: { ...rule, action: e.target.value } }) }}>\n \n \n \n \n \n \n \n\n \n \n \n \n \n
\n )\n }\n}\n\nexport default BreakPoint\n","const messageEnum = {\n 'request': 1,\n 'requestBody': 2,\n 'response': 3,\n 'responseBody': 4,\n}\n\nconst allMessageBytes = Object.keys(messageEnum).map(k => messageEnum[k])\n\nconst messageByteMap = Object.keys(messageEnum).reduce((m, k) => {\n m[messageEnum[k]] = k\n return m\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 => {\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]\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 = {\n type: messageByteMap[type],\n id,\n waitIntercept,\n }\n if (data.byteLength === 39) return resp\n if (type === messageEnum['requestBody'] || type === messageEnum['responseBody']) {\n resp.content = data.slice(39)\n return resp\n }\n\n let content = new TextDecoder().decode(data.slice(39))\n try {\n content = JSON.parse(content)\n } catch (err) {\n return null\n }\n\n resp.content = content\n return resp\n}\n\n\nexport const sendMessageEnum = {\n 'changeRequest': 11,\n 'changeResponse': 12,\n 'dropRequest': 13,\n 'dropResponse': 14,\n 'changeBreakPointRules': 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, flow) => {\n if (messageType === sendMessageEnum.dropRequest || messageType === sendMessageEnum.dropResponse) {\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, body\n \n if (messageType === sendMessageEnum.changeRequest) {\n ({ body, ...header } = flow.request)\n } else if (messageType === sendMessageEnum.changeResponse) {\n ({ body, ...header } = flow.response)\n } else {\n throw new Error('invalid message type')\n }\n \n const bodyLen = (body && body.byteLength) ? body.byteLength : 0\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, 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, rules) => {\n if (messageType !== sendMessageEnum.changeBreakPointRules) {\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","export const isTextBody = payload => {\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 => {\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","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 { sendMessageEnum, buildMessageEdit } from '../message'\nimport { isTextBody } from '../utils'\n\n\nconst stringifyRequest = request => {\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 => {\n const sections = content.split('\\n\\n')\n if (sections.length !== 3) return\n\n const [firstLine, headerLines, bodyLines] = sections\n const [method, url] = firstLine.split(' ')\n if (!method || !url) return\n \n const 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 let body = null\n if (bodyLines) body = new TextEncoder().encode(bodyLines)\n\n return {\n method,\n url,\n header,\n body,\n }\n}\n\nconst stringifyResponse = response => {\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 => {\n const sections = content.split('\\n\\n')\n if (sections.length !== 3) return\n\n const [firstLine, headerLines, bodyLines] = sections\n const statusCode = parseInt(firstLine)\n if (isNaN(statusCode)) return\n\n const 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 let body = null\n if (bodyLines) body = new TextEncoder().encode(bodyLines)\n\n return {\n statusCode,\n header,\n body,\n }\n}\n\n\nclass EditFlow extends React.Component {\n constructor(props) {\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) {\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)\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 \n\n
\n\n
\n\n
\n\n\n
\n \n Edit {when === 'request' ? 'Request' : 'Response'}\n \n\n \n \n { this.setState({ content: e.target.value }) }} />\n \n {\n !alertMsg ? null : {alertMsg}\n }\n \n\n \n \n \n \n \n\n
\n )\n }\n}\n\nexport default EditFlow\n","export class FlowManager {\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) {\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 this._map.delete(oldest.id)\n }\n }\n\n get(id) {\n return this._map.get(id)\n }\n\n changeFilter(text) {\n this.filterText = text\n }\n\n changeFilterLazy(text, callback) {\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)\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'\n\nimport { FlowManager } from './flow'\nimport { isTextBody, getSize } from './utils'\nimport { parseMessage, sendMessageEnum, buildMessageMeta } from './message'\n\nclass App extends React.Component {\n\n constructor(props) {\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 === 'request') {\n const flow = { id: msg.id, request: msg.content, waitIntercept: msg.waitIntercept }\n this.flowMgr.add(flow)\n this.setState({ flows: this.flowMgr.showList() })\n }\n else if (msg.type === 'requestBody') {\n const flow = this.flowMgr.get(msg.id)\n if (!flow) return\n flow.waitIntercept = msg.waitIntercept\n flow.request.body = msg.content\n this.setState({ flows: this.state.flows })\n }\n else if (msg.type === 'response') {\n const flow = this.flowMgr.get(msg.id)\n if (!flow) return\n flow.waitIntercept = msg.waitIntercept\n flow.response = msg.content\n this.setState({ flows: this.state.flows })\n }\n else if (msg.type === 'responseBody') {\n const flow = this.flowMgr.get(msg.id)\n if (!flow || !flow.response) return\n flow.waitIntercept = msg.waitIntercept\n flow.response.body = msg.content\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 = flow.response || {}\n\n return (\n \n
\n { this.setState({ flow: null }) }}>x\n { this.setState({ flowTab: 'Headers' }) }}>Headers\n { this.setState({ flowTab: 'Preview' }) }}>Preview\n { this.setState({ flowTab: 'Response' }) }}>Response\n\n {\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 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 this.ws.send(msg)\n flow.waitIntercept = false\n this.setState({ flows: this.state.flows })\n }}\n />\n\n
\n\n
\n {\n !(flowTab === 'Headers') ? null :\n
\n
\n
General
\n
\n
Request URL: {request.url}
\n
Request Method: {request.method}
\n
Status Code: {`${response.statusCode || '(pending)'}`}
\n
\n
\n\n {\n !(response.header) ? null :\n
\n
Response Headers
\n
\n {\n Object.keys(response.header).map(key => {\n return (\n
{key}: {response.header[key].join(' ')}
\n )\n })\n }\n
\n
\n }\n\n
\n
Request Headers
\n
\n {\n !(request.header) ? null :\n Object.keys(request.header).map(key => {\n return (\n
{key}: {request.header[key].join(' ')}
\n )\n })\n }\n
\n
\n\n {\n !(request.body && request.body.byteLength) ? null :\n
\n
Request Body
\n
\n
\n {\n !(isTextBody(request)) ? \"Not text\" :\n new TextDecoder().decode(request.body)\n }\n
\n
\n
\n }\n\n
\n }\n\n {\n !(flowTab === 'Response') ? null :\n !(response.body && response.body.byteLength) ?
No response
:\n !(isTextBody(response)) ?
Not text response
:\n
\n {new TextDecoder().decode(response.body)}\n
\n }\n
\n\n
\n )\n }\n \n render() {\n const { flows } = this.state\n return (\n \n
\n
\n
\n
{\n const value = e.target.value\n this.flowMgr.changeFilterLazy(value, () => {\n this.setState({ flows: this.flowMgr.showList() })\n })\n }}\n >\n \n \n\n
{\n const msg = buildMessageMeta(sendMessageEnum.changeBreakPointRules, rules)\n this.ws.send(msg)\n }} />\n \n\n
\n \n \n No | \n Host | \n Path | \n Method | \n Status | \n Size | \n
\n \n \n {\n flows.map(f => {\n const url = f.request.url\n const u = new URL(url)\n let host = u.host\n if (host.length > 35) host = host.slice(0, 35) + '...'\n let path = u.pathname + u.search\n if (path.length > 65) path = path.slice(0, 65) + '...'\n\n const request = f.request\n const response = f.response || {}\n\n const classNames = []\n if (this.state.flow && this.state.flow.id === f.id) classNames.push('tr-selected')\n if (f.waitIntercept) classNames.push('tr-wait-intercept')\n\n return (\n {\n this.setState({ flow: f })\n }}\n >\n {f.no} | \n {host} | \n {path} | \n {request.method} | \n {response.statusCode || '(pending)'} | \n {getSize(response)} | \n
\n )\n })\n }\n \n
\n\n {this.renderFlow()}\n
\n )\n }\n}\n\nexport default App\n","const reportWebVitals = onPerfEntry => {\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 \n \n ,\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":""}
\ No newline at end of file
diff --git a/addon/web/client/build/static/js/runtime-main.e3236fc4.js b/addon/web/client/build/static/js/runtime-main.48e80cd2.js
similarity index 95%
rename from addon/web/client/build/static/js/runtime-main.e3236fc4.js
rename to addon/web/client/build/static/js/runtime-main.48e80cd2.js
index 9016066..91574ae 100644
--- a/addon/web/client/build/static/js/runtime-main.e3236fc4.js
+++ b/addon/web/client/build/static/js/runtime-main.48e80cd2.js
@@ -1,2 +1,2 @@
-!function(e){function t(t){for(var n,i,a=t[0],c=t[1],l=t[2],s=0,p=[];s