def parse_output(self, btext) -> Dict: # getting meta data and response body out of nghttp's output # is a bit tricky. Without '-v' we just get the body. With '-v' meta # data and timings in both directions are listed. # We rely on response :status: to be unique and on # response body not starting with space. # Something not good enough for general purpose, but for these tests.
output = {}
body = ''
streams = {}
skip_indents = True # chunk output into lines. nghttp mixes text # meta output with bytes from the response body.
lines = [l.decode() for l in btext.split(b'\n')]
for lidx, l in enumerate(lines): if len(l) == 0:
body += '\n' continue
m = re.match(r'(.*)\[.*] recv \(stream_id=(\d+)\) (\S+): (\S*)', l) if m:
body += m.group(1)
s = self.get_stream(streams, m.group(2))
hname = m.group(3)
hval = m.group(4)
print("stream %d header %s: %s" % (s["id"], hname, hval))
header = s["header"] if hname in header:
header[hname] += ", %s" % hval else:
header[hname] = hval continue
m = re.match(r'(.*)\[.*] recv HEADERS frame <.* stream_id=(\d+)>', l) if m:
body += m.group(1)
s = self.get_stream(streams, m.group(2)) if s:
print("stream %d: recv %d header" % (s["id"], len(s["header"])))
response = s["response"]
hkey = "header" if"header"in response:
h = response["header"] if":status"in h and int(h[":status"]) >= 200:
hkey = "trailer" else:
prev = { "header": h
} if"previous"in response:
prev["previous"] = response["previous"]
response["previous"] = prev
response[hkey] = s["header"]
s["header"] = {}
body = '' continue
m = re.match(r'(.*)\[.*] recv DATA frame ', l) if m:
body += m.group(1)
s = self.get_stream(streams, m.group(3))
blen = int(m.group(2)) if s:
print(f'stream {s["id"]}: {blen} DATA bytes added via "{l}"')
padlen = 0 if len(lines) > lidx + 2:
mpad = re.match(r' +\(padlen=(\d+)\)', lines[lidx+2]) if mpad:
padlen = int(mpad.group(1))
s["data_lengths"].append(blen)
s["paddings"].append(padlen)
blen -= padlen
s["response"]["body"] += body[-blen:].encode()
body = ''
skip_indents = True continue
m = re.match(r'(.*)\[.*] recv PUSH_PROMISE frame <.* stream_id=(\d+)>', l) if m:
body += m.group(1)
s = self.get_stream(streams, m.group(2)) if s: # headers we have are request headers for the PUSHed stream # these have been received on the originating stream, the promised # stream id it mentioned in the following lines
print("stream %d: %d PUSH_PROMISE header" % (s["id"], len(s["header"]))) if len(lines) > lidx+2:
m2 = re.match(r'\s+\(.*promised_stream_id=(\d+)\)', lines[lidx+2]) if m2:
s2 = self.get_stream(streams, m2.group(1))
s2["request"]["header"] = s["header"]
s["promises"].append(s2)
s["header"] = {} continue
m = re.match(r'(.*)\[.*] recv (\S+) frame ', l) if m:
print("recv frame %s on stream %s" % (m.group(2), m.group(4)))
body += m.group(1)
skip_indents = True continue
m = re.match(r'(.*)\[.*] send (\S+) frame ', l) if m:
print("send frame %s on stream %s" % (m.group(2), m.group(4)))
body += m.group(1)
skip_indents = True continue
if skip_indents and l.startswith(' '): continue
if'[' != l[0]:
skip_indents = None
body += l + '\n'
# the main request is done on the lowest odd numbered id
main_stream = 99999999999 for sid in streams:
s = streams[sid] if"header"in s["response"] and":status"in s["response"]["header"]:
s["response"]["status"] = int(s["response"]["header"][":status"]) if (sid % 2) == 1 and sid < main_stream:
main_stream = sid
output["streams"] = streams if main_stream in streams:
output["response"] = streams[main_stream]["response"]
output["paddings"] = streams[main_stream]["paddings"]
output["data_lengths"] = streams[main_stream]["data_lengths"] return output
def _raw(self, url, timeout, options):
args = ["-v"] if self._test_name isnotNone:
args.append(f'--header=AP-Test-Name: {self._test_name}') if options:
args.extend(options)
r = self._baserun(url, timeout, args) if 0 == r.exit_code:
r.add_results(self.parse_output(r.outraw)) return r
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.