Repository: hikari-py/hikari
Pull request #963 (2022-01-11 09:45:09)

Fix handling of utf-8 audit log reasons
### Summary
Fix handling of utf-8 audit log reasons

### Checklist
<!-- Make sure to tick all the following boxes by putting an `x` in between (like this `[x]`) -->
- [ ] I have run `nox` and all the pipelines have passed.
- [ ] I have made unittests according to the code I have added/modified/deleted.

### Related issues
<!--
To mention an issue use `#issue-id` and to mention a merge request use `!merge-request-id`
To close/fix an issue use `Close #issue-id` or `Fix #issue-id` (depending on the merge request)
-->



Patch:
diff --git a/changes/963.bugfix.md b/changes/963.bugfix.md
new file mode 100644
index 00000000..a5060cf2
--- /dev/null
+++ b/changes/963.bugfix.md
@@ -0,0 +1,1 @@
+UTF-8 characters are now properly handled for audit-log reasons in REST requests.
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 777ccc56..9f9ddae4 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -9,7 +9,7 @@ mock==4.0.3
 pytest==6.2.5
 pytest-asyncio==0.16.0
 pytest-cov==3.0.0
-pytest-randomly==3.10.3
+pytest-randomly==3.11.0
 
 # Coverage testing.
 coverage[toml]==6.2
diff --git a/flake8-requirements.txt b/flake8-requirements.txt
index 0a252ae5..8afc4343 100644
--- a/flake8-requirements.txt
+++ b/flake8-requirements.txt
@@ -8,7 +8,7 @@ flake8-black==0.2.3                     # runs black
 flake8-broken-line==0.4.0               # forbey "\" linebreaks
 flake8-builtins==1.5.3                  # builtin shadowing checks
 flake8-coding==1.3.2                    # coding magic-comment detection
-flake8-comprehensions==3.7.0            # comprehension checks
+flake8-comprehensions==3.8.0            # comprehension checks
 flake8-deprecated==1.3                  # deprecated call checks
 flake8-docstrings==1.6.0                # pydocstyle support
 flake8-executable==2.1.1                # shebangs
diff --git a/hikari/impl/rest.py b/hikari/impl/rest.py
index 1e3f0d00..65b94b71 100644
--- a/hikari/impl/rest.py
+++ b/hikari/impl/rest.py
@@ -42,6 +42,7 @@
 import platform
 import sys
 import typing
+import urllib.parse
 
 import aiohttp
 import attr
@@ -706,7 +707,8 @@ async def _request(
                 token = await self._token.acquire(self)
                 headers[_AUTHORIZATION_HEADER] = token
 
-        headers.put(_X_AUDIT_LOG_REASON_HEADER, reason)
+        # As per the docs, UTF-8 characters are only supported here if it's url-encoded.
+        headers.put(_X_AUDIT_LOG_REASON_HEADER, reason, conversion=urllib.parse.quote)
 
         url = compiled_route.create_url(self._rest_url)
 


Test patch:
diff --git a/tests/hikari/impl/test_rest.py b/tests/hikari/impl/test_rest.py
index 106671c8..ad883b04 100644
--- a/tests/hikari/impl/test_rest.py
+++ b/tests/hikari/impl/test_rest.py
@@ -1084,6 +1084,22 @@ async def test__request_builds_form_when_passed(self, rest_client, exit_exceptio
         assert kwargs["data"] is mock_form.build.return_value
         assert live_attributes.still_alive.call_count == 3
 
+    @hikari_test_helpers.timeout()
+    async def test__request_url_encodes_reason_header(self, rest_client, exit_exception, live_attributes):
+        route = routes.Route("GET", "/something/{channel}/somewhere").compile(channel=123)
+        mock_session = mock.AsyncMock(request=mock.AsyncMock(side_effect=exit_exception))
+        live_attributes.buckets.is_started = True
+        live_attributes.client_session = mock_session
+
+        with pytest.raises(exit_exception):
+            await rest_client._request(route, reason="光のenergyが　大地に降りそそぐ")
+
+        _, kwargs = mock_session.request.call_args_list[0]
+        assert kwargs["headers"][rest._X_AUDIT_LOG_REASON_HEADER] == (
+            "%E5%85%89%E3%81%AEenergy%E3%81%8C%E3%80%80%E5%A4%"
+            "A7%E5%9C%B0%E3%81%AB%E9%99%8D%E3%82%8A%E3%81%9D%E3%81%9D%E3%81%90"
+        )
+
     @hikari_test_helpers.timeout()
     async def test__request_with_strategy_token(self, rest_client, exit_exception, live_attributes):
         route = routes.Route("GET", "/something/{channel}/somewhere").compile(channel=123)