File tree Expand file tree Collapse file tree 4 files changed +71
-1
lines changed
Expand file tree Collapse file tree 4 files changed +71
-1
lines changed Original file line number Diff line number Diff line change 1717import base64
1818import calendar
1919import datetime
20+ from email .message import Message
2021import sys
2122import urllib
2223
@@ -63,6 +64,28 @@ def decorator(method):
6364 return decorator
6465
6566
67+ def parse_content_type (header_value ):
68+ """Parse a 'content-type' header value to get just the plain media-type (without parameters).
69+
70+ This is done using the class Message from email.message as suggested in PEP 594
71+ (because the cgi is now deprecated and will be removed in python 3.13,
72+ see https://peps.python.org/pep-0594/#cgi).
73+
74+ Args:
75+ header_value (str): The value of a 'content-type' header as a string.
76+
77+ Returns:
78+ str: A string with just the lowercase media-type from the parsed 'content-type' header.
79+ If the provided content-type is not parsable, returns 'text/plain',
80+ the default value for textual files.
81+ """
82+ m = Message ()
83+ m ["content-type" ] = header_value
84+ return (
85+ m .get_content_type ()
86+ ) # Despite the name, actually returns just the media-type
87+
88+
6689def utcnow ():
6790 """Returns the current UTC datetime.
6891
Original file line number Diff line number Diff line change @@ -218,7 +218,10 @@ def get(
218218
219219 if response .status == http_client .OK :
220220 content = _helpers .from_bytes (response .data )
221- if response .headers ["content-type" ] == "application/json" :
221+ if (
222+ _helpers .parse_content_type (response .headers ["content-type" ])
223+ == "application/json"
224+ ):
222225 try :
223226 return json .loads (content )
224227 except ValueError as caught_exc :
Original file line number Diff line number Diff line change @@ -176,6 +176,24 @@ def test_get_success_json():
176176 assert result [key ] == value
177177
178178
179+ def test_get_success_json_content_type_charset ():
180+ key , value = "foo" , "bar"
181+
182+ data = json .dumps ({key : value })
183+ request = make_request (
184+ data , headers = {"content-type" : "application/json; charset=UTF-8" }
185+ )
186+
187+ result = _metadata .get (request , PATH )
188+
189+ request .assert_called_once_with (
190+ method = "GET" ,
191+ url = _metadata ._METADATA_ROOT + PATH ,
192+ headers = _metadata ._METADATA_HEADERS ,
193+ )
194+ assert result [key ] == value
195+
196+
179197def test_get_success_retry ():
180198 key , value = "foo" , "bar"
181199
Original file line number Diff line number Diff line change @@ -51,6 +51,32 @@ def func2(): # pragma: NO COVER
5151 _helpers .copy_docstring (SourceClass )(func2 )
5252
5353
54+ def test_parse_content_type_plain ():
55+ assert _helpers .parse_content_type ("text/html" ) == "text/html"
56+ assert _helpers .parse_content_type ("application/xml" ) == "application/xml"
57+ assert _helpers .parse_content_type ("application/json" ) == "application/json"
58+
59+
60+ def test_parse_content_type_with_parameters ():
61+ content_type_html = "text/html; charset=UTF-8"
62+ content_type_xml = "application/xml; charset=UTF-16; version=1.0"
63+ content_type_json = "application/json; charset=UTF-8; indent=2"
64+ assert _helpers .parse_content_type (content_type_html ) == "text/html"
65+ assert _helpers .parse_content_type (content_type_xml ) == "application/xml"
66+ assert _helpers .parse_content_type (content_type_json ) == "application/json"
67+
68+
69+ def test_parse_content_type_missing_or_broken ():
70+ content_type_foo = None
71+ content_type_bar = ""
72+ content_type_baz = "1234"
73+ content_type_qux = " ; charset=UTF-8"
74+ assert _helpers .parse_content_type (content_type_foo ) == "text/plain"
75+ assert _helpers .parse_content_type (content_type_bar ) == "text/plain"
76+ assert _helpers .parse_content_type (content_type_baz ) == "text/plain"
77+ assert _helpers .parse_content_type (content_type_qux ) == "text/plain"
78+
79+
5480def test_utcnow ():
5581 assert isinstance (_helpers .utcnow (), datetime .datetime )
5682
You can’t perform that action at this time.
0 commit comments