aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/optmanager.py5
-rw-r--r--test/mitmproxy/test_optmanager.py1
-rw-r--r--test/mitmproxy/tools/web/test_app.py4
-rw-r--r--web/src/js/components/Modal/OptionMaster.jsx138
-rw-r--r--web/src/js/components/Modal/OptionTypes.jsx48
5 files changed, 144 insertions, 52 deletions
diff --git a/mitmproxy/optmanager.py b/mitmproxy/optmanager.py
index 5692d751..e1d74b8e 100644
--- a/mitmproxy/optmanager.py
+++ b/mitmproxy/optmanager.py
@@ -409,14 +409,15 @@ def dump_defaults(opts):
return ruamel.yaml.round_trip_dump(s)
-def dump_dicts(opts):
+def dump_dicts(opts, keys: typing.List[str]=None):
"""
Dumps the options into a list of dict object.
Return: A list like: { "anticache": { type: "bool", default: false, value: true, help: "help text"} }
"""
options_dict = {}
- for k in sorted(opts.keys()):
+ keys = keys if keys else opts.keys()
+ for k in sorted(keys):
o = opts._options[k]
t = typecheck.typespec_to_str(o.typespec)
option = {
diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py
index 0c400683..7b4ffb8b 100644
--- a/test/mitmproxy/test_optmanager.py
+++ b/test/mitmproxy/test_optmanager.py
@@ -341,6 +341,7 @@ def test_dump_defaults():
def test_dump_dicts():
o = options.Options()
assert optmanager.dump_dicts(o)
+ assert optmanager.dump_dicts(o, ['http2', 'anticomp'])
class TTypes(optmanager.OptManager):
diff --git a/test/mitmproxy/tools/web/test_app.py b/test/mitmproxy/tools/web/test_app.py
index e6d563e7..044b4595 100644
--- a/test/mitmproxy/tools/web/test_app.py
+++ b/test/mitmproxy/tools/web/test_app.py
@@ -255,8 +255,8 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
def test_options(self):
j = json(self.fetch("/options"))
- assert type(j) == list
- assert type(j[0]) == dict
+ assert type(j) == dict
+ assert type(j['anticache']) == dict
def test_option_update(self):
assert self.put_json("/options", {"anticache": True}).code == 200
diff --git a/web/src/js/components/Modal/OptionMaster.jsx b/web/src/js/components/Modal/OptionMaster.jsx
new file mode 100644
index 00000000..e16319fb
--- /dev/null
+++ b/web/src/js/components/Modal/OptionMaster.jsx
@@ -0,0 +1,138 @@
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import { update as updateOptions } from '../../ducks/options'
+
+PureBooleanOption.PropTypes = {
+ value: PropTypes.bool.isRequired,
+ onChange: PropTypes.func.isRequired,
+}
+
+function PureBooleanOption({ value, onChange, name, help}) {
+ return (
+ <div className="menu-entry">
+ <label>
+ <input type="checkbox"
+ checked={value}
+ onChange={onChange}
+ title={help}
+ />
+ { name }
+ </label>
+ </div>
+ )
+}
+
+PureStringOption.PropTypes = {
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+}
+
+function PureStringOption( { value, onChange, name, help }) {
+ let onKeyDown = (e) => {e.stopPropagation()}
+ return (
+ <div className="menu-entry">
+ <label>
+ { name }
+ <input type="text"
+ value={value}
+ onChange={onChange}
+ title={help}
+ onKeyDown={onKeyDown}
+ />
+ </label>
+ </div>
+ )
+}
+
+PureNumberOption.PropTypes = {
+ value: PropTypes.number.isRequired,
+ onChange: PropTypes.func.isRequired,
+}
+
+function PureNumberOption( {value, onChange, name, help }) {
+ let onKeyDown = (e) => {e.stopPropagation()}
+ return (
+ <div className="menu-entry">
+ <label>
+ { name }
+ <input type="number"
+ value={value}
+ onChange={onChange}
+ title={help}
+ onKeyDown={onKeyDown}
+ />
+ </label>
+ </div>
+ )
+}
+
+PureChoicesOption.PropTypes = {
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+}
+
+function PureChoicesOption( { value, onChange, name, help, choices }) {
+ return (
+ <div className="menu-entry">
+ <label htmlFor="">
+ { name }
+ <select name={name} onChange={onChange} title={help} selected={value}>
+ { choices.map(choice => (
+ <option value={choice}> {choice} </option>
+ ))}
+ </select>
+ </label>
+ </div>
+ )
+}
+
+const OptionTypes = {
+ bool: PureBooleanOption,
+ str: PureStringOption,
+ int: PureNumberOption,
+ "optional str": PureStringOption,
+ "sequence of str": PureStringOption,
+}
+
+Wrapper.displayName = 'OptionWrapper'
+
+
+function Wrapper({option, options, updateOptions, ...props}) {
+ let optionObj = options[option],
+ WrappedComponent = null
+ if (optionObj.choices) {
+ WrappedComponent = PureChoicesOption
+ } else {
+ WrappedComponent = OptionTypes[optionObj.type]
+ }
+
+ let onChange = (e) => {
+ switch (optionObj.type) {
+ case 'bool' :
+ updateOptions({[option]: !optionObj.value})
+ break
+ case 'int':
+ updateOptions({[option]: parseInt(e.target.value)})
+ break
+ default:
+ updateOptions({[option]: e.target.value})
+ }
+ }
+ return <WrappedComponent
+ children={props.children}
+ value={optionObj.value}
+ onChange={onChange}
+ name={option}
+ help={optionObj.help}
+ choices={optionObj.choices}
+ />
+}
+
+export default connect(
+ state => ({
+ options: state.options,
+ }),
+ {
+ updateOptions,
+ }
+)(Wrapper)
diff --git a/web/src/js/components/Modal/OptionTypes.jsx b/web/src/js/components/Modal/OptionTypes.jsx
deleted file mode 100644
index 8a9325e1..00000000
--- a/web/src/js/components/Modal/OptionTypes.jsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
-import { update as updateOptions } from '../../ducks/options'
-
-MenuToggle.propTypes = {
- value: PropTypes.bool.isRequired,
- onChange: PropTypes.func.isRequired,
- children: PropTypes.node.isRequired,
-}
-
-export function MenuToggle({ value, onChange, children }) {
- return (
- <div className="menu-entry">
- <label>
- <input type="checkbox"
- checked={value}
- onChange={onChange}/>
- {children}
- </label>
- </div>
- )
-}
-
-OptionsToggle.propTypes = {
- option: PropTypes.string.isRequired,
- children: PropTypes.node.isRequired,
-}
-
-export function OptionsToggle({ option, children, options, updateOptions }) {
- return (
- <MenuToggle
- value={ options[option].value }
- onChange={() => {console.log(options[option]);
- updateOptions({ [option]: !(options[option].value)}) }}
- >
- {children}
- </MenuToggle>
- )
-}
-
-OptionsToggle = connect(
- state => ({
- options: state.options,
- }),
- {
- updateOptions,
- }
-)(OptionsToggle)