Skip to content

Commit

Permalink
Initiator (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
cle-b authored Dec 4, 2022
1 parent d1c37d4 commit c6eb36c
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 55 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pyhttpdbg --pytest [arg1 --arg2 ...]
| library | status | known limitations |
|------------|---------------|---------------------------------------------|
| requests | supported | content not recorded if stream mode enabled |
| httpx | experimental | content not recorded if stream mode enabled |
| httpx | experimental | request not recorded if stream mode enabled |

## configuration

Expand Down Expand Up @@ -93,7 +93,7 @@ Many options are available:
* Hide the status column
* Hide the method column
* Hide the netloc in the url
* Hide the initiator column
* Hide the initiator rows

To keep your configuration, bookmark the page with the full search query.

Expand Down
4 changes: 2 additions & 2 deletions httpdbg/hooks/httpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def _hook_send(self, request, *args, **kwargs):

record = HTTPRecord()

record.initiator = get_initiator()
record.initiator = get_initiator(records._initiators)

record.url = str(request.url)
record.method = request.method
Expand Down Expand Up @@ -98,7 +98,7 @@ async def _hook_send(self, request, *args, **kwargs):

record = HTTPRecord()

record.initiator = get_initiator()
record.initiator = get_initiator(records._initiators)

record.url = str(request.url)
record.method = request.method
Expand Down
2 changes: 1 addition & 1 deletion httpdbg/hooks/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def _hook_send(self, request, *args, **kwargs):

record = HTTPRecord()

record.initiator = get_initiator()
record.initiator = get_initiator(records._initiators)

record.url = request.url
record.method = request.method
Expand Down
32 changes: 24 additions & 8 deletions httpdbg/initiator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,30 @@
import platform
import traceback

from httpdbg.utils import get_new_uuid


class Initiator(object):
def __init__(self, short_label, long_label, stack):
self.short_label = short_label
def __init__(self, id, short_label, long_label, stack):
self.id = id
self.short_label = f'{short_label[:77]}{"..." if len(short_label)>76 else ""}'
self.long_label = long_label
self.stack = stack

def to_json(self, full=True):
if full:
json = {
"id": self.id,
"short_label": self.short_label,
"long_label": self.long_label,
"stack": "\n".join(self.stack),
}
else:
json = {"short_label": self.short_label, "long_label": self.long_label}
json = {
"id": self.id,
"short_label": self.short_label,
"long_label": self.long_label,
}
return json


Expand All @@ -38,11 +46,12 @@ def in_lib(line):
)


def get_initiator():
def get_initiator(initiators):
short_label = ""
long_label = ""
stack = []
fullstack = traceback.format_stack()
id = None

if "PYTEST_CURRENT_TEST" in os.environ:
long_label = " ".join(os.environ["PYTEST_CURRENT_TEST"].split(" ")[:-1])
Expand All @@ -55,7 +64,9 @@ def get_initiator():
stack.append(line)
if "in pytest_pyfunc_call" in line or "in call_fixture_func" in line:
in_stack = True

