Issue 1:
Not sure whether this is actually a requests bug, but trying here first as it's here it manifests.

I'm using a http proxy for https traffic, and it works fine for normal GET, POST and PUT requests using requests. However, if enabled chunked uploads, it fails with requests.exceptions.ConnectionError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1131)

From googling it appears to be trying to access the http proxy using https. I'm fully aware of the normal "problem" where people confuse the protocols and use "https://" for their http proxy, but as can be seen in the example below this is not the problem in this case.

I've been digging into adapters.py and the low_conn connection it uses appears to have the correct proxy set (with "http" as protocol), but this is outside my expertise.

Expected Result

Request to go through proxy like for non-chunked uploads without errors.

Actual Result

Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/requests/adapters.py", line 521, in send
low_conn.endheaders()
File "/usr/lib/python3.8/http/client.py", line 1251, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.8/http/client.py", line 1011, in _send_output
self.send(msg)
File "/usr/lib/python3.8/http/client.py", line 951, in send
self.connect()
File "/usr/local/lib/python3.8/dist-packages/urllib3/connection.py", line 414, in connect
self.sock = ssl_wrap_socket(
File "/usr/local/lib/python3.8/dist-packages/urllib3/util/ssl_.py", line 449, in ssl_wrap_socket
ssl_sock = _ssl_wrap_socket_impl(
File "/usr/local/lib/python3.8/dist-packages/urllib3/util/ssl_.py", line 493, in _ssl_wrap_socket_impl
return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1131)

Reproduction Steps

Run script below with and without proxy. Without proxy it works fine, with http proxy it gives above error.

import requests

with open('test', 'w') as f:
f.write('test')

with open('test', 'rb') as f:
resp = requests.put('https://www.google.com', data=f)
assert resp.status_code == 405

def x():
yield "test".encode('utf-8')

resp = requests.put('https://www.google.com', data=x())
assert resp.status_code == 405

System Information

$ python -m requests.help

{
"chardet": {
"version": null
},
"charset_normalizer": {
"version": "3.0.1"
},
"cryptography": {
"version": ""
},
"idna": {
"version": "3.4"
},
"implementation": {
"name": "CPython",
"version": "3.8.10"
},
"platform": {
"release": "4.18.0-425.10.1.el8_7.x86_64",
"system": "Linux"
},
"pyOpenSSL": {
"openssl_version": "",
"version": null
},
"requests": {
"version": "2.28.2"
},
"system_ssl": {
"version": "1010106f"
},
"urllib3": {
"version": "1.26.14"
},
"using_charset_normalizer": true,
"using_pyopenssl": false
}

Issue 2:
I am using the chunked request body feature (data=generator). When defining a HTTP proxy and sending a request to a HTTPS URL, requests is trying to perform a TLS handshake with the (HTTP) proxy server, instead of sending a CONNECT request and performing the handshake with the target server through the tunnel. This behaviour prevents the request from completing successfully.

Expected Result

requests should send a CONNECT request to the proxy and negotiate TLS with the target server through the tunnel.

Actual Result

requests tries to negotiate TLS directly with the HTTP proxy server, and fails to do so.

Reproduction Steps

Run an HTTP proxy on 127.0.0.1:8080 and execute the following code:

import requests

def body_generator():
yield "test"
return

requests.post("https://www.google.com/",
proxies={"https": "http://127.0.0.1:8080/"},
data=body_generator(),
)

More info

The chunked encoding generator feature is implemented in requests/adapters.py:

try:
if not chunked:
resp = conn.urlopen(
...
)

# Send the request.
else:
if hasattr(conn, "proxy_pool"):
conn = conn.proxy_pool

low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT)

try:
... Send request with chunked body ...

In the case of chunked encoding, instead of using conn.urlopen to send the request, it uses conn._get_conn and sends the request manually.

It seems like, for some reason, conn._get_conn is not handling the proxy correctly.