Fail fast on HTTPS calls with the ssl module unavailable

While hanging around the IRC channel today, a user came in with an HTTPS request that was not completing. It turned out that he didn't have ssl configured properly on his python 3 installation (here's looking at you ArchLinux).

It would seem to me that failing quickly as opposed to just hanging there would be far more useful. Admittedly you would hope an advanced user would know if they have SSL installed or enabled, but someone just starting out might not. I know urllib3 smothers the Exception they get when importing ssl, but would anyone object to throwing a custom Exception when users try to make HTTPS requests?


I'm all for it. =)


@sigmavirus24 
Could you provide more details/a transcription of the IRC conversation?
I created a really minimal VM of ArchLinux (base installation + python from the repos + requests from pip and from the repos) and everything worked fine.


@t-8ch

The following is the start of the conversation: 
https://botbot.me/freenode/python-requests/msg/2523881/

You can see I worked through it with upmauro until we realized that his 
version of python 3 had been compiled without support for `ssl`.  
(https://botbot.me/freenode/python-requests/msg/2523881/ to save you some 
reading)

I know that in one of the recent changes I saw in urllib3 the following:

``` python
try:
    import ssl
except ImportError:
    ssl = None
```

I suspect the fact that no exception was raised was because of the silent 
failure of importing the `ssl` module. I obviously have to attempt to build a 
system in which the ssl module would be unavailable in a version of python to 
be absolutely certain, but judging by the behaviour it seems a fair 
conclusion.


I can reproduce this now. The mentioned URL also hangs for me on python3.
Importing ssl on the other hand works just fine.
On python2 it takes a bit of time but works in the end.

Python3 on ArchLinux is compiled with ssl:

```
[~]$ ldd /usr/lib/python3.3/lib-dynload/_ssl.cpython-33m.so 
    libssl.so.1.0.0 => /usr/lib/libssl.so.1.0.0 (0x00007f760ef7c000)
    # [..]
[~]$ pacman -Qi python
Name           : python
Version        : 3.3.0-3
# [..]
Depends On     : expat  bzip2  gdbm  openssl  libffi  zlib
# [..]
```

If I remove `openssl` it dies while importing requests.


The problem is upmauro has disappeared so I don't know if we'll be able to 
confirm any of these details. The other issue is that setting a timeout did 
not work for him.


I'll look into the issue of the hanging request tomorrow.
I assume there was some miscommunication between upmauro and you because ArchLinux without openssl is quite unusable (no SSH, no pacman).


No. ArchLinux had SSL. His version of Python 2 had support for it. His version 
of Python 3 did not.


The version in the official repos definitely has ssl support.


Then he did something to install python 3 without ssl support. What, we may 
never know, but it remains an issue, and python compiled without ssl support 
is apparently a common issue. If it doesn't fail fast, that is a design flaw 
in my candid opinion. I'll figure out how to reproduce the environment and 
update the ticket when I do.


You may want to keep Appengine in mind, where no ssl module is available but `HTTPSConnection` is provided.

Urllib3 should fail the moment one tries to issue a https request on an unsupported platform (determined by feature detection).
The many import-ssl-module bugreports for 1.1.0 were caused by a bug I introduced where the ssl module was accessed while importing urllib3 in general. This has been fixed.


> You may want to keep Appengine in mind, where no ssl module is available but `HTTPSConnection` is provided.

We don't support Appengine. =)


Yeah, I am aware of this.
To clarify my previous post: urllib3 _already does_ the feature detection and fails if one tries to do HTTPS on unsupported platforms. (Including the fallback on Appengine)
The issue upmauro faced also occurs with plain httplib on python3 (works on python2):

``` py
try:
    import http.client as lib
except ImportError:
    import httplib as lib

conn = lib.HTTPSConnection('services.redecard.com.br')
conn.request('GET', '/novoportal/Portals/Servico/PopUp_login_Existente.asp')

r = conn.getresponse()
print(r.read(10000))
print(r.getheaders())
```


Right, so it's probably the website. =) Thanks Thomas!