Show http trailers in web-ui (#4142)

This commit is contained in:
sanlengjingvv 2020-08-12 23:21:31 +08:00 committed by GitHub
parent 5ebc338fde
commit 5d0e1906e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 306 additions and 39 deletions

View File

@ -7,6 +7,7 @@ Unreleased: mitmproxy next
* Fix links to anticache docs in mitmweb and use HTTPS for links to documentation (@rugk)
* Updated typing for WebsocketMessage.content (@prinzhorn)
* Prevent transparent mode from connecting to itself in the basic cases (@prinzhorn)
* Display HTTP trailers in mitmweb (@sanlengjingvv)
* --- TODO: add new PRs above this line ---

View File

@ -305,6 +305,10 @@ class FlowHandler(RequestHandler):
request.headers.clear()
for header in v:
request.headers.add(*header)
elif k == "trailers":
request.trailers.clear()
for trailer in v:
request.trailers.add(*trailer)
elif k == "content":
request.text = v
else:
@ -321,6 +325,10 @@ class FlowHandler(RequestHandler):
response.headers.clear()
for header in v:
response.headers.add(*header)
elif k == "trailers":
response.trailers.clear()
for trailer in v:
response.trailers.add(*trailer)
elif k == "content":
response.text = v
else:

View File

@ -58,7 +58,7 @@ describe('Request Component', () => {
})
it('should handle change on flow request header', () => {
let headers = TestUtils.findRenderedComponentWithType(provider, Headers)
let headers = TestUtils.scryRenderedComponentsWithType(provider, Headers).filter(headers => headers.props.type === 'headers')[0]
headers.props.onChange('foo')
expect(store.getActions()).toEqual([updateEdit({ request: { headers: 'foo' }})])
})
@ -115,7 +115,7 @@ describe('Response Component', () => {
})
it('should handle change on flow response headers', () => {
let headers = TestUtils.findRenderedComponentWithType(provider, Headers)
let headers = TestUtils.scryRenderedComponentsWithType(provider, Headers).filter(headers => headers.props.type === 'headers')[0]
headers.props.onChange('foo')
expect(store.getActions()).toEqual([updateEdit( { response: { headers: 'foo' }})])
})

View File

@ -199,6 +199,111 @@ exports[`Request Component should render correctly 1`] = `
</tbody>
</table>
<hr />
<hr />
<table
className="header-table"
>
<tbody>
<tr>
<td
className="header-name"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "trailer",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
<span
className="header-colon"
>
:
</span>
</td>
<td
className="header-value"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "qvalue",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
</td>
</tr>
<tr>
<td
className="header-name"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "content-length",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
<span
className="header-colon"
>
:
</span>
</td>
<td
className="header-value"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "7",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
</td>
</tr>
</tbody>
</table>
</article>
<footer>
<div
@ -462,6 +567,111 @@ exports[`Response Component should render correctly 1`] = `
</tbody>
</table>
<hr />
<hr />
<table
className="header-table"
>
<tbody>
<tr>
<td
className="header-name"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "trailer",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
<span
className="header-colon"
>
:
</span>
</td>
<td
className="header-value"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "qvalue",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
</td>
</tr>
<tr>
<td
className="header-name"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "content-length",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
<span
className="header-colon"
>
:
</span>
</td>
<td
className="header-value"
>
<div
className="inline-input readonly"
contentEditable={undefined}
dangerouslySetInnerHTML={
Object {
"__html": "7",
}
}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onPaste={[Function]}
tabIndex={undefined}
/>
</td>
</tr>
</tbody>
</table>
</article>
<footer>
<div

View File

@ -46,7 +46,17 @@ export default function(){
"pretty_host": "address",
"scheme": "http",
"timestamp_end": null,
"timestamp_start": null
"timestamp_start": null,
"trailers": [
[
"trailer",
"qvalue"
],
[
"content-length",
"7"
]
]
},
"response": {
"contentHash": "ab530a13e45914982b79f9b7e3fba994cfd1f3fb22f71cea1afbf02b460c6d1d",
@ -66,7 +76,17 @@ export default function(){
"reason": "OK",
"status_code": 200,
"timestamp_end": 1495370312.4814625,
"timestamp_start": 1495370312.481462
"timestamp_start": 1495370312.481462,
"trailers": [
[
"trailer",
"qvalue"
],
[
"content-length",
"7"
]
]
},
"server_conn": {
"address": [

View File

@ -46,10 +46,15 @@ export default class Headers extends Component {
static propTypes = {
onChange: PropTypes.func.isRequired,
message: PropTypes.object.isRequired,
type: PropTypes.string.isRequired,
}
static defaultProps = {
type: 'headers',
}
onChange(row, col, val) {
const nextHeaders = _.cloneDeep(this.props.message.headers)
const nextHeaders = _.cloneDeep(this.props.message[this.props.type])
nextHeaders[row][col] = val
@ -75,7 +80,7 @@ export default class Headers extends Component {
}
onTab(row, col, e) {
const headers = this.props.message.headers
const headers = this.props.message[this.props.type]
if (col === 0) {
this._nextSel = `${row}-value`
@ -88,7 +93,7 @@ export default class Headers extends Component {
e.preventDefault()
const nextHeaders = _.cloneDeep(this.props.message.headers)
const nextHeaders = _.cloneDeep(this.props.message[this.props.type])
nextHeaders.push(['Name', 'Value'])
this.props.onChange(nextHeaders)
this._nextSel = `${row + 1}-key`
@ -113,11 +118,11 @@ export default class Headers extends Component {
render() {
const { message, readonly } = this.props
if (message[this.props.type]) {
return (
<table className="header-table">
<tbody>
{message.headers.map((header, i) => (
{message[this.props.type].map((header, i) => (
<tr key={i}>
<td className="header-name">
<HeaderEditor
@ -145,5 +150,13 @@ export default class Headers extends Component {
</tbody>
</table>
)
} else {
return (
<table className="header-table">
<tbody>
</tbody>
</table>
)
}
}
}

View File

@ -105,6 +105,14 @@ export class Request extends Component {
flow={flow}
onContentChange={content => updateFlow({ request: {content}})}
message={flow.request}/>
<hr/>
<Headers
message={flow.request}
readonly={!isEdit}
onChange={trailers => updateFlow({ request: { trailers } })}
type='trailers'
/>
</article>
<HideInStatic>
{!noContent &&
@ -150,6 +158,13 @@ export class Response extends Component {
onContentChange={content => updateFlow({ response: {content}})}
message={flow.response}
/>
<hr/>
<Headers
message={flow.response}
readonly={!isEdit}
onChange={trailers => updateFlow({ response: { trailers } })}
type='trailers'
/>
</article>
<HideInStatic>
{!noContent &&