if long_label not in initiators:
initiators[long_label] = get_new_uuid()
id = initiators[long_label]
else:
if compatible_path("httpdbg/mode_script.py") in "".join(
fullstack
Expand All @@ -66,8 +77,13 @@ def get_initiator():
stack.append(line)
long_label = stack[-1]
short_label = long_label.split("\n")[1]
hashstack = hash("".join(fullstack))
if hashstack not in initiators:
initiators[hashstack] = get_new_uuid()
id = initiators[hashstack]
else:
short_label = ""
long_label = ""
short_label = "console"
long_label = "console"
id = "console"

return Initiator(short_label, long_label, stack)
return Initiator(id, short_label, long_label, stack)
8 changes: 2 additions & 6 deletions httpdbg/records.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
# -*- coding: utf-8 -*-
import secrets
import string
from urllib.parse import urlparse


def get_new_uuid():
# important - the uuid must be compatible with method naming rules
return "".join(secrets.choice(string.ascii_letters) for i in range(10))
from httpdbg.utils import get_new_uuid


class HTTPRecords:
def __init__(self):
self.id = get_new_uuid()
self.requests = {}
self.requests_already_loaded = 0
self._initiators = {}

@property
def unread(self):
Expand Down
8 changes: 8 additions & 0 deletions httpdbg/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
import secrets
import string


def get_new_uuid():
# important - the uuid must be compatible with method naming rules
return "".join(secrets.choice(string.ascii_letters) for i in range(10))
8 changes: 4 additions & 4 deletions httpdbg/webapp/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ def default(self, req):


class RequestListPayload(JSONEncoder):
def default(self, reqs):
def default(self, records):
assert isinstance(
reqs, HTTPRecords
records, HTTPRecords
), "This encoder works only for HTTPRecords object."

payload = {"id": reqs.id, "requests": {}}
payload = {"id": records.id, "requests": {}}

for id, req in reqs.requests.items():
for id, req in records.requests.items():

payload["requests"][id] = {
"id": req.id,
Expand Down
4 changes: 2 additions & 2 deletions httpdbg/webapp/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@


class HttpbgHTTPRequestHandler(BaseHTTPRequestHandler):
def __init__(self, record, *args, **kwargs):
self.records = record
def __init__(self, records, *args, **kwargs):
self.records = records
super().__init__(*args, **kwargs)

def do_GET(self):
Expand Down
24 changes: 12 additions & 12 deletions httpdbg/webapp/static/index.htm
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ <h4>configuration</h4>
<br>

<input type="checkbox" id="cinitiator" name="hi" onchange="load_config_from_form(true)">
<label for="cinitiator">Hide the initiator column</label>
<label for="cinitiator">Hide the initiator rows</label>

<br>

Expand All @@ -67,12 +67,6 @@ <h4>configuration</h4>
<div class="grid-column grid-column-left">

<table class="requests-table" id="requests-list">
<colgroup>
<col span="1" class="status">
<col span="1" class="method">
<col span="1" class="url">
<col span="1" class="initiator">
</colgroup>

<thead>
<tr>
Expand All @@ -84,24 +78,30 @@ <h4>configuration</h4>
oncut="update_filter_url()" onpaste="update_filter_url()" onchange="update_filter_url()"
style="display: none;">
</th>
<th class="initiator" title="initiator">initiator</th>
</tr>
</thead>

<tbody>
</tbody>
<script id="template_initiator" type="x-tmpl-mustache">
<tbody id="initiator-{{initiator.id}}" name="initiator">
<tr class="initiator">
<td>
<span title="{{initiator.long_label}}" class="initiator-label">{{initiator.short_label}}</span>
</td>
</tr>
</tbody>
</script>

<script id="template_request" type="x-tmpl-mustache">
<tr id="request-{{id}}"
data-filter-url="{{url}}"
onclick="show_request('{{id}}')"
class="request">
<td class="status"><span data-tooltip="{{reason}}" class="tooltip tooltip-status">{{{status_code_view}}}</span></td>
<td class="method"><span>{{verb}}</span></td>
<td class="method"><span title="{{verb}}">{{verb}}</span></td>
<td class="url"><span title="{{url}}"><span class="netloc">{{netloc}}</span><span>{{urlext}}</span<></span></td>
<td class="initiator"><span title="{{initiator.long_label}}">{{initiator.short_label}}</span></td>
</tr>
</script>

</table>

</div>
Expand Down
16 changes: 12 additions & 4 deletions httpdbg/webapp/static/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ var k7_id = null;
async function refresh_resquests() {
var table = document.getElementById("requests-list");
var template_request = document.getElementById("template_request").innerHTML;
var template_initiator = document.getElementById("template_initiator").innerHTML;

if (global.k7 != k7_id) {
table.getElementsByTagName("tbody")[0].innerHTML = '';
var initiators = document.getElementsByName("initiator");
while (initiators.length > 0) {
initiators[0].remove();
}
document.getElementById("headers").innerHTML = 'select a request to view details';
document.getElementById("cookies").innerHTML = 'select a request to view details';
document.getElementById("body_sent").innerHTML = 'select a request to view details';
Expand All @@ -17,14 +21,18 @@ async function refresh_resquests() {
};
k7_id = global.k7;

var tbody = table.getElementsByTagName("tbody")[0];

for (const [request_id, request] of Object.entries(global.requests)) {
if (request.to_refresh) {
var elt = document.getElementById("request-" + request.id);
var rendered = Mustache.render(template_request, request);
if (!elt) {
tbody.insertAdjacentHTML("beforeend", rendered);
var elt_initiator = document.getElementById("initiator-" + request.initiator.id);
if (!elt_initiator) {
var rendered_initiator = Mustache.render(template_initiator, request);
table.insertAdjacentHTML("beforeend", rendered_initiator);
elt_initiator = document.getElementById("initiator-" + request.initiator.id);
};
elt_initiator.insertAdjacentHTML("beforeend", rendered);
} else {
elt.innerHTML = rendered;
};
Expand Down
1 change: 1 addition & 0 deletions httpdbg/webapp/static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
--table-header-text: #000000;
--table-header-btn-active: #cccccc;
--table-header-btn-hover: #eeeeee;
--table-initiator: #eeeeee;
--selected-url-text: #000000;
--tooltip-bg-color: #111111;
--tooltip-text: #ffffff;
Expand Down
24 changes: 11 additions & 13 deletions httpdbg/webapp/static/table.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,28 @@
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: auto;
}

.initiator {
text-align: left;
.initiator-label {
column-span: all;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 20%;
background-color: var(--table-initiator);
}

.status {
text-align: center;
width: 36px;
padding: 6px !important;
}


.method {
text-align: left;
width: 78px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 48px;
padding: 6px !important;
}

.request {
Expand All @@ -50,18 +53,13 @@
}

.requests-table td {
padding: 6px 10px;
padding: 6px;
}

.requests-table tbody tr {
border-bottom: 1px solid #dddddd;
}

.requests-table tbody tr:last-of-type {
border-bottom: 2px solid #009879;
}


.requests-table tbody tr.active-row {
font-weight: bold;
color: var(--selected-url-text);
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

setuptools.setup(
name="httpdbg",
version="0.1.2",
version="0.2.0",
author="cle-b",
author_email="[email protected]",
description="A very simple tool to debug HTTP(S) client requests",
Expand Down

0 comments on commit c6eb36c

Please sign in to comment.