Patchwork [2,of,3,STABLE] httpclient: pass serverhostname (issue5210)

login
register
mail settings
Submitter timeless
Date April 21, 2016, 5:30 a.m.
Message ID <ffc332df490b894efd35.1461216636@gcc2-power8.osuosl.org>
Download mbox | patch
Permalink /patch/14751/
State Accepted
Headers show

Comments

timeless - April 21, 2016, 5:30 a.m.
# HG changeset patch
# User timeless <timeless@mozdev.org>
# Date 1461216417 0
#      Thu Apr 21 05:26:57 2016 +0000
# Branch stable
# Node ID ffc332df490b894efd359d2ea6a5e0066fc6d7ea
# Parent  57d34adbea5be4a183a6a80a08abc45664c6d952
# Available At bb://timeless/mercurial-crew
#              hg pull bb://timeless/mercurial-crew -r ffc332df490b
httpclient: pass serverhostname (issue5210)
Augie Fackler - April 21, 2016, 4:37 p.m.
On Thu, Apr 21, 2016 at 05:30:36AM +0000, timeless wrote:
> # HG changeset patch
> # User timeless <timeless@mozdev.org>
> # Date 1461216417 0
> #      Thu Apr 21 05:26:57 2016 +0000
> # Branch stable
> # Node ID ffc332df490b894efd359d2ea6a5e0066fc6d7ea
> # Parent  57d34adbea5be4a183a6a80a08abc45664c6d952
> # Available At bb://timeless/mercurial-crew
> #              hg pull bb://timeless/mercurial-crew -r ffc332df490b
> httpclient: pass serverhostname (issue5210)

I know you sent me some bb PRs for httpclient's upstream - how do
those relate to this patch? This is the kind of thing I'd expect to
get clobbered next time I do an import from upstream...

