httpdbg 0.13.2__tar.gz → 0.13.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {httpdbg-0.13.2 → httpdbg-0.13.4}/PKG-INFO +1 -1
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/__init__.py +1 -1
- httpdbg-0.13.4/httpdbg/preview.py +53 -0
- httpdbg-0.13.4/httpdbg/webapp/static/filter.js +29 -0
- httpdbg-0.13.4/httpdbg/webapp/static/icons/filter-outline-icon.svg +1 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/index.htm +2 -2
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/render.js +43 -1
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/table.css +8 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg.egg-info/PKG-INFO +1 -1
- httpdbg-0.13.4/tests/test_preview.py +56 -0
- httpdbg-0.13.2/httpdbg/preview.py +0 -88
- httpdbg-0.13.2/httpdbg/webapp/static/filter.js +0 -18
- httpdbg-0.13.2/httpdbg/webapp/static/icons/filter-outline-icon.svg +0 -1
- httpdbg-0.13.2/tests/test_preview.py +0 -96
- {httpdbg-0.13.2 → httpdbg-0.13.4}/LICENSE +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/README.md +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/__main__.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/args.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/__init__.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/aiohttp.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/all.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/generic.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/httpx.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/requests.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/socket.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/urllib3.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/hooks/utils.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/initiator.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/mode_console.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/mode_module.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/mode_script.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/records.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/server.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/utils.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/__init__.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/api.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/app.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/api.js +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/column.css +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/configuration.js +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/detail.css +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/favicon.ico +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/download-install-line-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/engine-gears-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/files-papers-outline-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/information-mark-circle-outline-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/math-multiplication-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/push-pin-green-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/question-mark-round-line-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/recycle-bin-line-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/wait-sandclock-icon.svg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/main.js +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/mustache.min.js +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/style.css +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg.egg-info/SOURCES.txt +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg.egg-info/dependency_links.txt +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg.egg-info/entry_points.txt +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg.egg-info/top_level.txt +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/pyproject.toml +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/setup.cfg +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_api.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_cli.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_context_manager.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_hook_aiohttp.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_hook_httpx.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_hook_requests.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_hook_urllib3.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_initiator.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_mode_console.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_mode_module_pytest.py +0 -0
- {httpdbg-0.13.2 → httpdbg-0.13.4}/tests/test_mode_script.py +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from typing import Tuple, Dict, Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def parse_content_type(content_type: str) -> Tuple[str, Dict[str, str]]:
|
|
6
|
+
s = content_type.split(";")
|
|
7
|
+
media_type = s[0]
|
|
8
|
+
directives = {}
|
|
9
|
+
for directive in s[1:]:
|
|
10
|
+
sp = directive.split("=")
|
|
11
|
+
if len(sp) == 2:
|
|
12
|
+
directives[sp[0].strip()] = sp[1].strip()
|
|
13
|
+
return media_type, directives
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def generate_preview(
|
|
17
|
+
raw_data: bytes, content_type: str, content_encoding: str
|
|
18
|
+
) -> Dict[str, Union[str, bool]]:
|
|
19
|
+
body: Dict[str, Union[str, bool]] = {}
|
|
20
|
+
|
|
21
|
+
body["content_type"] = content_type
|
|
22
|
+
|
|
23
|
+
if content_encoding.lower() == "br":
|
|
24
|
+
try:
|
|
25
|
+
import brotli # type: ignore
|
|
26
|
+
|
|
27
|
+
raw_data = brotli.decompress(raw_data)
|
|
28
|
+
except Exception:
|
|
29
|
+
# if there is no brotli library available to decompress the data we keep the compressed data
|
|
30
|
+
pass
|
|
31
|
+
elif content_encoding.lower() == "gzip":
|
|
32
|
+
try:
|
|
33
|
+
import zlib
|
|
34
|
+
|
|
35
|
+
raw_data = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(raw_data)
|
|
36
|
+
except Exception:
|
|
37
|
+
pass
|
|
38
|
+
# TODO deflate
|
|
39
|
+
|
|
40
|
+
if "image/" in content_type.lower():
|
|
41
|
+
body["image"] = True
|
|
42
|
+
else:
|
|
43
|
+
if isinstance(raw_data, str):
|
|
44
|
+
body["text"] = raw_data
|
|
45
|
+
elif isinstance(raw_data, bytes):
|
|
46
|
+
try:
|
|
47
|
+
body["text"] = raw_data.decode(
|
|
48
|
+
parse_content_type(content_type)[1].get("charset", "utf-8")
|
|
49
|
+
)
|
|
50
|
+
except Exception:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
return body
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function update_filter_url() {
|
|
4
|
+
var sheet = document.getElementById("filter").sheet;
|
|
5
|
+
|
|
6
|
+
while (sheet.cssRules.length > 0) {
|
|
7
|
+
sheet.deleteRule(0);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
var value = document.getElementById("filter-url").value;
|
|
11
|
+
|
|
12
|
+
if (value == "") {
|
|
13
|
+
// if there is no filter, all rows are visible
|
|
14
|
+
sheet.insertRule("[data-filter-url] {display: table-row;}");
|
|
15
|
+
sheet.insertRule(".initiator-header {display: table-row-group;}");
|
|
16
|
+
} else {
|
|
17
|
+
// if there is a filter, only the requests that match the filter are visible
|
|
18
|
+
sheet.insertRule("[data-filter-url*='" + value + "'] {display: table-row;}");
|
|
19
|
+
if (CSS.supports("selector(:has(*))")) {
|
|
20
|
+
// an initiator row is visible only if it contains at least one visible request
|
|
21
|
+
sheet.insertRule(".initiator-header:has([data-filter-url*='" + value + "']) {display: table-row-group;}");
|
|
22
|
+
// if there is a filter and no request visible, the filter icon is red
|
|
23
|
+
sheet.insertRule(".requests-table:not(:has([data-filter-url*='" + value + "'])):has(tbody) .icon-filter {filter: grayscale(0%) !important;}");
|
|
24
|
+
} else {
|
|
25
|
+
// in case :has is not supported, the initiator rows are always visible
|
|
26
|
+
sheet.insertRule(".initiator-header {display: table-row-group;}");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 410.73"><path fill="red" stroke="black" fill-rule="nonzero" d="M335.62 410.73H164.96V239.89L13.31 59.96C7.33 52.52 3.19 44.79 1.29 37.65c-1.79-6.72-1.76-13.28.34-19.1 2.3-6.44 6.92-11.63 13.91-14.9C20.35 1.41 26.3.13 33.4.1L472.7.04c7.93-.29 14.95.96 20.74 3.44 7.02 2.97 12.28 7.87 15.44 14.17 3.05 6.1 3.93 13.27 2.34 21.06-1.5 7.24-5.17 15.11-11.32 23.16l-151.94 178.1v170.76h-12.34zm95.61-347.71-69.16 81.05-18.67-16.01 69.16-81.05 18.67 16.01zm-84.8 99.39-24.45 28.66-18.68-16.01 24.45-28.66 18.68 16.01zM189.64 386.06h133.64V235.48l3-8L480.45 46.79c3.77-4.97 5.94-9.39 6.7-13.04.45-2.2.35-3.95-.24-5.12-.49-.97-1.58-1.87-3.19-2.55-2.53-1.13-6.06-1.64-10.44-1.42l-439.84.06c-3.33-.05-5.83.41-7.5 1.18-.68.32-1.09.65-1.18.92-.32.91-.2 2.48.33 4.46 1.05 3.96 3.61 8.57 7.38 13.28L186.7 227.59l2.94 7.89v150.58z"/></svg>
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
<th class="method" title="method"></th>
|
|
116
116
|
<th class="url">
|
|
117
117
|
url
|
|
118
|
-
<img class="icon" src="static/icons/filter-outline-icon.svg-+-$**HTTPDBG_VERSION**$"
|
|
118
|
+
<img class="icon icon-filter" src="static/icons/filter-outline-icon.svg-+-$**HTTPDBG_VERSION**$"
|
|
119
119
|
alt="filter for url" />
|
|
120
120
|
<label for="filter-url" class="visuallyhidden">
|
|
121
121
|
filter for url
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
</thead>
|
|
129
129
|
|
|
130
130
|
<script id="template_initiator" type="x-tmpl-mustache">
|
|
131
|
-
<tbody id="initiator-{{initiator.id}}" name="initiator">
|
|
131
|
+
<tbody id="initiator-{{initiator.id}}" name="initiator" class="initiator-header">
|
|
132
132
|
<tr class="initiator">
|
|
133
133
|
<td colspan="4" class="initiator-label" title="{{initiator.long_label}}">
|
|
134
134
|
{{initiator.short_label}}
|
|
@@ -127,6 +127,12 @@ function fill_content(request_id, name) {
|
|
|
127
127
|
|
|
128
128
|
if (request.body && request.body.text) {
|
|
129
129
|
request.body.raw_text = "global.requests['" + request_id + "'].data.request.body.text";
|
|
130
|
+
|
|
131
|
+
const parsed_text = parse_raw_text(request.body.text, request.body.content_type);
|
|
132
|
+
if (parsed_text) {
|
|
133
|
+
request.body.parsed = parsed_text;
|
|
134
|
+
}
|
|
135
|
+
|
|
130
136
|
if (request.body.parsed) {
|
|
131
137
|
request.body.parsed_text = "global.requests['" + request_id + "'].data.request.body.parsed";
|
|
132
138
|
}
|
|
@@ -140,6 +146,12 @@ function fill_content(request_id, name) {
|
|
|
140
146
|
|
|
141
147
|
if (response.body && response.body.text) {
|
|
142
148
|
response.body.raw_text = "global.requests['" + request_id + "'].data.response.body.text";
|
|
149
|
+
|
|
150
|
+
const parsed_text = parse_raw_text(response.body.text, response.body.content_type);
|
|
151
|
+
if (parsed_text) {
|
|
152
|
+
response.body.parsed = parsed_text;
|
|
153
|
+
}
|
|
154
|
+
|
|
143
155
|
if (response.body.parsed) {
|
|
144
156
|
response.body.parsed_text = "global.requests['" + request_id + "'].data.response.body.parsed";
|
|
145
157
|
}
|
|
@@ -314,7 +326,7 @@ function select_next_request() {
|
|
|
314
326
|
|
|
315
327
|
if (request == undefined) {
|
|
316
328
|
// maybe there are some requests under another initiator
|
|
317
|
-
var next_initiator = document.querySelector(".active-row").parentElement.nextElementSibling;
|
|
329
|
+
var next_initiator = document.querySelector(".active-row").parentElement.nextElementSibling;
|
|
318
330
|
|
|
319
331
|
if (next_initiator != undefined) {
|
|
320
332
|
request = next_initiator.querySelector(".request");
|
|
@@ -324,4 +336,34 @@ function select_next_request() {
|
|
|
324
336
|
if (request != undefined) {
|
|
325
337
|
request.click();
|
|
326
338
|
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function parse_raw_text(raw_text, content_type) {
|
|
342
|
+
var parsed_text="";
|
|
343
|
+
|
|
344
|
+
if (content_type.toLowerCase().includes("json")) {
|
|
345
|
+
try {
|
|
346
|
+
parsed_text = JSON.stringify(JSON.parse(raw_text), null, " ");
|
|
347
|
+
} catch {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
} else if (content_type.toLowerCase().includes("x-www-form-urlencoded")) {
|
|
351
|
+
try {
|
|
352
|
+
var params = new URLSearchParams(raw_text);
|
|
353
|
+
|
|
354
|
+
for (const key of params.keys()) {
|
|
355
|
+
params.getAll(key).forEach((value) => {
|
|
356
|
+
try {
|
|
357
|
+
parsed_text += key + ": " + JSON.stringify(JSON.parse(value), null, " ") + "\n";
|
|
358
|
+
} catch {
|
|
359
|
+
parsed_text += key + ": " + value + "\n";
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
} catch {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return parsed_text;
|
|
327
369
|
}
|
|
@@ -70,6 +70,10 @@
|
|
|
70
70
|
padding: 6px !important;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
.initiator-header {
|
|
74
|
+
display: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
73
77
|
.request {
|
|
74
78
|
display: none;
|
|
75
79
|
}
|
|
@@ -100,4 +104,8 @@
|
|
|
100
104
|
width: 50%;
|
|
101
105
|
border-width: 0px;
|
|
102
106
|
padding: 1px 2px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.icon-filter {
|
|
110
|
+
filter: grayscale(100%);
|
|
103
111
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from httpdbg.preview import generate_preview
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.mark.preview
|
|
8
|
+
def test_preview_unknown_type_text():
|
|
9
|
+
body = generate_preview("a text", "unknown/type", "")
|
|
10
|
+
assert body == {"text": "a text", "content_type": "unknown/type"}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.preview
|
|
14
|
+
def test_preview_unknown_type_bytes():
|
|
15
|
+
body = generate_preview(b"a text", "unknown/type", "")
|
|
16
|
+
assert body == {"text": "a text", "content_type": "unknown/type"}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.mark.preview
|
|
20
|
+
@pytest.mark.parametrize("content_type", ["text/json", "application/json", "text", ""])
|
|
21
|
+
def test_preview_text(content_type):
|
|
22
|
+
raw_data = '{"a": "1", "b": {"c": 2} }'
|
|
23
|
+
body = generate_preview(raw_data, content_type, "")
|
|
24
|
+
|
|
25
|
+
assert body == {
|
|
26
|
+
"text": raw_data,
|
|
27
|
+
"content_type": content_type,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.mark.preview
|
|
32
|
+
def test_preview_image():
|
|
33
|
+
body = generate_preview(None, "image/png", "")
|
|
34
|
+
|
|
35
|
+
assert body == {
|
|
36
|
+
"image": True,
|
|
37
|
+
"content_type": "image/png",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_preview_application_no_content_type_text():
|
|
42
|
+
body = generate_preview("just text", "", "")
|
|
43
|
+
|
|
44
|
+
assert body == {
|
|
45
|
+
"text": "just text",
|
|
46
|
+
"content_type": "",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_preview_application_no_content_type_bytes():
|
|
51
|
+
body = generate_preview("just éà bytes".encode("utf-8"), "", "")
|
|
52
|
+
|
|
53
|
+
assert body == {
|
|
54
|
+
"text": "just éà bytes",
|
|
55
|
+
"content_type": "",
|
|
56
|
+
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import json
|
|
3
|
-
import urllib
|
|
4
|
-
from typing import Tuple, Dict, Union
|
|
5
|
-
from xml.dom import minidom
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def parse_content_type(content_type: str) -> Tuple[str, Dict[str, str]]:
|
|
9
|
-
s = content_type.split(";")
|
|
10
|
-
media_type = s[0]
|
|
11
|
-
directives = {}
|
|
12
|
-
for directive in s[1:]:
|
|
13
|
-
sp = directive.split("=")
|
|
14
|
-
if len(sp) == 2:
|
|
15
|
-
directives[sp[0].strip()] = sp[1].strip()
|
|
16
|
-
return media_type, directives
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def generate_preview(
|
|
20
|
-
raw_data: bytes, content_type: str, content_encoding: str
|
|
21
|
-
) -> Dict[str, Union[str, bool]]:
|
|
22
|
-
body: Dict[str, Union[str, bool]] = {}
|
|
23
|
-
|
|
24
|
-
if content_encoding.lower() == "br":
|
|
25
|
-
try:
|
|
26
|
-
import brotli # type: ignore
|
|
27
|
-
|
|
28
|
-
raw_data = brotli.decompress(raw_data)
|
|
29
|
-
except Exception:
|
|
30
|
-
# if there is no brotli library available to decompress the data we keep the compressed data
|
|
31
|
-
pass
|
|
32
|
-
elif content_encoding.lower() == "gzip":
|
|
33
|
-
try:
|
|
34
|
-
import zlib
|
|
35
|
-
|
|
36
|
-
raw_data = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(raw_data)
|
|
37
|
-
except Exception:
|
|
38
|
-
pass
|
|
39
|
-
# TODO deflate
|
|
40
|
-
|
|
41
|
-
if "image/" in content_type.lower():
|
|
42
|
-
body["image"] = True
|
|
43
|
-
else:
|
|
44
|
-
if isinstance(raw_data, str):
|
|
45
|
-
body["text"] = raw_data
|
|
46
|
-
elif isinstance(raw_data, bytes):
|
|
47
|
-
try:
|
|
48
|
-
body["text"] = raw_data.decode(
|
|
49
|
-
parse_content_type(content_type)[1].get("charset", "utf-8")
|
|
50
|
-
)
|
|
51
|
-
except Exception:
|
|
52
|
-
pass
|
|
53
|
-
|
|
54
|
-
if body.get("text"):
|
|
55
|
-
if isinstance(body["text"], str):
|
|
56
|
-
# json
|
|
57
|
-
try:
|
|
58
|
-
body["parsed"] = json.dumps(
|
|
59
|
-
json.loads(body["text"]), sort_keys=True, indent=4
|
|
60
|
-
)
|
|
61
|
-
except Exception:
|
|
62
|
-
# xml, ...
|
|
63
|
-
try:
|
|
64
|
-
lines = minidom.parseString(body["text"]).toprettyxml(
|
|
65
|
-
indent=" "
|
|
66
|
-
)
|
|
67
|
-
body["parsed"] = "\n".join(
|
|
68
|
-
[line for line in lines.split("\n") if line.strip() != ""]
|
|
69
|
-
)
|
|
70
|
-
except Exception:
|
|
71
|
-
# query string
|
|
72
|
-
try:
|
|
73
|
-
if (
|
|
74
|
-
parse_content_type(content_type)[0]
|
|
75
|
-
== "application/x-www-form-urlencoded"
|
|
76
|
-
):
|
|
77
|
-
qs = []
|
|
78
|
-
for key, value in urllib.parse.parse_qsl(
|
|
79
|
-
body["text"], strict_parsing=True
|
|
80
|
-
):
|
|
81
|
-
if value:
|
|
82
|
-
qs.append(f"{key}={value}")
|
|
83
|
-
if qs:
|
|
84
|
-
body["parsed"] = "\n\n".join(qs)
|
|
85
|
-
except Exception:
|
|
86
|
-
pass
|
|
87
|
-
|
|
88
|
-
return body
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
function update_filter_url() {
|
|
4
|
-
var sheet = document.getElementById("filter").sheet;
|
|
5
|
-
|
|
6
|
-
while (sheet.cssRules.length > 0) {
|
|
7
|
-
sheet.deleteRule(0);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
var value = document.getElementById("filter-url").value;
|
|
11
|
-
if (value == "") {
|
|
12
|
-
new_rule = '[data-filter-url] {display: table-row;}'
|
|
13
|
-
} else {
|
|
14
|
-
var new_rule = '[data-filter-url*="' + value + '"] {display: table-row;}'
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
sheet.insertRule(new_rule);
|
|
18
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 410.73"><path fill-rule="nonzero" d="M335.62 410.73H164.96V239.89L13.31 59.96C7.33 52.52 3.19 44.79 1.29 37.65c-1.79-6.72-1.76-13.28.34-19.1 2.3-6.44 6.92-11.63 13.91-14.9C20.35 1.41 26.3.13 33.4.1L472.7.04c7.93-.29 14.95.96 20.74 3.44 7.02 2.97 12.28 7.87 15.44 14.17 3.05 6.1 3.93 13.27 2.34 21.06-1.5 7.24-5.17 15.11-11.32 23.16l-151.94 178.1v170.76h-12.34zm95.61-347.71-69.16 81.05-18.67-16.01 69.16-81.05 18.67 16.01zm-84.8 99.39-24.45 28.66-18.68-16.01 24.45-28.66 18.68 16.01zM189.64 386.06h133.64V235.48l3-8L480.45 46.79c3.77-4.97 5.94-9.39 6.7-13.04.45-2.2.35-3.95-.24-5.12-.49-.97-1.58-1.87-3.19-2.55-2.53-1.13-6.06-1.64-10.44-1.42l-439.84.06c-3.33-.05-5.83.41-7.5 1.18-.68.32-1.09.65-1.18.92-.32.91-.2 2.48.33 4.46 1.05 3.96 3.61 8.57 7.38 13.28L186.7 227.59l2.94 7.89v150.58z"/></svg>
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import pytest
|
|
3
|
-
|
|
4
|
-
from httpdbg.preview import generate_preview
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@pytest.mark.preview
|
|
8
|
-
def test_preview_unknown_type_text():
|
|
9
|
-
body = generate_preview("a text", "unknown/type", "")
|
|
10
|
-
assert body == {"text": "a text"}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@pytest.mark.preview
|
|
14
|
-
def test_preview_unknown_type_bytes():
|
|
15
|
-
body = generate_preview(b"a text", "unknown/type", "")
|
|
16
|
-
assert body == {"text": "a text"}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@pytest.mark.preview
|
|
20
|
-
@pytest.mark.parametrize(
|
|
21
|
-
"content_type",
|
|
22
|
-
["text/html", "application/xhtml+xml", "application/xml", "text", ""],
|
|
23
|
-
)
|
|
24
|
-
def test_preview_xml(content_type):
|
|
25
|
-
raw_data = "<html><head><title>:-)</title></head><body>empty</body></html>"
|
|
26
|
-
body = generate_preview(raw_data, content_type, "")
|
|
27
|
-
parsed = '<?xml version="1.0" ?>\n<html>\n <head>\n <title>:-)</title>\n </head>\n <body>empty</body>\n</html>'
|
|
28
|
-
|
|
29
|
-
assert body == {
|
|
30
|
-
"text": raw_data,
|
|
31
|
-
"parsed": parsed,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@pytest.mark.preview
|
|
36
|
-
@pytest.mark.parametrize("content_type", ["text/json", "application/json", "text", ""])
|
|
37
|
-
def test_preview_json(content_type):
|
|
38
|
-
raw_data = '{"a": "1", "b": {"c": 2} }'
|
|
39
|
-
body = generate_preview(raw_data, "application/json", "")
|
|
40
|
-
parsed = '{\n "a": "1",\n "b": {\n "c": 2\n }\n}'
|
|
41
|
-
|
|
42
|
-
assert body == {
|
|
43
|
-
"text": raw_data,
|
|
44
|
-
"parsed": parsed,
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@pytest.mark.preview
|
|
49
|
-
def test_preview_query_string():
|
|
50
|
-
raw_data = "a=1&b=2&c=%7B%27er%27%3A+43434%7D"
|
|
51
|
-
body = generate_preview(
|
|
52
|
-
raw_data,
|
|
53
|
-
"application/x-www-form-urlencoded",
|
|
54
|
-
"",
|
|
55
|
-
)
|
|
56
|
-
parsed = "a=1\n\nb=2\n\nc={'er': 43434}"
|
|
57
|
-
|
|
58
|
-
assert body == {
|
|
59
|
-
"text": raw_data,
|
|
60
|
-
"parsed": parsed,
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@pytest.mark.preview
|
|
65
|
-
def test_preview_query_string_not_urlencoded_mimetype():
|
|
66
|
-
raw_data = "a=1&b=2&c=%7B%27er%27%3A+43434%7D"
|
|
67
|
-
body = generate_preview(raw_data, "test/plain", "")
|
|
68
|
-
|
|
69
|
-
assert body == {
|
|
70
|
-
"text": raw_data,
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@pytest.mark.preview
|
|
75
|
-
def test_preview_image():
|
|
76
|
-
body = generate_preview(None, "image/png", "")
|
|
77
|
-
|
|
78
|
-
assert body == {
|
|
79
|
-
"image": True,
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def test_preview_application_no_content_type_text():
|
|
84
|
-
body = generate_preview("just text", "", "")
|
|
85
|
-
|
|
86
|
-
assert body == {
|
|
87
|
-
"text": "just text",
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def test_preview_application_no_content_type_bytes():
|
|
92
|
-
body = generate_preview("just éà bytes".encode("utf-8"), "", "")
|
|
93
|
-
|
|
94
|
-
assert body == {
|
|
95
|
-
"text": "just éà bytes",
|
|
96
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/download-install-line-icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{httpdbg-0.13.2 → httpdbg-0.13.4}/httpdbg/webapp/static/icons/question-mark-round-line-icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|