mirror of
https://github.com/zulip/zulip.git
synced 2026-07-06 21:18:58 +08:00
outgoing_http: Factor out outgoing HTTP session with timeout.
This commit is contained in:
parent
2dc6df33ae
commit
b88d7a741e
25
zerver/lib/outgoing_http.py
Normal file
25
zerver/lib/outgoing_http.py
Normal file
@ -0,0 +1,25 @@
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import requests
|
||||
from urllib3 import HTTPResponse
|
||||
|
||||
|
||||
class OutgoingSession(requests.Session):
|
||||
def __init__(self, timeout: int, headers: Optional[Dict[str, str]] = None) -> None:
|
||||
super().__init__()
|
||||
outgoing_adapter = OutgoingHTTPAdapter(timeout=timeout)
|
||||
self.mount("http://", outgoing_adapter)
|
||||
self.mount("https://", outgoing_adapter)
|
||||
|
||||
|
||||
class OutgoingHTTPAdapter(requests.adapters.HTTPAdapter):
|
||||
timeout: int
|
||||
|
||||
def __init__(self, timeout: int, *args: Any, **kwargs: Any) -> None:
|
||||
self.timeout = timeout
|
||||
super().__init__(*args, *kwargs)
|
||||
|
||||
def send(self, *args: Any, **kwargs: Any) -> HTTPResponse:
|
||||
if kwargs.get("timeout") is None:
|
||||
kwargs["timeout"] = self.timeout
|
||||
return super().send(*args, **kwargs)
|
||||
@ -7,13 +7,13 @@ from typing import Any, AnyStr, Dict, Optional
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
from requests import Response, Session
|
||||
from urllib3 import HTTPResponse
|
||||
from requests import Response
|
||||
|
||||
from version import ZULIP_VERSION
|
||||
from zerver.decorator import JsonableError
|
||||
from zerver.lib.actions import check_send_message
|
||||
from zerver.lib.message import MessageDict
|
||||
from zerver.lib.outgoing_http import OutgoingSession
|
||||
from zerver.lib.queue import retry_event
|
||||
from zerver.lib.topic import get_topic_from_message_info
|
||||
from zerver.lib.url_encoding import near_message_url
|
||||
@ -28,26 +28,14 @@ from zerver.models import (
|
||||
)
|
||||
|
||||
|
||||
class TimeoutAdapter(requests.adapters.HTTPAdapter):
|
||||
def __init__(self, timeout: Optional[int] = None, *args: Any, **kwargs: Any) -> None:
|
||||
self.timeout = timeout
|
||||
super().__init__(*args, *kwargs)
|
||||
|
||||
def send(self, *args: Any, **kwargs: Any) -> HTTPResponse:
|
||||
if kwargs.get("timeout") is None:
|
||||
kwargs["timeout"] = self.timeout
|
||||
return super().send(*args, **kwargs)
|
||||
|
||||
|
||||
class OutgoingWebhookServiceInterface(metaclass=abc.ABCMeta):
|
||||
def __init__(self, token: str, user_profile: UserProfile, service_name: str) -> None:
|
||||
self.token: str = token
|
||||
self.user_profile: UserProfile = user_profile
|
||||
self.service_name: str = service_name
|
||||
self.session: Session = Session()
|
||||
timeout_adapter = TimeoutAdapter(timeout=settings.OUTGOING_WEBHOOK_TIMEOUT_SECONDS)
|
||||
self.session.mount("http://", timeout_adapter)
|
||||
self.session.mount("https://", timeout_adapter)
|
||||
self.session: requests.Session = OutgoingSession(
|
||||
timeout=10,
|
||||
)
|
||||
self.session.headers.update(
|
||||
{
|
||||
"X-Smokescreen-Role": "webhook",
|
||||
|
||||
38
zerver/tests/test_outgoing_http.py
Normal file
38
zerver/tests/test_outgoing_http.py
Normal file
@ -0,0 +1,38 @@
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
import responses
|
||||
|
||||
from zerver.lib.outgoing_http import OutgoingSession
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
|
||||
|
||||
class RequestMockWithTimeoutAsHeader(responses.RequestsMock):
|
||||
def _on_request(
|
||||
self,
|
||||
adapter: requests.adapters.HTTPAdapter,
|
||||
request: requests.PreparedRequest,
|
||||
**kwargs: Any,
|
||||
) -> requests.Response:
|
||||
if kwargs.get("timeout") is not None:
|
||||
request.headers["X-Timeout"] = kwargs["timeout"]
|
||||
return super()._on_request( # type: ignore[misc] # This is an undocumented internal API
|
||||
adapter,
|
||||
request,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
class TestOutgoingHttp(ZulipTestCase):
|
||||
def test_timeouts(self) -> None:
|
||||
with RequestMockWithTimeoutAsHeader() as mock_requests:
|
||||
mock_requests.add(responses.GET, "http://example.com/")
|
||||
OutgoingSession(timeout=17).get("http://example.com/")
|
||||
self.assertEqual(len(mock_requests.calls), 1)
|
||||
self.assertEqual(mock_requests.calls[0].request.headers["X-Timeout"], 17)
|
||||
|
||||
with RequestMockWithTimeoutAsHeader() as mock_requests:
|
||||
mock_requests.add(responses.GET, "http://example.com/")
|
||||
OutgoingSession(timeout=17).get("http://example.com/", timeout=42)
|
||||
self.assertEqual(len(mock_requests.calls), 1)
|
||||
self.assertEqual(mock_requests.calls[0].request.headers["X-Timeout"], 42)
|
||||
Loading…
Reference in New Issue
Block a user