Skip to content

Commit 622df26

Browse files
committed
added option to write response content to separate files outside log files.
1 parent 32c8258 commit 622df26

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

doc/howto.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ Synopsis::
261261
-h, --help show this help message and exit
262262
-H, --prettyprint Status output as human readable python dictionary
263263
-J TT_CONFIG_FILE Test target configuration in JSON format
264-
-L, --log Print HTTP log information # TODO: update documentation
264+
-k Print HTTP response contents into separate files
265+
-L, --log Path to the logfile directory
265266
-l, --list List all the test flows as a JSON object
266267
-m, --metadata Return the SP metadata
267268
-O, --operations Operations module (generated from Repository as idp_saml2base.py)

src/sp_test/__init__.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import json
22
import pprint
33
import argparse
4+
import os.path
45
import sys
6+
import traceback
57
from importlib import import_module
68

79
from idp_test import SCHEMA
@@ -63,11 +65,19 @@ def __init__(self, operations, check_factory):
6365
"printed python dict instead of JSON")
6466
self._parser.add_argument("-i", dest="insecure", action='store_true',
6567
help="Do not verify SSL certificate")
68+
self._parser.add_argument("-I", dest="keysdir", default="keys",
69+
help="Directory for invalid IDP keys")
6670
self._parser.add_argument('-J', dest="json_config_file",
67-
help="Script configuration")
71+
help="Test target configuration")
72+
self._parser.add_argument(
73+
'-k', dest='content_log', action='store_true',
74+
help="Log HTTP content in spearate files in directory "
75+
"<operation>/, which defaults to the path in -L")
6876
self._parser.add_argument(
6977
"-l", dest="list", action="store_true",
7078
help="List all the test flows as a JSON object")
79+
self._parser.add_argument("-L", dest="logpath", default=".",
80+
help="Path to the logfile directory")
7181
self._parser.add_argument('-m', dest="metadata", action='store_true',
7282
help="Return the IdP metadata")
7383
self._parser.add_argument(
@@ -184,7 +194,8 @@ def run(self):
184194
self.interactions, self.json_config,
185195
check_factory=self.check_factory,
186196
entity_id=self.entity_id,
187-
constraints=self.constraints)
197+
constraints=self.constraints,
198+
commandlineargs = self.args)
188199
try:
189200
conv.do_sequence_and_tests(oper["sequence"], oper["tests"])
190201
self.test_log = conv.test_output

src/sp_test/base.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import base64
22
import cookielib
33
import re
4+
import os
45
import traceback
56
import urllib
67
import sys
@@ -10,6 +11,7 @@
1011
from saml2 import BINDING_HTTP_POST
1112
from saml2.request import SERVICE2REQUEST
1213
from saml2.sigver import signed_instance_factory, pre_signature_part
14+
from saml2.samlp import HttpParameters
1315

1416
from saml2test import CheckError, FatalError
1517
from saml2test.check import Check
@@ -31,6 +33,9 @@
3133

3234
logger = logging.getLogger(__name__)
3335

36+
FILE_EXT = {"text/html": "html", "test/plain": "txt", "application/json": "json",
37+
"text/xml": "xml", "application/xml": "xml", }
38+
3439
camel2underscore = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))')
3540

3641

@@ -47,6 +52,7 @@ def __init__(self, instance, config, interaction, json_config,
4752
self.check_factory = check_factory
4853
self.msg_factory = msg_factory
4954
self.expect_exception = expect_exception
55+
self.commandlineargs = commandlineargs
5056

5157
self.cjar = {"browser": cookielib.CookieJar(),
5258
"rp": cookielib.CookieJar(),
@@ -144,8 +150,46 @@ def which_endpoint(self, url):
144150
return None
145151

146152
def _log_response(self, response):
153+
"""Depending on -k argument write content to either logger or extra file
154+
155+
Create the <operation> directory; delete all possibly existing files
156+
Write response content into response_x.<ext> (with x incrementing from 0)
157+
"""
147158
logger.info("<-- Status: %s" % response.status_code)
148-
logger.info("<-- Content: %s" % response.content)
159+
if response.status_code in [302, 301, 303]:
160+
logger.info("<-- location: %s" %
161+
response.headers._store['location'][1])
162+
else:
163+
if self.commandlineargs.content_log:
164+
self._content_log_fileno = getattr(self, '_content_log_fileno', 0) + 1
165+
if not getattr(self, 'logcontentpath', None):
166+
try:
167+
content_type_hdr = response.headers._store['content-type'][1]
168+
l = content_type_hdr.split(';') + ['charset=ISO-8859-1',]
169+
content_type = l[0]
170+
encoding = l[1].split("=")
171+
ext = "." + FILE_EXT[content_type]
172+
except Exception as e:
173+
ext = ""
174+
self._logcontentpath = os.path.join(
175+
self.commandlineargs.logpath, "log",
176+
self.commandlineargs.oper)
177+
if not os.path.exists(self._logcontentpath):
178+
os.makedirs(self._logcontentpath)
179+
for fn in os.listdir(self._logcontentpath):
180+
old_file = os.path.join(self._logcontentpath, fn)
181+
if os.path.isfile(old_file):
182+
os.unlink(old_file)
183+
fn = os.path.join(self._logcontentpath, "response_%d%s"
184+
% (self._content_log_fileno, ext ))
185+
f = open(fn, "w")
186+
f.write(response.content)
187+
f.close()
188+
logger.info("<-- Response content (encoding=%s) in file %s" %
189+
(encoding, fn))
190+
pass
191+
else:
192+
logger.info("<-- Content: %s" % response.content)
149193

150194
def wb_send_GET_startpage(self):
151195
"""
@@ -193,6 +237,8 @@ def parse_saml_message(self):
193237
self.saml_request = self.instance._parse_request(
194238
_str, SERVICE2REQUEST[self._endpoint], self._endpoint,
195239
self._binding)
240+
if self._binding == BINDING_HTTP_REDIRECT:
241+
self.http_parameters = HttpParameters(_dict)
196242

197243
def _redirect(self, _response):
198244
rdseq = []
@@ -363,7 +409,7 @@ def do_sequence_and_tests(self, oper, tests=None):
363409
self.do_flow(flow)
364410
except InteractionNeeded:
365411
self.test_output.append({"status": INTERACTION,
366-
"message": self.last_content,
412+
"message": "see detail log for response content",
367413
"id": "exception",
368414
"name": "interaction needed",
369415
"url": self.position})

0 commit comments

Comments
 (0)