web addon web interface

addon-dailer
lqqyt2423 4 years ago
parent c3b0c8091a
commit 4890ead7f0

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

@ -1,4 +1,46 @@
.main-table-wrap { .main-table-wrap {
font-family: Menlo,Monaco; font-family: Menlo,Monaco;
font-size: 0.9rem; font-size: 0.8rem;
}
.flow-detail {
position: fixed;
top: 0;
right: 0;
height: 100vh;
background-color: #fff;
min-width: 500px;
width: 50%;
overflow-y: auto;
word-break: break-all;
}
.flow-detail .header-tabs span {
display: inline-block;
line-height: 1;
padding: 8px;
cursor: pointer;
}
.flow-detail .header-tabs .selected {
border-bottom: 2px rgb(35, 118, 229) solid;
}
/* .flow-detail .header-block {
margin: 20px;
} */
.flow-detail .header-block > p {
font-weight: bold;
}
.flow-detail .header-block .header-block-content p {
margin: 5px 0;
}
.flow-detail .header-block .header-block-content {
margin-left: 20px;
line-height: 1.5;
} }

@ -1,7 +1,16 @@
import React from 'react' import React from 'react'
import Table from 'react-bootstrap/Table' import Table from 'react-bootstrap/Table'
import { Base64 } from 'js-base64'
import './App.css' import './App.css'
const isTextResponse = response => {
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(''))
}
class App extends React.Component { class App extends React.Component {
constructor(props) { constructor(props) {
@ -9,6 +18,9 @@ class App extends React.Component {
this.state = { this.state = {
flows: [], flows: [],
flow: null,
flowTab: 'Headers', // Headers, Preview, Response
} }
this.ws = null this.ws = null
} }
@ -53,6 +65,79 @@ class App extends React.Component {
// this.ws.send('msg') // this.ws.send('msg')
// this.ws.close() // this.ws.close()
} }
renderFlow() {
const { flow, flowTab } = this.state
if (!flow) return null
const request = flow.request
const response = flow.response || {}
return (
<div className="flow-detail">
<div className="header-tabs">
<span onClick={() => { this.setState({ flow: null }) }}>x</span>
<span className={flowTab === 'Headers' ? 'selected' : null} onClick={() => { this.setState({ flowTab: 'Headers' }) }}>Headers</span>
<span className={flowTab === 'Preview' ? 'selected' : null} onClick={() => { this.setState({ flowTab: 'Preview' }) }}>Preview</span>
<span className={flowTab === 'Response' ? 'selected' : null} onClick={() => { this.setState({ flowTab: 'Response' }) }}>Response</span>
</div>
<div style={{ padding: '20px' }}>
{
!(flowTab === 'Headers') ? null :
<div>
<div className="header-block">
<p>General</p>
<div className="header-block-content">
<p>Request URL: {request.url}</p>
<p>Request Method: {request.method}</p>
<p>Status Code: {`${response.statusCode || '(pending)'}`}</p>
</div>
</div>
<div className="header-block">
<p>Response Headers</p>
<div className="header-block-content">
{
!(response.header) ? null :
Object.keys(response.header).map(key => {
return (
<p key={key}>{key}: {response.header[key].join(' ')}</p>
)
})
}
</div>
</div>
<div className="header-block">
<p>Request Headers</p>
<div className="header-block-content">
{
!(request.header) ? null :
Object.keys(request.header).map(key => {
return (
<p key={key}>{key}: {request.header[key].join(' ')}</p>
)
})
}
</div>
</div>
</div>
}
{
!(flowTab === 'Response') ? null :
!(response.body && response.body.length) ? <div>No response</div> :
!(isTextResponse(response)) ? <div>Not text response</div> :
<div>
{Base64.decode(response.body)}
</div>
}
</div>
</div>
)
}
render() { render() {
const { flows } = this.state const { flows } = this.state
@ -61,10 +146,10 @@ class App extends React.Component {
<Table striped bordered size="sm"> <Table striped bordered size="sm">
<thead> <thead>
<tr> <tr>
<th>Status</th>
<th>Method</th>
<th>Host</th> <th>Host</th>
<th>Path</th> <th>Path</th>
<th>Method</th>
<th>Status</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -78,17 +163,21 @@ class App extends React.Component {
const request = f.request const request = f.request
const response = f.response || {} const response = f.response || {}
return ( return (
<tr key={f.id}> <tr key={f.id} onClick={() => {
<td>{response.statusCode || '(pending)'}</td> this.setState({ flow: f })
<td>{request.method}</td> }}>
<td>{u.host}</td> <td>{u.host}</td>
<td>{path}</td> <td>{path}</td>
<td>{request.method}</td>
<td>{response.statusCode || '(pending)'}</td>
</tr> </tr>
) )
}) })
} }
</tbody> </tbody>
</Table> </Table>
{this.renderFlow()}
</div> </div>
) )
} }

@ -6650,6 +6650,11 @@ jest@26.6.0:
import-local "^3.0.2" import-local "^3.0.2"
jest-cli "^26.6.0" jest-cli "^26.6.0"
js-base64@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.6.0.tgz#773e1de628f4f298d65a7e9842c50244751f5756"
integrity sha512-wVdUBYQeY2gY73RIlPrysvpYx+2vheGo8Y1SNQv/BzHToWpAZzJU7Z6uheKMAe+GLSBig5/Ps2nxg/8tRB73xg==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

@ -52,6 +52,7 @@ func main() {
p.AddAddon(dumper) p.AddAddon(dumper)
} }
p.AddAddon(&addon.Decoder{})
p.AddAddon(web.NewWebAddon()) p.AddAddon(web.NewWebAddon())
log.Fatal(p.Start()) log.Fatal(p.Start())

Loading…
Cancel
Save