• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

localstack / localstack / eecfcde7-ad29-491d-8275-025cc506dd7d

14 May 2025 03:08PM UTC coverage: 86.62% (-0.004%) from 86.624%
eecfcde7-ad29-491d-8275-025cc506dd7d

push

circleci

web-flow
Added pagination and filtering for s3 list buckets operation (#12609)

18 of 18 new or added lines in 1 file covered. (100.0%)

11 existing lines in 3 files now uncovered.

64358 of 74299 relevant lines covered (86.62%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.09
/localstack-core/localstack/http/duplex_socket.py
1
from __future__ import annotations
1✔
2

3
import logging
1✔
4
import socket
1✔
5
import ssl
1✔
6
from asyncio.selector_events import BaseSelectorEventLoop
1✔
7

8
from localstack.utils.asyncio import run_sync
1✔
9
from localstack.utils.objects import singleton_factory
1✔
10
from localstack.utils.patch import Patch, patch
1✔
11

12
# set up logger
13
LOG = logging.getLogger(__name__)
1✔
14

15

16
class DuplexSocket(ssl.SSLSocket):
1✔
17
    """Simple duplex socket wrapper that allows serving HTTP/HTTPS over the same port."""
18

19
    def accept(self):
1✔
20
        newsock, addr = socket.socket.accept(self)
1✔
21
        if DuplexSocket.is_ssl_socket(newsock) is not False:
1✔
22
            newsock = self.context.wrap_socket(
1✔
23
                newsock,
24
                do_handshake_on_connect=self.do_handshake_on_connect,
25
                suppress_ragged_eofs=self.suppress_ragged_eofs,
26
                server_side=True,
27
            )
28

29
        return newsock, addr
1✔
30

31
    @staticmethod
1✔
32
    def is_ssl_socket(newsock):
1✔
33
        """Returns True/False if the socket uses SSL or not, or None if the status cannot be
34
        determined"""
35

36
        def peek_ssl_header():
1✔
37
            peek_bytes = 5
1✔
38
            first_bytes = newsock.recv(peek_bytes, socket.MSG_PEEK)
1✔
39
            if len(first_bytes or "") != peek_bytes:
1✔
40
                return
1✔
41
            first_byte = first_bytes[0]
1✔
42
            return first_byte < 32 or first_byte >= 127
1✔
43

44
        try:
1✔
45
            return peek_ssl_header()
1✔
UNCOV
46
        except Exception:
×
47
            # Fix for "[Errno 11] Resource temporarily unavailable" - This can
48
            #   happen if we're using a non-blocking socket in a blocking thread.
UNCOV
49
            newsock.setblocking(1)
×
UNCOV
50
            newsock.settimeout(1)
×
UNCOV
51
            try:
×
UNCOV
52
                return peek_ssl_header()
×
53
            except Exception:
×
54
                return False
×
55

56

57
@singleton_factory
1✔
58
def enable_duplex_socket():
1✔
59
    """
60
    Function which replaces the ssl.SSLContext.sslsocket_class with the DuplexSocket, enabling serving both,
61
    HTTP and HTTPS connections on a single port.
62
    """
63

64
    # set globally defined SSL socket implementation class
65
    Patch(ssl.SSLContext, "sslsocket_class", DuplexSocket).apply()
1✔
66

67
    if hasattr(BaseSelectorEventLoop, "_accept_connection2"):
1✔
68

69
        @patch(BaseSelectorEventLoop._accept_connection2)
1✔
70
        async def _accept_connection2(
1✔
71
            fn, self, protocol_factory, conn, extra, sslcontext, *args, **kwargs
72
        ):
73
            is_ssl_socket = await run_sync(DuplexSocket.is_ssl_socket, conn)
1✔
74
            if is_ssl_socket is False:
1✔
75
                sslcontext = None
1✔
76
            result = await fn(self, protocol_factory, conn, extra, sslcontext, *args, **kwargs)
1✔
77
            return result
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc