diff --git a/gidgethub/abc.py b/gidgethub/abc.py index dd7a764..3923704 100644 --- a/gidgethub/abc.py +++ b/gidgethub/abc.py @@ -19,7 +19,9 @@ # Value represents etag, last-modified, data, and next page. CACHE_TYPE = MutableMapping[str, Tuple[Opt[str], Opt[str], Any, Opt[str]]] -_json_content_type = "application/json; charset=utf-8" +JSON_CONTENT_TYPE = "application/json" +UTF_8_CHARSET = "utf-8" +JSON_UTF_8_CHARSET = f"{JSON_CONTENT_TYPE}; charset={UTF_8_CHARSET}" class GitHubAPI(abc.ABC): @@ -59,7 +61,7 @@ async def _make_request( accept: str, jwt: Opt[str] = None, oauth_token: Opt[str] = None, - content_type: Opt[str] = None, + content_type: str = JSON_CONTENT_TYPE, ) -> Tuple[bytes, Opt[str]]: """Construct and make an HTTP request.""" if oauth_token is not None and jwt is not None: @@ -96,15 +98,14 @@ async def _make_request( if last_modified is not None: request_headers["if-modified-since"] = last_modified else: - if content_type != "application/json": - # We don't know how to handle other content types, so just pass things along. + if content_type != JSON_CONTENT_TYPE: + # We don't know how to handle other content types, so just pass things along. request_headers["content-type"] = content_type body = data else: # Since JSON is so common, add some niceties. - charset = "utf-8" - body = json.dumps(data).encode(charset) - request_headers["content-type"] = f"application/json; charset={charset}" + body = json.dumps(data).encode(UTF_8_CHARSET) + request_headers["content-type"] = JSON_UTF_8_CHARSET request_headers["content-length"] = str(len(body)) if self.rate_limit is not None: self.rate_limit.remaining -= 1 @@ -169,7 +170,7 @@ async def post( accept: str = sansio.accept_format(), jwt: Opt[str] = None, oauth_token: Opt[str] = None, - content_type: Opt[str] = None, + content_type: str = JSON_CONTENT_TYPE, ) -> Any: data, _ = await self._make_request( "POST", @@ -244,11 +245,11 @@ async def graphql( payload["variables"] = variables request_data = json.dumps(payload).encode("utf-8") request_headers = sansio.create_headers( - self.requester, accept=_json_content_type, oauth_token=self.oauth_token + self.requester, accept=JSON_UTF_8_CHARSET, oauth_token=self.oauth_token ) request_headers.update( { - "content-type": _json_content_type, + "content-type": JSON_UTF_8_CHARSET, "content-length": str(len(request_data)), } ) diff --git a/tests/test_abc.py b/tests/test_abc.py index f70e9fd..bd4a0ba 100644 --- a/tests/test_abc.py +++ b/tests/test_abc.py @@ -22,6 +22,8 @@ from .samples import GraphQL as graphql_samples +from gidgethub.abc import JSON_UTF_8_CHARSET + class MockGitHubAPI(gh_abc.GitHubAPI): @@ -29,7 +31,7 @@ class MockGitHubAPI(gh_abc.GitHubAPI): "x-ratelimit-limit": "2", "x-ratelimit-remaining": "1", "x-ratelimit-reset": "0", - "content-type": "application/json; charset=utf-8", + "content-type": JSON_UTF_8_CHARSET, } def __init__( @@ -343,42 +345,41 @@ async def test_post(self): send_json = json.dumps(send).encode("utf-8") receive = {"hello": "world"} headers = MockGitHubAPI.DEFAULT_HEADERS.copy() - headers["content-type"] = "application/json; charset=utf-8" gh = MockGitHubAPI(headers=headers, body=json.dumps(receive).encode("utf-8")) await gh.post("/fake", data=send) assert gh.method == "POST" assert gh.headers["content-type"] == "application/json; charset=utf-8" assert gh.body == send_json assert gh.headers["content-length"] == str(len(send_json)) + assert gh.headers["content-type"] == JSON_UTF_8_CHARSET @pytest.mark.asyncio async def test_with_passed_jwt(self): send = [1, 2, 3] receive = {"hello": "world"} headers = MockGitHubAPI.DEFAULT_HEADERS.copy() - headers["content-type"] = "application/json; charset=utf-8" gh = MockGitHubAPI(headers=headers, body=json.dumps(receive).encode("utf-8")) await gh.post("/fake", data=send, jwt="json web token") assert gh.method == "POST" assert gh.headers["authorization"] == "bearer json web token" + assert gh.headers["content-type"] == JSON_UTF_8_CHARSET @pytest.mark.asyncio async def test_with_passed_oauth_token(self): send = [1, 2, 3] receive = {"hello": "world"} headers = MockGitHubAPI.DEFAULT_HEADERS.copy() - headers["content-type"] = "application/json; charset=utf-8" gh = MockGitHubAPI(headers=headers, body=json.dumps(receive).encode("utf-8")) await gh.post("/fake", data=send, oauth_token="my oauth token") assert gh.method == "POST" assert gh.headers["authorization"] == "token my oauth token" + assert gh.headers["content-type"] == JSON_UTF_8_CHARSET @pytest.mark.asyncio async def test_cannot_pass_both_oauth_and_jwt(self): send = [1, 2, 3] receive = {"hello": "world"} headers = MockGitHubAPI.DEFAULT_HEADERS.copy() - headers["content-type"] = "application/json; charset=utf-8" gh = MockGitHubAPI(headers=headers, body=json.dumps(receive).encode("utf-8")) with pytest.raises(ValueError) as exc_info: await gh.post(