r47132 - Apply proxy-protocol-8203-5.patch.

adiroiban-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Sat, 2 Apr 2016 17:27:26 -0600 (MDT)
Newsgroups gmane.comp.python.twisted.commits
Message-ID <[email protected]>
Author: adiroiban
Date: Sat Apr  2 17:27:20 2016
New Revision: 47132

Added:
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/__init__.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/_exc.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/_info.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/_interfaces.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/_v1parser.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/_v2parser.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/_wrapper.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/test/
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/test/__init__.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/test/test_v1parser.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/test/test_v2parser.py
   branches/haproxy-endpoint-8203-2/twisted/protocols/haproxy/test/test_wrapper.py
   branches/haproxy-endpoint-8203-2/twisted/topfiles/8203.feature
Modified:
   branches/haproxy-endpoint-8203-2/docs/core/howto/endpoints.rst
   branches/haproxy-endpoint-8203-2/twisted/internet/endpoints.py
   branches/haproxy-endpoint-8203-2/twisted/internet/test/test_endpoints.py
   branches/haproxy-endpoint-8203-2/twisted/plugins/twisted_core.py

Log:
Apply proxy-protocol-8203-5.patch.

Modified: branches/haproxy-endpoint-8203-2/docs/core/howto/endpoints.rst
==============================================================================
--- branches/haproxy-endpoint-8203-2/docs/core/howto/endpoints.rst	(original)
+++ branches/haproxy-endpoint-8203-2/docs/core/howto/endpoints.rst	Sat Apr  2 17:27:20 2016
@@ -353,3 +353,10 @@
    For example, ``systemd:domain=INET6:index=3``.
 
    See also :doc:`Deploying Twisted with systemd <systemd>`.
+
+PROXY
+  The PROXY protocol is a stream wrapper and can be applied any of the other server endpoints by placing ``haproxy:`` in front of a normal port definition.
+
+  For example, ``haproxy:tcp:port=80:interface=192.168.1.1`` or ``haproxy:ssl:port=443:privateKey=/etc/ssl/server.pem:extraCertChain=/etc/ssl/chain.pem:sslmethod=SSLv3_METHOD:dhParameters=dh_param_1024.pem``.
+
+  The PROXY protocol provides a way for load balancers and reverse proxies to send down the real IP of a connection's source and destination without relying on X-Forwarded-For headers. A Twisted service using this endpoint wrapper must run behind a service that sends valid PROXY protocol headers. For more on the protocol see `the formal specification<http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt>`_. Both version one and two of the protocol are currently supported.

Modified: branches/haproxy-endpoint-8203-2/twisted/internet/endpoints.py
==============================================================================
--- branches/haproxy-endpoint-8203-2/twisted/internet/endpoints.py	(original)
+++ branches/haproxy-endpoint-8203-2/twisted/internet/endpoints.py	Sat Apr  2 17:27:20 2016
@@ -34,6 +34,7 @@
 from twisted.internet.stdio import StandardIO, PipeAddress
 from twisted.internet.task import LoopingCall
 from twisted.plugin import IPlugin, getPlugins
+from twisted.protocols import haproxy
 from twisted.python import log
 from twisted.python.compat import nativeString, unicode, _matchingString
 from twisted.python.components import proxyForInterface
@@ -41,6 +42,7 @@
 from twisted.python.failure import Failure
 from twisted.python.filepath import FilePath
 from twisted.python.compat import iterbytes
+from twisted.python.compat import iteritems
 from twisted.python.systemd import ListenFDs
 
 
@@ -1281,6 +1283,41 @@
 
 
 
