Skip to content

Commit 4bfdaf1

Browse files
authored
Merge pull request #1543 from mohamedsolaiman/feature/verbose-output
Add --verbose/-v flag with response time and content type output
2 parents 20b4247 + 1b975eb commit 4bfdaf1

14 files changed

Lines changed: 166 additions & 14 deletions

File tree

config.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ quiet-mode = False
7474
color = True
7575
show-redirects-history = False
7676
disable-cli = False
77+
verbose = False
7778

7879
[output]
7980
# Available: simple, plain, json, xml, md, csv, html, sqlite

lib/connection/requester.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ def request(self, path: str, proxy: str | None = None) -> Response:
208208
prep = self.session.prepare_request(request)
209209
prep.url = url
210210

211+
start_time = time.perf_counter()
211212
origin_response = self.session.send(
212213
prep,
213214
allow_redirects=options["follow_redirects"],
@@ -216,6 +217,7 @@ def request(self, path: str, proxy: str | None = None) -> Response:
216217
stream=True,
217218
)
218219
response = Response(url, origin_response)
220+
response.elapsed = time.perf_counter() - start_time
219221

220222
log_msg = f'"{options["http_method"]} {response.url}" {response.status} - {response.length}B'
221223

@@ -382,13 +384,17 @@ async def request(
382384
extensions={"target": (url if replay else f"/{safequote(path)}").encode()},
383385
)
384386

387+
start_time = time.perf_counter()
385388
xresponse = await session.send(
386389
request,
387390
stream=True,
388391
follow_redirects=options["follow_redirects"],
389392
)
390393
response = await AsyncResponse.create(url, xresponse)
391394
await xresponse.aclose()
395+
# Measure the whole streamed request lifecycle so sync and async
396+
# modes report the same thing.
397+
response.elapsed = time.perf_counter() - start_time
392398

393399
log_msg = f'"{options["http_method"]} {response.url}" {response.status} - {response.length}B'
394400

lib/connection/response.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636

3737
class BaseResponse:
38-
def __init__(self, url, response: requests.Response | httpx.Response) -> None:
38+
def __init__(self, url, response: requests.Response | httpx.Response, elapsed: float = 0.0) -> None:
3939
self.datetime = time.strftime("%Y-%m-%d %H:%M:%S")
4040
self.url = url
4141
self.full_path = parse_path(self.url)
@@ -44,6 +44,7 @@ def __init__(self, url, response: requests.Response | httpx.Response) -> None:
4444
self.headers = response.headers
4545
self.redirect = self.headers.get("location", "")
4646
self.history = [str(res.url) for res in response.history]
47+
self.elapsed = elapsed
4748
self.content = ""
4849
self.body = b""
4950

@@ -80,8 +81,8 @@ def __eq__(self, other: Any) -> bool:
8081

8182

8283
class Response(BaseResponse):
83-
def __init__(self, url, response: requests.Response) -> None:
84-
super().__init__(url, response)
84+
def __init__(self, url, response: requests.Response, elapsed: float = 0.0) -> None:
85+
super().__init__(url, response, elapsed)
8586

8687
for chunk in response.iter_content(chunk_size=ITER_CHUNK_SIZE):
8788
self.body += chunk
@@ -102,8 +103,8 @@ def __init__(self, url, response: requests.Response) -> None:
102103

103104
class AsyncResponse(BaseResponse):
104105
@classmethod
105-
async def create(cls, url, response: httpx.Response) -> AsyncResponse:
106-
self = cls(url, response)
106+
async def create(cls, url, response: httpx.Response, elapsed: float = 0.0) -> AsyncResponse:
107+
self = cls(url, response, elapsed)
107108
async for chunk in response.aiter_bytes(chunk_size=ITER_CHUNK_SIZE):
108109
self.body += chunk
109110

lib/core/data.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
"color": True,
9999
"quiet": False,
100100
"disable_cli": False,
101+
"verbose": False,
101102
"output_file": None,
102103
"output_table": None,
103104
"output_formats": None,

