mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-22 07:08:10 +00:00
Show http trailers in web-ui (#4142)
This commit is contained in:
parent
5ebc338fde
commit
5d0e1906e6
@ -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 ---
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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' }})])
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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": [
|
||||
|
@ -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,37 +118,45 @@ export default class Headers extends Component {
|
||||
|
||||
render() {
|
||||
const { message, readonly } = this.props
|
||||
|
||||
return (
|
||||
<table className="header-table">
|
||||
<tbody>
|
||||
{message.headers.map((header, i) => (
|
||||
<tr key={i}>
|
||||
<td className="header-name">
|
||||
<HeaderEditor
|
||||
ref={`${i}-key`}
|
||||
content={header[0]}
|
||||
readonly={readonly}
|
||||
onDone={val => this.onChange(i, 0, val)}
|
||||
onRemove={event => this.onRemove(i, 0, event)}
|
||||
onTab={event => this.onTab(i, 0, event)}
|
||||
/>
|
||||
<span className="header-colon">:</span>
|
||||
</td>
|
||||
<td className="header-value">
|
||||
<HeaderEditor
|
||||
ref={`${i}-value`}
|
||||
content={header[1]}
|
||||
readonly={readonly}
|
||||
onDone={val => this.onChange(i, 1, val)}
|
||||
onRemove={event => this.onRemove(i, 1, event)}
|
||||
onTab={event => this.onTab(i, 1, event)}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
if (message[this.props.type]) {
|
||||
return (
|
||||
<table className="header-table">
|
||||
<tbody>
|
||||
{message[this.props.type].map((header, i) => (
|
||||
<tr key={i}>
|
||||
<td className="header-name">
|
||||
<HeaderEditor
|
||||
ref={`${i}-key`}
|
||||
content={header[0]}
|
||||
readonly={readonly}
|
||||
onDone={val => this.onChange(i, 0, val)}
|
||||
onRemove={event => this.onRemove(i, 0, event)}
|
||||
onTab={event => this.onTab(i, 0, event)}
|
||||
/>
|
||||
<span className="header-colon">:</span>
|
||||
</td>
|
||||
<td className="header-value">
|
||||
<HeaderEditor
|
||||
ref={`${i}-value`}
|
||||
content={header[1]}
|
||||
readonly={readonly}
|
||||
onDone={val => this.onChange(i, 1, val)}
|
||||
onRemove={event => this.onRemove(i, 1, event)}
|
||||
onTab={event => this.onTab(i, 1, event)}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<table className="header-table">
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 &&
|
||||
|
Loading…
Reference in New Issue
Block a user