>
> diff -r 57d34adbea5b -r ffc332df490b mercurial/httpclient/__init__.py
> --- a/mercurial/httpclient/__init__.py	Wed Apr 20 21:33:02 2016 +0000
> +++ b/mercurial/httpclient/__init__.py	Thu Apr 21 05:26:57 2016 +0000
> @@ -346,9 +346,62 @@
>              if '[' in host:
>                  host = host[1:-1]
>          if ssl_wrap_socket is not None:
> -            self._ssl_wrap_socket = ssl_wrap_socket
> +            _wrap_socket = ssl_wrap_socket
>          else:
> -            self._ssl_wrap_socket = socketutil.wrap_socket
> +            _wrap_socket = socketutil.wrap_socket
> +        def handlesarg(func, arg):
> +            """ Try to determine if func accepts arg
> +
> +            Typically a function will raise:
> +                TypeError got an unexpected keyword argument '{arg}'
> +            ... if it doesn't
> +            If it throws this for arg, handlesarg will return False
> +            If it throws this for our dummy, handlesarg will return True
> +
> +            If it happens to take **args, then it could do anything:
> +                * It could throw a different TypeError, just for fun
> +                * It could throw an ArgumentError or anything else
> +                * It could choose not to throw an Exception at all
> +            handlesarg will return 'unknown'
> +            """
> +            args = {arg: True, 'nosuchargument': True}
> +            try:
> +                if arg == 'server_hostname':
> +                    func(server_hostname=True, nosuchargument=True)
> +                else:
> +                    func(serverhostname=True, nosuchargument=True)
> +            except TypeError as e:
> +                msg = str(e)
> +                if 'nosuchargument' in msg:
> +                    return True
> +                if arg in msg:
> +                    return False
> +                return 'unknown'
> +            except:
> +                return 'unknown'
> +            return 'unknown'
> +        call_wrap_socket = None
> +        handlesubar = handlesarg(_wrap_socket, 'server_hostname')
> +        if handlesubar is True:
> +            # supports server_hostname
> +            call_wrap_socket = _wrap_socket
> +        handlesnobar = handlesarg(_wrap_socket, 'serverhostname')
> +        if handlesnobar is True and handlesubar is not True:
> +            # supports serverhostname
> +            def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
> +                return _wrap_socket(sock, serverhostname=server_hostname,
> +                                    **ssl_opts)
> +        if handlesubar is False and handlesnobar is False:
> +            # does not support either
> +            def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
> +                return _wrap_socket(sock, **ssl_opts)
> +        if call_wrap_socket is None:
> +            # we assume it takes **args
> +            def call_wrap_socket(sock, **ssl_opts):
> +                if 'server_hostname' in ssl_opts:
> +                    ssl_opts['serverhostname'] = ssl_opts['server_hostname']
> +                return _wrap_socket(sock, **ssl_opts)
> +        self._ssl_wrap_socket = call_wrap_socket
>          if use_ssl is None and port is None:
>              use_ssl = False
>              port = 80
> @@ -429,7 +482,8 @@
>              sock.setblocking(1)
>              logger.debug('wrapping socket for ssl with options %r',
>                           self.ssl_opts)
> -            sock = self._ssl_wrap_socket(sock, **self.ssl_opts)
> +            sock = self._ssl_wrap_socket(sock, server_hostname=self.host,
> +                                         **self.ssl_opts)
>              if self._ssl_validator:
>                  self._ssl_validator(sock)
>          sock.setblocking(0)
> diff -r 57d34adbea5b -r ffc332df490b mercurial/httpclient/socketutil.py
> --- a/mercurial/httpclient/socketutil.py	Wed Apr 20 21:33:02 2016 +0000
> +++ b/mercurial/httpclient/socketutil.py	Thu Apr 21 05:26:57 2016 +0000
> @@ -122,7 +122,8 @@
>                  server_side=False, cert_reqs=CERT_NONE,
>                  ssl_version=_PROTOCOL_SSLv23, ca_certs=None,
>                  do_handshake_on_connect=True,
> -                suppress_ragged_eofs=True):
> +                suppress_ragged_eofs=True,
> +                server_hostname=None):
>          """Backport of ssl.wrap_socket from Python 2.6."""
>          if cert_reqs != CERT_NONE and ca_certs:
>              raise CertificateValidationUnsupported(
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
timeless - April 22, 2016, 12:01 a.m.
This should be equivalent to
https://bitbucket.org/durin42/httpplus/pull-requests/1/ssl-add-support-for-server_hostname/commits

On Thu, Apr 21, 2016 at 12:37 PM, Augie Fackler <raf@durin42.com> wrote:
> On Thu, Apr 21, 2016 at 05:30:36AM +0000, timeless wrote:
>> # HG changeset patch
>> # User timeless <timeless@mozdev.org>
>> # Date 1461216417 0
>> #      Thu Apr 21 05:26:57 2016 +0000
>> # Branch stable
>> # Node ID ffc332df490b894efd359d2ea6a5e0066fc6d7ea
>> # Parent  57d34adbea5be4a183a6a80a08abc45664c6d952
>> # Available At bb://timeless/mercurial-crew
>> #              hg pull bb://timeless/mercurial-crew -r ffc332df490b
>> httpclient: pass serverhostname (issue5210)
>
> I know you sent me some bb PRs for httpclient's upstream - how do
> those relate to this patch? This is the kind of thing I'd expect to
> get clobbered next time I do an import from upstream...
>
>>
>> diff -r 57d34adbea5b -r ffc332df490b mercurial/httpclient/__init__.py
>> --- a/mercurial/httpclient/__init__.py        Wed Apr 20 21:33:02 2016 +0000
>> +++ b/mercurial/httpclient/__init__.py        Thu Apr 21 05:26:57 2016 +0000
>> @@ -346,9 +346,62 @@
>>              if '[' in host:
>>                  host = host[1:-1]
>>          if ssl_wrap_socket is not None:
>> -            self._ssl_wrap_socket = ssl_wrap_socket
>> +            _wrap_socket = ssl_wrap_socket
>>          else:
>> -            self._ssl_wrap_socket = socketutil.wrap_socket
>> +            _wrap_socket = socketutil.wrap_socket
>> +        def handlesarg(func, arg):
>> +            """ Try to determine if func accepts arg
>> +
>> +            Typically a function will raise:
>> +                TypeError got an unexpected keyword argument '{arg}'
>> +            ... if it doesn't
>> +            If it throws this for arg, handlesarg will return False
>> +            If it throws this for our dummy, handlesarg will return True
>> +
>> +            If it happens to take **args, then it could do anything:
>> +                * It could throw a different TypeError, just for fun
>> +                * It could throw an ArgumentError or anything else
>> +                * It could choose not to throw an Exception at all
>> +            handlesarg will return 'unknown'
>> +            """
>> +            args = {arg: True, 'nosuchargument': True}
>> +            try:
>> +                if arg == 'server_hostname':
>> +                    func(server_hostname=True, nosuchargument=True)
>> +                else:
>> +                    func(serverhostname=True, nosuchargument=True)
>> +            except TypeError as e:
>> +                msg = str(e)
>> +                if 'nosuchargument' in msg:
>> +                    return True
>> +                if arg in msg:
>> +                    return False
>> +                return 'unknown'
>> +            except:
>> +                return 'unknown'
>> +            return 'unknown'
>> +        call_wrap_socket = None
>> +        handlesubar = handlesarg(_wrap_socket, 'server_hostname')
>> +        if handlesubar is True:
>> +            # supports server_hostname
>> +            call_wrap_socket = _wrap_socket
>> +        handlesnobar = handlesarg(_wrap_socket, 'serverhostname')
>> +        if handlesnobar is True and handlesubar is not True:
>> +            # supports serverhostname
>> +            def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
>> +                return _wrap_socket(sock, serverhostname=server_hostname,
>> +                                    **ssl_opts)
>> +        if handlesubar is False and handlesnobar is False:
>> +            # does not support either
>> +            def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
>> +                return _wrap_socket(sock, **ssl_opts)
>> +        if call_wrap_socket is None:
>> +            # we assume it takes **args
>> +            def call_wrap_socket(sock, **ssl_opts):
>> +                if 'server_hostname' in ssl_opts:
>> +                    ssl_opts['serverhostname'] = ssl_opts['server_hostname']
>> +                return _wrap_socket(sock, **ssl_opts)
>> +        self._ssl_wrap_socket = call_wrap_socket
>>          if use_ssl is None and port is None:
>>              use_ssl = False
>>              port = 80
>> @@ -429,7 +482,8 @@
>>              sock.setblocking(1)
>>              logger.debug('wrapping socket for ssl with options %r',
>>                           self.ssl_opts)
>> -            sock = self._ssl_wrap_socket(sock, **self.ssl_opts)
>> +            sock = self._ssl_wrap_socket(sock, server_hostname=self.host,
>> +                                         **self.ssl_opts)
>>              if self._ssl_validator:
>>                  self._ssl_validator(sock)
>>          sock.setblocking(0)
>> diff -r 57d34adbea5b -r ffc332df490b mercurial/httpclient/socketutil.py
>> --- a/mercurial/httpclient/socketutil.py      Wed Apr 20 21:33:02 2016 +0000
>> +++ b/mercurial/httpclient/socketutil.py      Thu Apr 21 05:26:57 2016 +0000
>> @@ -122,7 +122,8 @@
>>                  server_side=False, cert_reqs=CERT_NONE,
>>                  ssl_version=_PROTOCOL_SSLv23, ca_certs=None,
>>                  do_handshake_on_connect=True,
>> -                suppress_ragged_eofs=True):
>> +                suppress_ragged_eofs=True,
>> +                server_hostname=None):
>>          """Backport of ssl.wrap_socket from Python 2.6."""
>>          if cert_reqs != CERT_NONE and ca_certs:
>>              raise CertificateValidationUnsupported(
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel@mercurial-scm.org
>> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff -r 57d34adbea5b -r ffc332df490b mercurial/httpclient/__init__.py
--- a/mercurial/httpclient/__init__.py	Wed Apr 20 21:33:02 2016 +0000
+++ b/mercurial/httpclient/__init__.py	Thu Apr 21 05:26:57 2016 +0000
@@ -346,9 +346,62 @@ 
             if '[' in host:
                 host = host[1:-1]
         if ssl_wrap_socket is not None:
-            self._ssl_wrap_socket = ssl_wrap_socket
+            _wrap_socket = ssl_wrap_socket
         else:
-            self._ssl_wrap_socket = socketutil.wrap_socket
+            _wrap_socket = socketutil.wrap_socket
+        def handlesarg(func, arg):
+            """ Try to determine if func accepts arg
+
+            Typically a function will raise:
+                TypeError got an unexpected keyword argument '{arg}'
+            ... if it doesn't
+            If it throws this for arg, handlesarg will return False
+            If it throws this for our dummy, handlesarg will return True
+
+            If it happens to take **args, then it could do anything:
+                * It could throw a different TypeError, just for fun
+                * It could throw an ArgumentError or anything else
+                * It could choose not to throw an Exception at all
+            handlesarg will return 'unknown'
+            """
+            args = {arg: True, 'nosuchargument': True}
+            try:
+                if arg == 'server_hostname':
+                    func(server_hostname=True, nosuchargument=True)
+                else:
+                    func(serverhostname=True, nosuchargument=True)
+            except TypeError as e:
+                msg = str(e)
+                if 'nosuchargument' in msg:
+                    return True
+                if arg in msg:
+                    return False
+                return 'unknown'
+            except:
+                return 'unknown'
+            return 'unknown'
+        call_wrap_socket = None
+        handlesubar = handlesarg(_wrap_socket, 'server_hostname')
+        if handlesubar is True:
+            # supports server_hostname
+            call_wrap_socket = _wrap_socket
+        handlesnobar = handlesarg(_wrap_socket, 'serverhostname')
+        if handlesnobar is True and handlesubar is not True:
+            # supports serverhostname
+            def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
+                return _wrap_socket(sock, serverhostname=server_hostname,
+                                    **ssl_opts)
+        if handlesubar is False and handlesnobar is False:
+            # does not support either
+            def call_wrap_socket(sock, server_hostname=None, **ssl_opts):
+                return _wrap_socket(sock, **ssl_opts)
+        if call_wrap_socket is None:
+            # we assume it takes **args
+            def call_wrap_socket(sock, **ssl_opts):
+                if 'server_hostname' in ssl_opts:
+                    ssl_opts['serverhostname'] = ssl_opts['server_hostname']
+                return _wrap_socket(sock, **ssl_opts)
+        self._ssl_wrap_socket = call_wrap_socket
         if use_ssl is None and port is None:
             use_ssl = False
             port = 80
@@ -429,7 +482,8 @@ 
             sock.setblocking(1)
             logger.debug('wrapping socket for ssl with options %r',
                          self.ssl_opts)
-            sock = self._ssl_wrap_socket(sock, **self.ssl_opts)
+            sock = self._ssl_wrap_socket(sock, server_hostname=self.host,
+                                         **self.ssl_opts)
             if self._ssl_validator:
                 self._ssl_validator(sock)
         sock.setblocking(0)
diff -r 57d34adbea5b -r ffc332df490b mercurial/httpclient/socketutil.py
--- a/mercurial/httpclient/socketutil.py	Wed Apr 20 21:33:02 2016 +0000
+++ b/mercurial/httpclient/socketutil.py	Thu Apr 21 05:26:57 2016 +0000
@@ -122,7 +122,8 @@ 
                 server_side=False, cert_reqs=CERT_NONE,
                 ssl_version=_PROTOCOL_SSLv23, ca_certs=None,
                 do_handshake_on_connect=True,
-                suppress_ragged_eofs=True):
+                suppress_ragged_eofs=True,
+                server_hostname=None):
         """Backport of ssl.wrap_socket from Python 2.6."""
         if cert_reqs != CERT_NONE and ca_certs:
             raise CertificateValidationUnsupported(