lib/core/options.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ def merge_config(opt: Values) -> Values:
545545
opt.color = opt.color if opt.color is False else config.safe_getboolean("view", "color", True)
546546
opt.quiet = opt.quiet or config.safe_getboolean("view", "quiet-mode")
547547
opt.disable_cli = opt.disable_cli or config.safe_getboolean("view", "disable-cli")
548+
opt.verbose = opt.verbose or config.safe_getboolean("view", "verbose")
548549
opt.redirects_history = opt.redirects_history or config.safe_getboolean(
549550
"view", "show-redirects-history"
550551
)

lib/parse/cmdline.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,13 @@ def parse_arguments() -> Values:
539539
view.add_option(
540540
"--disable-cli", action="store_true", dest="disable_cli", help="Turn off command-line output"
541541
)
542+
view.add_option(
543+
"-v",
544+
"--verbose",
545+
action="store_true",
546+
dest="verbose",
547+
help="Show verbose output with response time and content type",
548+
)
542549

543550
# Output Settings
544551
output = OptionGroup(parser, "Output Settings")

lib/report/csv_report.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class CSVReport(FileReportMixin, BaseReport):
2727
__extension__ = "csv"
2828

2929
def new(self):
30-
return [["URL", "Status", "Size", "Content Type", "Redirection"]]
30+
return [["URL", "Status", "Size", "Content Type", "Redirection", "Elapsed (s)"]]
3131

3232
def parse(self, file):
3333
with open(file) as fh:
@@ -41,7 +41,8 @@ def parse(self, file):
4141
@locked
4242
def save(self, file, result):
4343
rows = self.parse(file)
44-
rows.append([result.url, result.status, result.length, result.type, result.redirect])
44+
elapsed = round(result.elapsed, 3) if result.elapsed else ""
45+
rows.append([result.url, result.status, result.length, result.type, result.redirect, elapsed])
4546
self.write(file, rows)
4647

4748
def write(self, file, rows):

lib/report/html_report.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ def parse(self, file):
4444
@locked
4545
def save(self, file, result):
4646
results = self.parse(file)
47-
results.append({
47+
entry = {
4848
"url": result.url,
4949
"status": result.status,
5050
"contentLength": result.length,
5151
"contentType": result.type,
5252
"redirect": result.redirect,
53-
})
53+
}
54+
if result.elapsed:
55+
entry["elapsed"] = round(result.elapsed, 3)
56+
results.append(entry)
5457
self.write(file, self.generate(results))
5558

5659
def generate(self, results):

lib/report/json_report.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,16 @@ def parse(self, file):
4040
@locked
4141
def save(self, file, result):
4242
data = self.parse(file)
43-
data["results"].append({
43+
entry = {
4444
"url": result.url,
4545
"status": result.status,
4646
"contentLength": result.length,
4747
"contentType": result.type,
4848
"redirect": result.redirect,
49-
})
49+
}
50+
if result.elapsed:
51+
entry["elapsed"] = round(result.elapsed, 3)
52+
data["results"].append(entry)
5053
self.write(file, data)
5154

5255
def write(self, file, data):

lib/report/markdown_report.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ def new(self):
3535
header += NEW_LINE
3636
header += f"Time: {START_TIME}"
3737
header += NEW_LINE * 2
38-
header += "URL | Status | Size | Content Type | Redirection" + NEW_LINE
39-
header += "----|--------|------|--------------|------------" + NEW_LINE
38+
header += "URL | Status | Size | Content Type | Redirection | Elapsed (ms)" + NEW_LINE
39+
header += "----|--------|------|--------------|-------------|-------------" + NEW_LINE
4040
return header
4141

4242
@locked
4343
def save(self, file, result):
4444
md = self.parse(file)
45-
md += f"{result.url} | {result.status} | {result.length} | {result.type} | {result.redirect}" + NEW_LINE
45+
elapsed_ms = int(result.elapsed * 1000) if result.elapsed else "-"
46+
md += f"{result.url} | {result.status} | {result.length} | {result.type} | {result.redirect} | {elapsed_ms}" + NEW_LINE
4647
self.write(file, md)

0 commit comments

Comments
 (0)