+@implementer(IPlugin, IStreamServerEndpointStringParser)
+class _HAProxyServerParser(object):
+    """
+    Stream server endpoint string parser for the HAProxyServerEndpoint type.
+
+    @ivar prefix: See L{IStreamServerEndpointStringParser.prefix}.
+    """
+    prefix = "haproxy"
+
+    def _parseServer(self, reactor, *args, **kwargs):
+        """
+        Internal parser function.
+
+        @param reactor: An L{IReactorTCP} provider.
+
+        @param wrapped: The name of the endpoint to wrap. Ex: tcp6.
+        @type wrapped: str
+        """
+        # Rebuild the description to re-dispatch the request.
+        description = ':'.join(str(arg) for arg in args)
+        description += ':'.join(
+            '%s=%s' % (str(key), quoteStringArgument(str(value)))
+            for key, value in iteritems(kwargs)
+        )
+        return _WrapperServerEndpoint(
+            serverFromString(reactor, description),
+            haproxy.HAProxyWrappingFactory,
+        )
+
+
+    def parseStreamServer(self, reactor, *args, **kwargs):
+        return self._parseServer(reactor, *args, **kwargs)
+
+
+
 _serverParsers = {"tcp": _parseTCP,
                   "unix": _parseUNIX,
                   "ssl": _parseSSL,
@@ -1904,6 +1941,30 @@
 
 
 
+@implementer(interfaces.IStreamServerEndpoint)
+class _WrapperServerEndpoint(object):
+    """
+    A server endpoint that wraps another server endpoint.
+    """
+
+    def __init__(self, wrappedEndpoint, wrapperFactory):
+        """
+        Construct a L{_WrapperServerEndpoint}.
+        """
+        self._wrappedEndpoint = wrappedEndpoint
+        self._wrapperFactory = wrapperFactory
+
+
+    def listen(self, protocolFactory):
+        """
+        Connect the given protocol factory and unwrap its result.
+        """
+        return self._wrappedEndpoint.listen(
+            self._wrapperFactory(protocolFactory)
+        )
+
+
+
 def wrapClientTLS(connectionCreator, wrappedEndpoint):
     """
     Wrap an endpoint which upgrades to TLS as soon as the connection is
@@ -2025,6 +2086,3 @@
         @rtype: L{IStreamClientEndpoint}
         """
         return _parseClientTLS(reactor, *args, **kwargs)
-
-
-

Modified: branches/haproxy-endpoint-8203-2/twisted/internet/test/test_endpoints.py
==============================================================================
--- branches/haproxy-endpoint-8203-2/twisted/internet/test/test_endpoints.py	(original)
+++ branches/haproxy-endpoint-8203-2/twisted/internet/test/test_endpoints.py	Sat Apr  2 17:27:20 2016
@@ -3729,3 +3729,50 @@
         notImplemented = self.assertRaises(NotImplementedError, replaced,
                                            None, None)
         self.assertIn("OpenSSL not available", str(notImplemented))
+
+
+class HAProxyServerParserTests(unittest.TestCase):
+    """
+    Tests that the parser generates the correct endpoints.
+    """
+
+    def test_tcp4(self):
+        """
+        Test if the parser generates a wrapped TCP4 endpoint.
+        """
+        parser = endpoints._HAProxyServerParser()
+        server = parser.parseStreamServer(reactor, 'haproxy', 'tcp', '8080')
+        self.assertIsInstance(server, endpoints._WrapperServerEndpoint)
+        self.assertIsInstance(
+            server._wrappedEndpoint._wrappedEndpoint,
+            endpoints.TCP4ServerEndpoint,
+        )
+
+    def test_tcp6(self):
+        """
+        Test if the parser generates a wrapped TCP6 endpoint.
+        """
+        parser = endpoints._HAProxyServerParser()
+        server = parser.parseStreamServer(reactor, 'haproxy', 'tcp6', '8080')
+        self.assertIsInstance(server, endpoints._WrapperServerEndpoint)
+        self.assertIsInstance(
+            server._wrappedEndpoint._wrappedEndpoint,
+            endpoints.TCP6ServerEndpoint,
+        )
+
+    def test_unix(self):
+        """
+        Test if the parser generates a wrapped UNIX endpoint.
+        """
+        parser = endpoints._HAProxyServerParser()
+        server = parser.parseStreamServer(
+            reactor,
+            'haproxy',
+            'unix',
+            '/tmp/test',
+        )
+        self.assertIsInstance(server, endpoints._WrapperServerEndpoint)
+        self.assertIsInstance(
+            server._wrappedEndpoint._wrappedEndpoint,
+            endpoints.UNIXServerEndpoint,
+        )

Modified: branches/haproxy-endpoint-8203-2/twisted/plugins/twisted_core.py
==============================================================================
--- branches/haproxy-endpoint-8203-2/twisted/plugins/twisted_core.py	(original)
+++ branches/haproxy-endpoint-8203-2/twisted/plugins/twisted_core.py	Sat Apr  2 17:27:20 2016
@@ -5,9 +5,10 @@
 
 from twisted.internet.endpoints import (
     _SystemdParser, _TCP6ServerParser, _StandardIOParser,
-    _TLSClientEndpointParser)
+    _TLSClientEndpointParser, _HAProxyServerParser)
 
 systemdEndpointParser = _SystemdParser()
 tcp6ServerEndpointParser = _TCP6ServerParser()
 stdioEndpointParser = _StandardIOParser()
 tlsClientEndpointParser = _TLSClientEndpointParser()
+haProxyServerEndpointParser = _HAProxyServerParser()