Skip to content

application/x-www-form-urlencoded request with None body #913

Open
@ericbn

Description

@ericbn

Double checking the exiting transformers defined in vcr.matchers, we see:

>>> from vcr.matchers import _checker_transformer_pairs
>>> for i, (_, transformer) in enumerate(_checker_transformer_pairs):
...     print(i)
...     try:
...             print(transformer(None))
...     except Exception as e:
...             print(e)
...
0
None
1
'NoneType' object has no attribute 'decode'
2
None
3
a bytes-like object is required, not 'NoneType'
  1. Transfer-Encoding: chunked accepts None
  2. Content-Type: application/x-www-form-urlencoded does not accept None
  3. Content-Type: application/json accepts None
  4. Content-Type: text/xml; User-Agent: xmlrpc does not accept None

I'm particularly interested in letting the Content-Type: application/x-www-form-urlencoded transformer accept None.

The twilio package does arguably unusual requests in some cases: GET with header Content-Type: application/x-www-form-urlencoded. In these cases, the body is None. See

https://github.com/twilio/twilio-python/blob/71fb731c9c6356cf08030221d74a900c935109da/twilio/rest/sync/v1/service/sync_map/sync_map_item.py#L734-L740

When trying to record these requests with vcr, it fails with 'NoneType' object has no attribute 'decode'.

If I change matchers.py as follows:

 _checker_transformer_pairs = (
     (_header_checker("chunked", header="Transfer-Encoding"), _dechunk),
     (
         _header_checker("application/x-www-form-urlencoded"),
-        lambda body: urllib.parse.parse_qs(body.decode("ascii")),
+        lambda body: None if body is None else urllib.parse.parse_qs(body.decode("ascii")),
     ),
     (_header_checker("application/json"), _transform_json),
     (lambda request: _xml_header_checker(request) and _xmlrpc_header_checker(request), xmlrpc.client.loads),
 )

then I can successfully record an interaction. For the twilio package code mentioned above, a recorded interaction will then look like:

- request:
    body: null
    headers:
      Content-Type:
      - application/x-www-form-urlencoded
    method: GET
    uri: https://sync.twilio.com/v1/Services/default/Maps/MyMap/Items?PageSize=1000
  response:
    body:
      string: '{...}'
    headers:
      Content-Type:
      - application/json; charset=utf-8
    status:
      code: 200
      message: OK

Do you agree with the proposed change? I'll be happy to submit a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions