diff --git a/requests/exceptions.py b/requests/exceptions.py index 0e9c820c..c412ec98 100644 --- a/requests/exceptions.py +++ b/requests/exceptions.py @@ -25,6 +25,10 @@ class RequestException(IOError): super(RequestException, self).__init__(*args, **kwargs) +class InvalidJSONError(RequestException): + """A JSON error occurred.""" + + class HTTPError(RequestException): """An HTTP error occurred.""" diff --git a/requests/models.py b/requests/models.py index 34b672c2..93b901b4 100644 --- a/requests/models.py +++ b/requests/models.py @@ -29,7 +29,7 @@ from .auth import HTTPBasicAuth from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar from .exceptions import ( HTTPError, MissingSchema, InvalidURL, ChunkedEncodingError, - ContentDecodingError, ConnectionError, StreamConsumedError) + ContentDecodingError, ConnectionError, StreamConsumedError, InvalidJSONError) from ._internal_utils import to_native_string, unicode_is_ascii from .utils import ( guess_filename, get_auth_from_url, requote_uri, @@ -466,7 +466,12 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): # urllib3 requires a bytes-like body. Python 2's json.dumps # provides this natively, but Python 3 gives a Unicode string. content_type = 'application/json' - body = complexjson.dumps(json) + + try: + body = complexjson.dumps(json, allow_nan=False) + except ValueError as ve: + raise InvalidJSONError(ve, request=self) + if not isinstance(body, bytes): body = body.encode('utf-8') diff --git a/tests/test_requests.py b/tests/test_requests.py index 223c36e3..8f3914ee 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -24,7 +24,7 @@ from requests.cookies import ( from requests.exceptions import ( ConnectionError, ConnectTimeout, InvalidSchema, InvalidURL, MissingSchema, ReadTimeout, Timeout, RetryError, TooManyRedirects, - ProxyError, InvalidHeader, UnrewindableBodyError, SSLError, InvalidProxyURL) + ProxyError, InvalidHeader, UnrewindableBodyError, SSLError, InvalidProxyURL, InvalidJSONError) from requests.models import PreparedRequest from requests.structures import CaseInsensitiveDict from requests.sessions import SessionRedirectMixin @@ -2566,3 +2566,8 @@ class TestPreparingURLs(object): r = requests.Request('GET', url=input, params=params) p = r.prepare() assert p.url == expected + + def test_post_json_nan(self, httpbin): + data = {"foo": float("nan")} + with pytest.raises(requests.exceptions.InvalidJSONError): + r = requests.post(httpbin('post'), json=data) \ No newline at end of file