integrate feedback

This commit is contained in:
Martin Plattner 2020-09-04 15:02:58 +02:00
parent 2f434f91ff
commit 129c03e51a
4 changed files with 56 additions and 69 deletions

View File

@ -12,8 +12,7 @@ import typing
class CliDirector:
def __init__(self):
self.record_start = None
self.pause_between_keys = 0.1
self.pause_between_keys_rand = 0.25
self.pause_between_keys = 0.2
def start(self, filename: str, width: int = 0, height: int = 0) -> libtmux.Session:
self.start_session(width, height)
@ -34,7 +33,7 @@ class CliDirector:
self.asciinema_proc = subprocess.Popen([
"asciinema", "rec", "-y", "--overwrite", "-c", "tmux attach -t asciinema_recorder", filename])
self.pause(1.5)
self.record_start = datetime.datetime.now()
self.record_start = time.time()
def resize_window(self, width: int, height: int) -> None:
subprocess.Popen(["resize", "-s", str(height), str(width)], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -46,6 +45,7 @@ class CliDirector:
def end_recording(self) -> None:
self.asciinema_proc.terminate()
self.asciinema_proc.wait(timeout=5)
self.record_start = None
def end_session(self) -> None:
self.tmux_session.kill_session()
@ -59,7 +59,16 @@ class CliDirector:
if keys == " ":
keys = "Space"
target.send_keys(cmd=keys, enter=False, suppress_history=False)
self.pause(pause + random.uniform(0, self.pause_between_keys_rand))
# inspired by https://github.com/dmotz/TuringType
real_pause = random.uniform(0, pause) + 0.3 * pause
if keys == "Space" or keys == "," or keys == ".":
real_pause += random.uniform(0, pause)
if random.random() > 0.7:
real_pause += pause
if random.random() > 0.95:
real_pause += 2 * pause
self.pause(real_pause)
def type(self, keys: str, pause: typing.Optional[float] = None, target = None) -> None:
if pause is None:
@ -91,8 +100,8 @@ class CliDirector:
def message(self, msg: str, duration: typing.Optional[int] = None, add_instruction: bool = True, instruction_html: str = "") -> None:
if duration is None:
duration = len(msg) * 0.1 # seconds
self.tmux_session.set_option("display-time", int(duration * 1000)) # milliseconds
duration = len(msg) * 0.1 # seconds
self.tmux_session.set_option("display-time", int(duration * 1000)) # milliseconds
self.tmux_pane.display_message(" " + msg)
# todo: this is a hack and needs refactoring (instruction() is only defined in MitmCliDirector)
@ -119,8 +128,8 @@ class CliDirector:
@property
def current_time(self) -> float:
now = datetime.datetime.now()
return round((now - self.record_start).total_seconds(), 2)
now = time.time()
return round(now - self.record_start, 1)
@property
def current_pane(self) -> libtmux.Pane:
@ -130,7 +139,6 @@ class CliDirector:
class InstructionSpec(typing.NamedTuple):
instruction: str
time_from: float
time_from_str: str
time_to: float
@ -140,16 +148,14 @@ class MitmCliDirector(CliDirector):
super().__init__()
self.instructions: typing.List[InstructionSpec] = []
def instruction(self, instruction: str, duration: float = 3, time_from: typing.Optional[float] = None, correction: float = 0) -> None:
def instruction(self, instruction: str, duration: float = 3, time_from: typing.Optional[float] = None) -> None:
if time_from is None:
time_from = self.current_time
time_from_str = str(datetime.timedelta(seconds = int(time_from + correction)))[2:]
self.instructions.append(InstructionSpec(
str(len(self.instructions)+1) + ". " + instruction,
time_from=time_from + correction,
time_from_str=time_from_str,
time_to=time_from - correction + duration
instruction = str(len(self.instructions) + 1) + ". " + instruction,
time_from = round(time_from, 1),
time_to = round(time_from + duration, 1)
))
def save_instructions(self, output_path: str) -> None:

View File

@ -25,30 +25,17 @@ def record_user_interface(d: MitmCliDirector):
d.pause(2)
d.type("curl")
d.message("Use curls `-x` option to specify a proxy, e.g., `curl -x http://127.0.0.1:8080` to use mitmproxy.")
d.type(" -x http://127.0.0.1:8080")
d.message("Use curls `--proxy` option to configure mitmproxy as a proxy.")
d.type(" --proxy http://127.0.0.1:8080")
d.message("We use the text-based weather service `wttr.in`.")
d.exec(" \"http://wttr.in/Paris?0\"")
d.exec(" \"http://wttr.in/Dunedin?0\"")
d.pause(2)
d.press_key("Up")
d.press_key("Left", count=3)
d.press_key("BSpace", count=5)
d.exec("Miami")
d.pause(2)
d.press_key("Up")
d.press_key("Left", count=3)
d.press_key("BSpace", count=5)
d.exec("Tokio")
d.pause(2)
d.press_key("Up")
d.press_key("Left", count=3)
d.press_key("BSpace", count=5)
d.exec("London")
d.press_key("BSpace", count=7)
d.exec("Innsbruck")
d.pause(2)
d.exec("exit", target=pane_bottom)
@ -59,15 +46,16 @@ def record_user_interface(d: MitmCliDirector):
d.message("mitmproxy is controlled using keyboard shortcuts.")
d.message("Use your arrow keys `↑` and `↓` to change the focused flow (`>>`).")
d.press_key("Down", count=3, pause=0.5)
d.press_key("Up", count=2, pause=0.5)
d.press_key("Down", count=2, pause=0.5)
d.press_key("Down", pause=0.5)
d.press_key("Up", pause=0.5)
d.press_key("Down", pause=0.5)
d.press_key("Up", pause=0.5)
d.message("The focused flow (`>>`) is used as a target for various commands.")
d.message("One such command shows the flow details, it is bound to ``.")
d.message("One such command shows the flow details, it is bound to `ENTER`.")
d.message("Press `` to view the details of the focused flow.")
d.message("Press `ENTER` to view the details of the focused flow.")
d.press_key("Enter")
d.message("The flow details view has 3 panes: request, response, and detail.")
@ -83,6 +71,7 @@ def record_user_interface(d: MitmCliDirector):
d.pause(2)
d.press_key("Down", count=20, pause=0.25)
d.message("Tip: Remember the `?` shortcut. It works in every view.")
d.message("Press `q` to exit the current view.")
d.type("q")
@ -98,7 +87,7 @@ def record_user_interface(d: MitmCliDirector):
d.message("The argument `@focus` defines the target flow.")
d.message("Press `` to execute the command.")
d.message("Press `ENTER` to execute the command.")
d.press_key("Enter")
d.message("Commands unleash the full power of mitmproxy, i.e., to configure interceptions.")
@ -129,8 +118,8 @@ def record_intercept_requests(d: MitmCliDirector):
d.message("Additionally, we use the filter `~q` to only intercept requests, but not responses.")
d.message("We combine both flow filters using `&`.")
d.message("Enter `~u /Paris & ~q` between the quotes of the `set intercept` command and press `↵`.")
d.exec("~u /Paris & ~q")
d.message("Enter `~u /Dunedin & ~q` between the quotes of the `set intercept` command and press `ENTER`.")
d.exec("~u /Dunedin & ~q")
d.message("The bottom bar shows that the interception has been configured.")
d.message("Lets generate a request using `curl` in a separate terminal.")
@ -142,22 +131,17 @@ def record_intercept_requests(d: MitmCliDirector):
d.focus_pane(pane_bottom)
d.pause(2)
d.type("curl")
d.message("Use curls `-x` option to specify a proxy, e.g., `curl -x http://127.0.0.1:8080` to use mitmproxy.")
d.type(" -x http://127.0.0.1:8080")
d.message("We use the text-based weather service `wttr.in`.")
d.exec(" \"http://wttr.in/Paris?0\"")
d.exec("curl --proxy http://127.0.0.1:8080 \"http://wttr.in/Dunedin?0\"")
d.pause(2)
d.focus_pane(pane_top)
d.message("You will see a new line in in the list of flows.")
d.message("You see a new line in in the list of flows.")
d.message("The new flow is displayed in red to indicate that it has been intercepted.")
d.message("Put the focus (`>>`) on the intercepted flow. This is already the case in our example.")
d.message("Press `a` to resume this flow without making any changes.")
d.type("a")
d.pause(2)
d.focus_pane(pane_bottom)
@ -187,10 +171,10 @@ def record_modify_requests(d: MitmCliDirector):
d.pause(3)
d.message("We configure and use the same interception rule as in the last tutorial.")
d.message("Press `i` to prepopulate mitmproxys command prompt, enter the flow filter `~u /Paris & ~q`, and press `↵`.")
d.message("Press `i` to prepopulate mitmproxys command prompt, enter the flow filter `~u /Dunedin & ~q`, and press `ENTER`.")
d.type("i")
d.pause(2)
d.exec("~u /Paris & ~q")
d.exec("~u /Dunedin & ~q")
d.message("Lets generate a request using `curl` in a separate terminal.")
@ -201,8 +185,7 @@ def record_modify_requests(d: MitmCliDirector):
d.focus_pane(pane_bottom)
d.pause(2)
d.type("curl -x http://127.0.0.1:8080")
d.exec(" \"http://wttr.in/Paris?0\"")
d.exec("curl --proxy http://127.0.0.1:8080 \"http://wttr.in/Dunedin?0\"")
d.pause(2)
d.focus_pane(pane_top)
@ -210,7 +193,7 @@ def record_modify_requests(d: MitmCliDirector):
d.message("We now want to modify the intercepted request.")
d.message("Put the focus (`>>`) on the intercepted flow. This is already the case in our example.")
d.message("Press `` to open the details view for the intercepted flow.")
d.message("Press `ENTER` to open the details view for the intercepted flow.")
d.press_key("Enter")
d.message("Press `e` to edit the intercepted flow.")
@ -218,19 +201,19 @@ def record_modify_requests(d: MitmCliDirector):
d.message("mitmproxy asks which part to modify.")
d.message("Select `path` by using your arrow keys and press ``.")
d.message("Select `path` by using your arrow keys and press `ENTER`.")
d.press_key("Down", count=3, pause=0.5)
d.pause(1)
d.press_key("Enter")
d.message("mitmproxy shows all path components line by line, in our example its just one element: `Paris`.")
d.message("Press `` to modify the selected path component.")
d.message("mitmproxy shows all path components line by line, in our example its just `Dunedin`.")
d.message("Press `ENTER` to modify the selected path component.")
d.press_key("Down", pause=2)
d.press_key("Enter")
d.message("Replace `Paris` with `Tokio`.")
d.press_key("BSpace", count=5, pause=0.5)
d.type("Tokio", pause=0.5)
d.message("Replace `Dunedin` with `Innsbruck`.")
d.press_key("BSpace", count=7, pause=0.5)
d.type("Innsbruck", pause=0.5)
d.message("Press `ESC` to confirm your change.")
d.press_key("Escape")
@ -242,7 +225,7 @@ def record_modify_requests(d: MitmCliDirector):
d.type("a")
d.pause(2)
d.message("You see that the request URL was modified and `wttr.in` replied with the weather report for `Tokio`.")
d.message("You see that the request URL was modified and `wttr.in` replied with the weather report for `Innsbruck`.")
d.save_instructions("recordings/mitmproxy_modify_requests_instructions.json")
d.end()
@ -267,7 +250,7 @@ def record_replay_requests(d: MitmCliDirector):
d.focus_pane(pane_bottom)
d.pause(2)
d.exec("curl -x http://127.0.0.1:8080 \"http://wttr.in/Paris?0\"")
d.exec("curl --proxy http://127.0.0.1:8080 \"http://wttr.in/Dunedin?0\"")
d.pause(2)
d.focus_pane(pane_top)

View File

@ -96,7 +96,6 @@ figure.has-border img {
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.25);
}
// reset bulma pre styles
.asciicast-wrapper {
margin: 2rem 0;
@ -105,6 +104,7 @@ figure.has-border img {
margin-bottom: 1rem;
}
// reset bulma pre styles
pre.asciinema-terminal {
padding: 0;
overflow-x: hidden;
@ -115,10 +115,8 @@ figure.has-border img {
justify-content: space-between;
}
.panel-block.is-active {
.tag {
background-color: $link;
color: $white;
}
.panel-block.is-active .tag {
background-color: $link;
color: $white;
}
}

View File

@ -11,7 +11,7 @@
{{- range $instr := $data -}}
<a href="#" class="panel-block" data-from="{{ $instr.time_from }}" data-to="{{ $instr.time_to }}">
<span class="instruction-text">{{ $instr.instruction | markdownify }}</span>
<span class="tag is-light">{{ $instr.time_from_str }}</span>
<span class="tag is-light">{{ int $instr.time_from | dateFormat "04:05" }}</span>
</a>
{{- end -}}
</article>