Skip to content

Commit

Permalink
Log a warning when being ratelimtted by Github
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisLovering committed Dec 11, 2023
1 parent 04319c6 commit 44ae746
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 0 deletions.
16 changes: 16 additions & 0 deletions pydis_site/apps/api/tests/test_github_webhook_filter.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from unittest import mock
from urllib.error import HTTPError

from django.urls import reverse
from rest_framework.test import APITestCase

from pydis_site.apps.api.views import GitHubWebhookFilterView

class GitHubWebhookFilterAPITests(APITestCase):
def test_ignores_bot_sender(self):
Expand Down Expand Up @@ -44,3 +46,17 @@ def test_accepts_interesting_events(self):
response = self.client.post(url, data=payload, headers=headers)
self.assertEqual(response.status_code, context_mock.status)
self.assertEqual(response.headers.get('X-Clacks-Overhead'), 'Joe Armstrong')

def test_rate_limit_is_logged_to_sentry(self):
url = reverse('api:github-webhook-filter', args=('id', 'token'))
payload = {}
headers = {'X-GitHub-Event': 'pull_request_review'}
with (
mock.patch('urllib.request.urlopen') as urlopen,
mock.patch.object(GitHubWebhookFilterView, "logger") as logger,
):
urlopen.side_effect = HTTPError(None, 429, 'Too Many Requests', {}, None)
self.client.post(url, data=payload, headers=headers)

logger.warning = mock.PropertyMock()
logger.warning.assert_called_once()
9 changes: 9 additions & 0 deletions pydis_site/apps/api/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import json
import logging
import urllib.request
from collections.abc import Mapping
from http import HTTPStatus

from rest_framework import status
from rest_framework.exceptions import ParseError
Expand Down Expand Up @@ -254,6 +256,7 @@ class GitHubWebhookFilterView(APIView):

authentication_classes = ()
permission_classes = ()
logger = logging.getLogger("github_webhook_filter")

def post(self, request: Request, *, webhook_id: str, webhook_token: str) -> Response:
"""Filter a webhook POST from GitHub before sending it to Discord."""
Expand Down Expand Up @@ -329,4 +332,10 @@ def send_webhook(
with urllib.request.urlopen(request) as response: # noqa: S310
return (response.status, dict(response.getheaders()), response.read())
except urllib.error.HTTPError as err: # pragma: no cover
if err.code == HTTPStatus.TOO_MANY_REQUESTS:
self.logger.warning(
"We are being rate limited by Github! Scope: %s, reset-after: %d",
headers.get("X-RateLimit-Scope"),
headers.get("X-RateLimit-Reset-After"),
)
return (err.code, dict(err.headers), err.fp.read())

0 comments on commit 44ae746

Please sign in to comment.