mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-22 15:37:45 +00:00
combine clientside and serverside contentviews
This commit is contained in:
parent
2807329fb2
commit
a56c2ca731
@ -306,36 +306,6 @@ class ReplayFlow(RequestHandler):
|
||||
|
||||
|
||||
class FlowContent(RequestHandler):
|
||||
def _get_content_view(self, message, viewmode):
|
||||
|
||||
try:
|
||||
content = message.content
|
||||
if content != message.raw_content:
|
||||
enc = "[decoded {}]".format(
|
||||
message.headers.get("content-encoding")
|
||||
)
|
||||
else:
|
||||
enc = None
|
||||
except ValueError:
|
||||
content = message.raw_content
|
||||
enc = "[cannot decode]"
|
||||
try:
|
||||
query = None
|
||||
if isinstance(message, models.HTTPRequest):
|
||||
query = message.query
|
||||
description, lines = contentviews.get_content_view(
|
||||
viewmode, content, headers=message.headers, query=query
|
||||
)
|
||||
except exceptions.ContentViewException:
|
||||
description, lines = contentviews.get_content_view(
|
||||
contentviews.get("Raw"), content, headers=message.headers
|
||||
)
|
||||
description = description.replace("Raw", "Couldn't parse: falling back to Raw")
|
||||
|
||||
if enc:
|
||||
description = " ".join([enc, description])
|
||||
|
||||
return description, lines
|
||||
|
||||
def post(self, flow_id, message):
|
||||
self.flow.backup()
|
||||
@ -369,21 +339,69 @@ class FlowContent(RequestHandler):
|
||||
self.set_header("Content-Type", "application/text")
|
||||
self.set_header("X-Content-Type-Options", "nosniff")
|
||||
self.set_header("X-Frame-Options", "DENY")
|
||||
self.write(message.raw_content)
|
||||
|
||||
cv = self.get_argument("cv", None)
|
||||
if cv:
|
||||
self.set_header("Content-Encoding", "")
|
||||
viewmode = next(v for v in contentviews.views if v.name == cv)
|
||||
description, lines = self._get_content_view(
|
||||
message, viewmode
|
||||
class FlowContentView(RequestHandler):
|
||||
def _get_content_view(self, message, viewmode):
|
||||
|
||||
try:
|
||||
content = message.content
|
||||
if content != message.raw_content:
|
||||
enc = "[decoded {}]".format(
|
||||
message.headers.get("content-encoding")
|
||||
)
|
||||
else:
|
||||
enc = None
|
||||
except ValueError:
|
||||
content = message.raw_content
|
||||
enc = "[cannot decode]"
|
||||
try:
|
||||
query = None
|
||||
if isinstance(message, models.HTTPRequest):
|
||||
query = message.query
|
||||
description, lines = contentviews.get_content_view(
|
||||
viewmode, content, headers=message.headers, query=query
|
||||
)
|
||||
except exceptions.ContentViewException:
|
||||
description, lines = contentviews.get_content_view(
|
||||
contentviews.get("Raw"), content, headers=message.headers
|
||||
)
|
||||
description = description.replace("Raw", "Couldn't parse: falling back to Raw")
|
||||
|
||||
self.write(dict(
|
||||
lines=list(lines),
|
||||
description=description
|
||||
))
|
||||
else:
|
||||
self.write(message.raw_content)
|
||||
if enc:
|
||||
description = " ".join([enc, description])
|
||||
|
||||
return description, lines
|
||||
|
||||
def get(self, flow_id, message, content_view):
|
||||
message = getattr(self.flow, message)
|
||||
|
||||
original_cd = message.headers.get("Content-Disposition", None)
|
||||
filename = None
|
||||
if original_cd:
|
||||
filename = re.search("filename=([\w\" \.\-\(\)]+)", original_cd)
|
||||
if filename:
|
||||
filename = filename.group(1)
|
||||
if not filename:
|
||||
filename = self.flow.request.path.split("?")[0].split("/")[-1]
|
||||
|
||||
filename = re.sub(r"[^\w\" \.\-\(\)]", "", filename)
|
||||
cd = "attachment; filename={}".format(filename)
|
||||
self.set_header("Content-Disposition", cd)
|
||||
self.set_header("Content-Type", "application/json")
|
||||
self.set_header("X-Content-Type-Options", "nosniff")
|
||||
self.set_header("X-Frame-Options", "DENY")
|
||||
|
||||
self.set_header("Content-Encoding", "")
|
||||
|
||||
description, lines = self._get_content_view(
|
||||
message, contentviews.get(content_view.replace('_', ' '))
|
||||
)
|
||||
|
||||
self.write(dict(
|
||||
lines=list(lines),
|
||||
description=description
|
||||
))
|
||||
|
||||
|
||||
class Events(RequestHandler):
|
||||
@ -412,7 +430,7 @@ class Settings(RequestHandler):
|
||||
stickyauth=self.master.options.stickyauth,
|
||||
stickycookie=self.master.options.stickycookie,
|
||||
stream= self.master.options.stream_large_bodies,
|
||||
contentViews= [v.name for v in contentviews.views]
|
||||
contentViews= [v.name.replace(' ', '_') for v in contentviews.views]
|
||||
)
|
||||
))
|
||||
|
||||
@ -477,6 +495,7 @@ class Application(tornado.web.Application):
|
||||
(r"/flows/(?P<flow_id>[0-9a-f\-]+)/replay", ReplayFlow),
|
||||
(r"/flows/(?P<flow_id>[0-9a-f\-]+)/revert", RevertFlow),
|
||||
(r"/flows/(?P<flow_id>[0-9a-f\-]+)/(?P<message>request|response)/content", FlowContent),
|
||||
(r"/flows/(?P<flow_id>[0-9a-f\-]+)/(?P<message>request|response)/content/(?P<content_view>[0-9a-zA-Z\-\_]+)", FlowContentView),
|
||||
(r"/settings", Settings),
|
||||
(r"/clear", ClearAll),
|
||||
]
|
||||
|
@ -1,10 +1,14 @@
|
||||
.contentview {
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight{
|
||||
color: pink;
|
||||
font-weight: bold;
|
||||
}
|
||||
.offset{
|
||||
color: blue
|
||||
}
|
||||
.text{
|
||||
|
||||
}
|
||||
.offset{ }
|
||||
.text{ }
|
||||
}
|
||||
|
@ -18,31 +18,19 @@ function ViewImage({ flow, message }) {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
ViewRaw.matches = () => true
|
||||
ViewRaw.propTypes = {
|
||||
Edit.propTypes = {
|
||||
content: React.PropTypes.string.isRequired,
|
||||
}
|
||||
function ViewRaw({ content, readonly, onChange }) {
|
||||
return readonly ? <pre>{content}</pre> : <CodeEditor content={content} onChange={onChange}/>
|
||||
}
|
||||
ViewRaw = ContentLoader(ViewRaw)
|
||||
|
||||
ViewAuto.matches = () => false
|
||||
ViewAuto.findView = msg => [ViewImage, ViewRaw].find(v => v.matches(msg)) || ViewRaw
|
||||
ViewAuto.propTypes = {
|
||||
message: React.PropTypes.object.isRequired,
|
||||
flow: React.PropTypes.object.isRequired,
|
||||
}
|
||||
function ViewAuto({ message, flow, readonly, onChange }) {
|
||||
const View = ViewAuto.findView(message)
|
||||
return <View message={message} flow={flow} readonly={readonly} onChange={onChange}/>
|
||||
function Edit({ content, onChange }) {
|
||||
return <CodeEditor content={content} onChange={onChange}/>
|
||||
}
|
||||
Edit = ContentLoader(Edit)
|
||||
|
||||
|
||||
function ViewServer({content, contentView, message, flow}){
|
||||
function ViewServer(props){
|
||||
const {content, contentView, message} = props
|
||||
let data = JSON.parse(content)
|
||||
let showImage = isImage.test(MessageUtils.getContentType(message))
|
||||
|
||||
return <div>
|
||||
{contentView != data.description &&
|
||||
@ -59,14 +47,12 @@ function ViewServer({content, contentView, message, flow}){
|
||||
</div>
|
||||
)}
|
||||
</pre>
|
||||
{showImage &&
|
||||
<div className="flowview-image">
|
||||
<img src={MessageUtils.getContentURL(flow, message)} alt="preview" className="img-thumbnail"/>
|
||||
</div>
|
||||
{ViewImage.matches(message) &&
|
||||
<ViewImage {...props} />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
ViewServer = ContentLoader(ViewServer)
|
||||
|
||||
export { ViewImage, ViewRaw, ViewAuto, ViewServer }
|
||||
export { Edit, ViewServer, ViewImage }
|
||||
|
@ -24,25 +24,18 @@ ViewButton = connect(state => ({
|
||||
ViewSelector.propTypes = {
|
||||
message: PropTypes.object.isRequired,
|
||||
}
|
||||
function ViewSelector({ message, contentViews }) {
|
||||
|
||||
let autoView = ContentViews.ViewAuto.findView(message)
|
||||
let autoViewName = (autoView.displayName || autoView.name)
|
||||
.toLowerCase()
|
||||
.replace('view', '')
|
||||
.replace(/ContentLoader\((.+)\)/,"$1")
|
||||
|
||||
function ViewSelector({contentViews, isEdit }) {
|
||||
let edit = ContentViews.Edit.displayName
|
||||
return (
|
||||
<div className="view-selector btn-group btn-group-xs">
|
||||
|
||||
{Object.keys(ContentViews).map(name =>
|
||||
name === "ViewRaw" &&
|
||||
<ViewButton key={name} name={name}>{name.toLowerCase().replace('view', '')}</ViewButton>
|
||||
{contentViews.map(name =>
|
||||
<ViewButton key={name} name={name}>{name.toLowerCase().replace('_', ' ')}</ViewButton>
|
||||
)}
|
||||
|
||||
{contentViews.map(name =>
|
||||
<ViewButton key={name} name={name}>{name.toLowerCase().replace('view', '')}</ViewButton>
|
||||
)}
|
||||
{isEdit &&
|
||||
<ViewButton key={edit} name={edit}>{edit.toLowerCase()}</ViewButton>
|
||||
}
|
||||
|
||||
</div>
|
||||
)
|
||||
@ -50,5 +43,6 @@ function ViewSelector({ message, contentViews }) {
|
||||
|
||||
export default connect (
|
||||
state => ({
|
||||
contentViews: state.settings.contentViews
|
||||
contentViews: state.settings.contentViews,
|
||||
isEdit: !!state.ui.flow.modifiedFlow,
|
||||
}))(ViewSelector)
|
||||
|
@ -19,12 +19,14 @@ const defaultState = {
|
||||
}
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
let wasInEditMode = !!(state.modifiedFlow)
|
||||
switch (action.type) {
|
||||
|
||||
case START_EDIT:
|
||||
return {
|
||||
...state,
|
||||
modifiedFlow: action.flow,
|
||||
contentView: 'Edit'
|
||||
}
|
||||
|
||||
case UPDATE_EDIT:
|
||||
@ -38,6 +40,7 @@ export default function reducer(state = defaultState, action) {
|
||||
...state,
|
||||
modifiedFlow: false,
|
||||
displayLarge: false,
|
||||
contentView: (wasInEditMode ? 'Auto' : state.contentView)
|
||||
}
|
||||
|
||||
case flowsActions.UPDATE:
|
||||
@ -49,6 +52,7 @@ export default function reducer(state = defaultState, action) {
|
||||
...state,
|
||||
modifiedFlow: false,
|
||||
displayLarge: false,
|
||||
contentView: (wasInEditMode ? 'Auto' : state.contentView)
|
||||
}
|
||||
} else {
|
||||
return state
|
||||
|
@ -49,7 +49,7 @@ export var MessageUtils = {
|
||||
} else if (message === flow.response) {
|
||||
message = "response";
|
||||
}
|
||||
return `/flows/${flow.id}/${message}/content` + (view ? `?cv=${view}` : '');
|
||||
return `/flows/${flow.id}/${message}/content` + (view ? `/${view}` : '');
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user