Recently, I was writing a test platform for interface automation. I encountered a small problem in the step of backfilling the response header data in the request interface. I want to get the response header method (r.headers) that comes with the requests library, and then pass the value after getting the value. To display to the front end, the display effect is as follows:
Everything was fine when I started debugging, but in order to keep a record of this data something went wrong and an uncommon error was reported:
The first reaction is a problem related to django serialization. According to the error log, it can be traced back to the error in the step of creating data storage in batches through ORM in the code. After analyzing it, there is still no clue:
After hitting the breakpoint, adding comments and debugging, I found no results, and there is no doubt that the problem is caused by the addition of the operation of getting the response header. Later, I have no clue to comment this part of the code, and no error will be reported, and it can run normally!
Then after some debugging, it was found that the response header returned by requests is: <class 'requests.structures.CaseInsensitiveDict'>
this type, which is a custom data structure of requests, a data structure with case-insensitive pure string keys, and it also contains some byte data, so in the sequence It will report an error when it is a json string:
class CaseInsensitiveDict(MutableMapping):
"""A case-insensitive ``dict``-like object.
Implements all methods and operations of
``MutableMapping`` as well as dict's ``copy``. Also
provides ``lower_items``.
All keys are expected to be strings. The structure remembers the
case of the last key to be set, and ``iter(instance)``,
``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()``
will contain case-sensitive keys. However, querying and contains
testing is case insensitive::
cid = CaseInsensitiveDict()
cid['Accept'] = 'application/json'
cid['aCCEPT'] == 'application/json' # True
list(cid) == ['Accept'] # True
For example, ``headers['content-encoding']`` will return the
value of a ``'Content-Encoding'`` response header, regardless
of how the header name was originally stored.
If the constructor, ``.update``, or equality comparison
operations are given keys that have equal ``.lower()``s, the
behavior is undefined.
"""
def __init__(self, data=None, **kwargs):
self._store = OrderedDict()
if data is None:
data = {
}
self.update(data, **kwargs)
def __setitem__(self, key, value):
# Use the lowercased key for lookups, but store the actual
# key alongside the value.
self._store[key.lower()] = (key, value)
def __getitem__(self, key):
return self._store[key.lower()][1]
def __delitem__(self, key):
del self._store[key.lower()]
def __iter__(self):
return (casedkey for casedkey, mappedvalue in self._store.values())
def __len__(self):
return len(self._store)
def lower_items(self):
"""Like iteritems(), but with all lowercase keys."""
return (
(lowerkey, keyval[1])
for (lowerkey, keyval)
in self._store.items()
)
def __eq__(self, other):
if isinstance(other, Mapping):
other = CaseInsensitiveDict(other)
else:
return NotImplemented
# Compare insensitively
return dict(self.lower_items()) == dict(other.lower_items())
# Copy is required
def copy(self):
return CaseInsensitiveDict(self._store.values())
def __repr__(self):
return str(dict(self.items()))
So here I directly convert it to dict type to solve the problem:
原:req_log['res_headers'] = r.headers
改:req_log['res_headers'] = dict(r.headers)
I also didn't spend more time researching the function of this data structure, and here is mainly to make a note to remind myself.