Raibek/requests-github-issues huggingface dataset:
multipart/form-data and a generator...

I used a generator as an argument to data for Content-Type application/json, and that worked fine.

The problem now is that I need to do this for multipart/form-data, and it appears to not support a generator.

- I tried files={'content': my_generator_func()} and got: a bytes-like object is required, not 'generator'; so it looks like it would have accepted a file descriptor, but not a generator.

- I then tried a generator for the data argument, and set the files argument to a form name and value: files={'encoding': (None, 'base64')} [I read you have to use the files argument to get requests to do multipart/form-data]  For that I get the error "Streamed bodies and files are mutually exclusive".

- Just in case, I tried it different ways setting a header for Content-Type multipart/form-data, both with and without it [I had read that setting it yourself can mess up requests.] If I omitted it, it complained it was missing; and if I included it, I got the errors previously specified.

Is it possible to furnish a generator for multipart/form-data? If I have to, I will dump the stream into a file and pass a descriptor to the files argument; but seems that you would have furnished a way to use a generator since it is supported for Content-Type application/json


As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)
chunked put using a generator function...

<!-- Summary. -->
I made a generator function that returns str chunks; I passed it to data [...data=my_func()...], and it eventually comes back with the error "memoryview: a bytes-like object is required, not 'str'" (debug statements indicate this is happening on the first yield...)

Documentation indicates this is the way to do it: [https://docs.python-requests.org/en/latest/user/advanced/#chunk-encoded-requests](https://docs.python-requests.org/en/latest/user/advanced/#chunk-encoded-requests)

## Expected Result

<!-- What you expected. -->
No error!

## Actual Result

<!-- What happened instead. -->
The error "memoryview: a bytes-like object is required, not 'str'".
## Reproduction Steps

```python
import requests

def test():
    json_preamble='{"field": "value",'
    def put()->str:
        yield json_preamble

        return '"field2": "value2"}' # final chunk...

    response=requests.put(some_url, data=put(), headers=some_headers)

test ()
```

## System Information

    $ python -m requests.help

```json
{
  "chardet": {
    "version": "5.1.0"
  },
  "charset_normalizer": {
    "version": "3.0.1"
  },
  "cryptography": {
    "version": "38.0.4"
  },
  "idna": {
    "version": "3.3"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.11.2"
  },
  "platform": {
    "release": "6.1.0-26-amd64",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "30000080",
    "version": "23.0.0"
  },
  "requests": {
    "version": "2.28.1"
  },
  "system_ssl": {
    "version": "300000e0"
  },
  "urllib3": {
    "version": "1.26.12"
  },
  "using_charset_normalizer": false,
  "using_pyopenssl": true
}
```

<!-- This command is only available on Requests v2.16.4 and greater. Otherwise,
please provide some basic information about your system (Python version,
operating system, &c). -->


PS A put using a file descriptor as the data argument (opened 'rb' to a .json file...) works...

PPS I also tried returning byte strings, even though the documentation example does not do that, and it also fails, with a 400, bad request...

Hi @steve-osfda, this issue was patched in 2.29.0 early last year. If you update to a more recent version, you should no longer encounter this issue.

I would also suggest double checking your generator is actually producing what you're expecting. Your `return` will not be included in the generator, only the `StopIteration` exception raised at the end. You're only sending `{"field": "value",'` over the wire which is likely the cause of your 400.

That was the ticket for the version that returned bytes! A generator needs an [implicit] return None

I will run with the bytes-encloded return for now (checking the requests version and act accordingly...) Debian bookworm stable right now uses 2.28.

Thank you so much for your speedy response!
Add HTTP status group properties for response objects

## PR Description:

This PR adds properties (`is_2xx_successful`, `is_5xx_server_error`, etc.) to the HTTP response class for easy classification of HTTP status codes, improving code readability.

## Justification:
- **Improved readability**: Using direct range comparisons like `100 <= self.status_code < 200` makes the code clear and intuitive.
- **Maintaining performance**: The range comparison is efficient and keeps the performance trade-offs minimal while avoiding unnecessary complexity.


No thank you. We're not expanding the API of Requests at this time and the freeze is well documented. Sorry you spent your energy on this
Refactor and optimize codebase

Add new tests for `HTTPAdapter` and hooks.

* **tests/test_adapters.py**
  - Add `test_http_adapter_send` to test the `send` method of `HTTPAdapter`.
  - Add `test_http_adapter_cert_verify` to test the `cert_verify` method of `HTTPAdapter`.

* **tests/test_hooks.py**
  - Add `test_hooks_with_multiple_hooks` to test hooks with multiple functions.
  - Add `test_hooks_with_no_hooks` to test hooks with no functions.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/akaday/requests?shareId=XXXX-XXXX-XXXX-XXXX).
`Session.request` documentation does not specify what unit of time the `timeout` argument uses

[the documentation for `requests.request`](https://requests.readthedocs.io/en/latest/api/#requests.request) says this: 

> - **timeout** (_[float](https://docs.python.org/3/library/functions.html#float) or [tuple](https://docs.python.org/3/library/stdtypes.html#tuple)_) – (optional) How many seconds to wait for the server to send data before giving up, as a float, or a [(connect timeout, read timeout)](https://requests.readthedocs.io/en/latest/user/advanced/#timeouts) tuple.

however [the documentation for the same argument in `Session.request`](https://requests.readthedocs.io/en/latest/api/#requests.Session.request) does not clarify that it uses seconds: 

> - **timeout** (_[float](https://docs.python.org/3/library/functions.html#float) or [tuple](https://docs.python.org/3/library/stdtypes.html#tuple)_) – (optional) How long to wait for the server to send data before giving up, as a float, or a [(connect timeout, read timeout)](https://requests.readthedocs.io/en/latest/user/advanced/#timeouts) tuple.
Change auth.py to be used in a FIPS system

<!-- Summary. -->

## Expected Result

Using the requests to perform a HTTPS action is working in a FIPS environment
 

<!-- What you expected. -->

## Actual Result

In UNIX environment with fips enabled the MD5 can't be used.
It provides this error

ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS

## Solution
Apply this patch in auth.py

`

*** 145,151 ****
                def md5_utf8(x):
                    if isinstance(x, str):
                        x = x.encode("utf-8")
  !                 return hashlib.md5(x).hexdigest()    
                hash_utf8 = md5_utf8
            elif _algorithm == "SHA":
--- 145,151 ----
                def md5_utf8(x):
                    if isinstance(x, str):
                        x = x.encode("utf-8")
  !                 return hashlib.md5(x,usedforsecurity=False).hexdigest()
                hash_utf8 = md5_utf8
            elif _algorithm == "SHA":

`


Could I work on this ticket ?
The `usedforsecurity` parameter is only available in python >= 3.9. Plan is to set `usedforsecurity` to True only if python version >= 3.9.
what is the point of this line?

https://github.com/psf/requests/blame/7335bbf480adc8e6aa88feb2022797a549a00aa3/src/requests/sessions.py#L746

You have blamed the commit which shows which PR it came from (#1944) which references other issues and PRs. Please follow and read those. Issues are for detects and this is neither a defect nor pointing at a potential one.
Teach users to use with-statements for Multipart-Encoded Files

Hello, everyone!!

I am proposing a small improvement to `quickstart.rst` in order to teach users to use `with`-statements with `open()` calls when POSTing Multipart-Encoded files.

Changes such as this have been rejected in the past, for good reason. Thanks for spending the time to open this PR. In the future you might consider checking for others that have been rejected
AttributeError: 'Request' object has no attribute 'authorize'

There seems to be a call to request.authorize. Shouldn't that be request.auth?

```python
import requests
requests.get("https://google.com").raise_for_status()
```

## Error
```
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/user/my_lib/__main__.py", line 23, in <module>
    requests.get("https://google.com").raise_for_status()
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/my_lib/.venv/lib/python3.11/site-packages/requests/api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/my_lib/.venv/lib/python3.11/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/my_lib/.venv/lib/python3.11/site-packages/requests/sessions.py", line 575, in request
    prep = self.prepare_request(req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/my_lib/.venv/lib/python3.11/site-packages/requests/sessions.py", line 479, in prepare_request
    auth = request.authorize
```


## System Information

    $ python -m requests.help

```json
{
  "chardet": {
    "version": null
  },
  "charset_normalizer": {
    "version": "3.3.2"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "3.8"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.11.9"
  },
  "platform": {
    "release": "6.10.3-amd64",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.32.3"
  },
  "system_ssl": {
    "version": "30300010"
  },
  "urllib3": {
    "version": "2.2.2"
  },
  "using_charset_normalizer": true,
  "using_pyopenssl": false
}
```

<!-- This command is only available on Requests v2.16.4 and greater. Otherwise,
please provide some basic information about your system (Python version,
operating system, &c). -->


Ok. nevermind. my venv was indeed outdated. closing
Environment variables take precedence over the explicitly passed proxies argument in session.get()

Environment:
**uname -a**
Linux 6.1.0-25-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.106-3 (2024-08-26) x86_64 GNU/Linux
**pip list**
Package            Version
------------------ ---------
certifi            2024.8.30
charset-normalizer 3.3.2
idna               3.8
pip                23.0.1
requests           2.32.3
setuptools         66.1.1
urllib3            2.2.2


Is that normal that the Environment variables: HTTP_PROXY and HTTPS_PROXY would override the proxies argument passed to session.get()?

test code:
`import requests
import os
# Disable environment proxies temporarily

#os.environ.pop('https_proxy', None)
#os.environ.pop('http_proxy', None)

# get all environs

print(os.environ)
# Define a test URL (you can replace this with a URL of your choice)
test_url = 'http://httpbin.org/ip'
# Define your custom proxies
my_proxies = None
# Create a session
session = requests.Session()

# Test session.get with explicitly defined proxies
print("=== Session GET with my_proxies ===")
response = session.get(url=test_url, proxies=my_proxies)

# Print the result (should reflect the proxy being used)
print(f'Your IP (using my_proxies): {response.json().get("origin")}')`


Run it and you will notice that the session uses the proxy server instead of None (specified by my_proxies = None)

As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)
[Bugfix] Fix incorrectly overwriting Content-Type header when passing JSON body

Checks for when to set the Content-Type header currently are using the wrong casing to check if the value has already been set before
This is causing the header to be overwritten from what it may have already been set as

![image](https://github.com/user-attachments/assets/7de66c24-f6d3-4b8e-9d5d-f85d0c735c7f)


Hi @DeathHound6,

It looks like you may not have tested this before creating a PR? In the future, please read our contribution guide and open an issue describing your problem.

Requests uses a custom CaseInsensitiveDict that handles this for headers. As noted in the docs, individual prepare_* methods must not be invoked from end user code. `prepare` will ensure headers are evaluated case-insensitive.

If you have more info with an actual repro, please open an issue with exact instructions. Thanks!

```
import requests

r = requests.Request(
   'POST',
   'https://httpbin.org/post',
   headers={'cOnTeNt-TyPe': "application/foo"},
   json={"a": "b"}
)

p = r.prepare()
print(p.headers["content-type"])
>>> "application/foo"
```


Hi @nateprewitt 

Apologies, I did not realise that a case-insensitive dict was being used here

I hadn't really dug too much into the source code of the library, but I do believe there is a bug present in this general area.

We were experiencing issues in work during the week regarding passing a JSON body in a patch request, where our API was returning a request validation error. Unfortunately our logs were not providing any more information than this.
All of our patch endpoints require a certain value in our content-type header, which is not the normal `application/json` value.

I believed the library overwriting the header was the issue here as passing our json data through the `json` kwarg was raising this error, but passing through `data` kwarg wasn't.

I may take a more thorough look into the library's source code soon to try to resolve this.

Once again, apologies for my lack of testing.
Thanks

Please read the documentation of that endpoint closely. We do not allow you to override the content type when passing to the json kwarg. That's why using data worked because that's what you must use in that case. It's not a bug by any stretch.
Requests changes the URL on GET

When fetching a URL containing `%2c` with GET, the URL gets modified and `%2c` is replaced by `%2C`.

The problem with this is that the server may return a 404 when using `%2C` even if the resource exists when looking for it using `%2c` (i.e.: the server is expecting you to honor the lower-case encoding). This should not be the case since [URL percent-encoding is case insensitive](https://stackoverflow.com/questions/7994287/is-url-percent-encoding-case-sensitive), but actual servers may not comply with that and require you to use lower case.

This comes from a real use case where the server is generating and providing a URL to download a file, and refuses to reply with the file unless `%2c` is used (instead of `%2C`).

## Expected Result

Requests should not modify the URL, since `%2c` is already encoded (and lower-case is just as valid encoding as upper-case).

This expected behavior can be found when using other libraries like `httpx`.

## Actual Result

Requests modifies the URL, changing `%2c` to `%2C`.

## Reproduction Steps

```py
url = "https://domain.com/foo/bar%2cbaz.pdf"
response = requests.get(url)

print(url)           # https://domain.com/foo/bar%2cbaz.pdf
print(response.url)  # https://domain.com/foo/bar%2Cbaz.pdf
```

## System Information

    $ python -m requests.help

```json
{
  "chardet": {
    "version": "5.2.0"
  },
  "charset_normalizer": {
    "version": "3.3.2"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "3.4"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.11.5"
  },
  "platform": {
    "release": "6.10.6-200.fc40.x86_64",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.32.3"
  },
  "system_ssl": {
    "version": "300000c0"
  },
  "urllib3": {
    "version": "2.0.7"
  },
  "using_charset_normalizer": false,
  "using_pyopenssl": false
}
```


In the future, please search **closed and** open issues before creating new ones that are duplicates.

@sigmavirus24 I always do, but I didn't manage to find a duplicate.

Would you mind sharing which is/are the duplicate/s of this issue?

Also for traceability and future users that may come here and want to understand why this one was closed.

#6115

@sigmavirus24 I think that would not be the same issue as stated here. The issue I describe is about a URL that is already escaped/encoded using `%2c`. So there is no reason for `requests` to re-encode it again with `%2C` (both `%2c` and `%2C` are valid ways to encode/escape).

Or am I missing something?

What you're missing is that in that issue and others linked from it, people wish to control the encoding (or lack thereof) and in general normalization of the query string, which is what you want as well
Cannot close the proxy

<!-- Summary. -->
In windows pycharm jupyterlab when i open windows system proxy requests will use the proxy i set on windows system.
but cannot close this proxy direct to the internet . I try  
```python
response = requests.post(url, headers=headers, json=data, proxies=None)
response = requests.post(url, headers=headers, json=data, proxies={})
response = requests.post(url, headers=headers, json=data, proxies="")
```
can't work
## Expected Result

don't use proxy I set on windows
<!-- What you expected. -->
## Actual Result
I can check this connection on clash
<!-- What happened instead. -->

## Reproduction Steps
windows  requests                  2.31.0
use pycharm and jupyter
```python
import requests
response = requests.post(url, headers=headers, json=data, proxies=None)# I try None {} "" []
```

## System Information

    $ python -m requests.help

```json
{
  "chardet": {
    "version": null
  },
  "charset_normalizer": {
    "version": "2.0.4"
  },
  "cryptography": {
    "version": "41.0.7"
  },
  "idna": {
    "version": "3.4"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.11.5"
  },
  "platform": {
    "release": "10",
    "system": "Windows"
  },
  "pyOpenSSL": {
    "openssl_version": "300000c0",
    "version": "23.2.0"
  },
  "requests": {
    "version": "2.31.0"
  },
  "system_ssl": {
    "version": "300000c0"
  },
  "urllib3": {
    "version": "1.26.18"
  },
  "using_charset_normalizer": true,
  "using_pyopenssl": true
}

```

<!-- This command is only available on Requests v2.16.4 and greater. Otherwise,
please provide some basic information about your system (Python version,
operating system, &c). -->
Add Warning for Incorrect Keyword Arguments in POST Requests (e.g., 'header' instead of 'headers')

Summary:

When making a POST request using the requests library, passing an incorrect keyword argument (e.g., header instead of headers) does not trigger any error or warning. This can lead to unintended behavior, as the request proceeds without the intended headers being applied.

Problem:

The requests library currently does not validate keyword arguments for correctness. If a user accidentally passes a misspelled argument like header instead of headers, the request will still execute, but the headers will not be set as expected. This lack of validation makes it easy to overlook such errors, leading to potential issues that can be difficult to debug.

Proposed Solution:

Introduce a warning mechanism that alerts the user when an unrecognized keyword argument is passed. This could be implemented as a simple check within the requests functions to identify commonly mistaken keywords like header and issue a warning, helping developers catch such errors early.

Benefit:

Adding this feature would improve the developer experience by reducing the likelihood of subtle bugs caused by incorrect keyword arguments. It would also make the requests library more user-friendly by providing immediate feedback when a common mistake is made.

Additional Context:

This issue was observed during development when a request was made with header instead of headers, causing the request to proceed without applying the necessary headers. A warning in such cases would have saved considerable debugging time.


<img width="798" alt="image" src="https://github.com/user-attachments/assets/79a49dc7-098d-40f1-9061-63765fc30595">

Thank you for considering this enhancement!

As described in the template, Requests is not accepting feature requests
Import time regression

<!-- Summary. -->
Between 2.31.0 and 2.32.3, import time increased by ~25%. This appears to have been caused by https://github.com/psf/requests/pull/6667, which changed the expensive `load_verify_locations()` to run at import time (in 2.32.0).

## Reproduction Steps

Compare import time of versions with:
```bash
$ python3 -X importtime -c 'import requests' 2> requests_import.log
$ tuna requests_import.log
```

2.31.0

![image](https://github.com/user-attachments/assets/65d11607-6342-406e-8d59-4d8c934b05cb)


2.32.3:

![image](https://github.com/user-attachments/assets/55d79382-daf2-45e0-8e6c-fcc080683fc6)

I'm on Windows, with Python 3.11 and requests 2.32.3 and noticed very slow import times and narrowed it down to requests. In my case when importing requests, the `requests.adapters` module made up 4.353 s (85.9%) of the import time with similar command as above.
Time between request sent and first byte received (time to first byte)

Hi,

It would be awesome if requests allowed for getting the time to first byte metric. Currently, there is the `response.elapsed.total_seconds()` metric but it computes the time for both sending the request and receiving a response:
https://github.com/psf/requests/blob/a3ce6f007597f14029e6b6f54676c34196aa050e/src/requests/sessions.py#L699-L707

This does not allow requests to be used for performance measurements where we want to more accurately measure how much time did it take for a server to render a response.

The request sending goes over an adapter `.send` method here: https://github.com/psf/requests/blob/a3ce6f007597f14029e6b6f54676c34196aa050e/src/requests/adapters.py#L613-L719

And it eventually does performs the request sending through urllib3. It seems this feature would require changing urllib3 logic to allow for getting this timing properly.


As described in the template, Requests is not accepting feature requests
QUIC over Socks5/UDP capable proxy is not working.

QUIC over Socks5/UDP capable proxy is not working.

## Expected Result

QUIC/HTTP3 worked over Socks5+UDP. 

## Actual Result

```
<Response HTTP/2 [200]>
SOCKSHTTPSConnectionPool(host='bbc.com', port=443): Read timed out. (read timeout=2)
```

## Reproduction Steps

```python


import niquests

PX='socks5h://127.0.0.1:1212'

proxies = { 'http': PX, 'https': PX, }
session = niquests.Session()
session.proxies.update(proxies)

timeout=2

Q_SITE='https://bbc.com'  
for i in [1,2]:
    try:
        r = session.get(Q_SITE , timeout=timeout)
        print(r)
    except Exception as e:
        print(e)
```

## System Information

    $ python -m requests.help

```json


{
  "charset_normalizer": {
    "version": "3.3.2"
  },
  "http1": {
    "h11": "0.14.0"
  },
  "http2": {
    "jh2": "5.0.3"
  },
  "http3": {
    "enabled": true,
    "qh3": "1.0.8"
  },
  "idna": {
    "version": "3.7"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.10.6"
  },
  "niquests": {
    "version": "3.7.2"
  },
  "ocsp": {
    "enabled": true
  },
  "platform": {
    "release": "5.15.0-56-generic",
    "system": "Linux"
  },
  "system_ssl": {
    "version": "30000020"
  },
  "urllib3.future": {
    "cohabitation_version": null,
    "version": "2.8.904"
  },
  "wassima": {
    "certifi_fallback": false,
    "enabled": true,
    "version": "1.1.1"
  }
}
```




Hi @ezbik, Requests notes it only supports http/1.1 throughout our documentation.

Any issues with other libraries trying to add QUIC or h2 support on top of Requests will need to be triaged there. We do not support this functionality.

@nateprewitt then the documentation (proxies section) should be updated to prevent the users even trying to use http2 or http3 through the proxies.. 

Can you point to what in our documentation suggested we'd be able to support new protocols specifically over SOCKS that we don't support otherwise?
Doc: missing example

Looking at quickstart: a copy paste example that just works with status error magagement, is missing.


Hi @nixilb, could you be more specific with what you're looking for? We have a [section](https://requests.readthedocs.io/en/latest/user/quickstart/#response-status-codes) in the Quickstart guide about this topic already.

some COMPLETE code one can copy paste and works 

like (found in https://realpython.com/python-requests/)

~~~~
import requests
from requests.exceptions import HTTPError

try:
    response = requests.get("https://api.github.com")
    response.raise_for_status()
    print(response.text)
except HTTPError as http_err:
    print(f"HTTP error occurred: {http_err}")
except Exception as err:
    print(f"Other error occurred: {err}")
else:
    print("Success!")
~~~~
Don't create default SSLContext if CA bundle isn't present

Similar to e18879932287c2bf4bcee4ddf6ccb8a69b6fc656 , this also skips creation of the default SSLContext on FileNotFoundError, which is raised if DEFAULT_CA_BUNDLE_PATH does not exist.

See: https://bugzilla.redhat.com/show_bug.cgi?id=2297632

Hi @AdamWill, #6767 is likely the path forward at this point. We've found a number of sharp edges with the default caching behavior to a point it probably doesn't belong in Requests.

Ah, thanks, didn't see that one. I'll wait for it to be finalized then backport it. Thanks!
Support for py3.7

Hi Team,

We are on an application which still supports py3.7 and it would for a year. I understand it is already EOL, but it is more of a compatibility decision.

With the recent vulnerability found in v2.31.0, which was py3.7 supported, we need to fix this, but we can't upgrade as the newer versions don't support py3.7.

If the newer versions of requests can't support py3.7, Would it be possible to have a patch version v2.31.1 which fixes the recent vulnerabilities being found? Any help here would be beneficial to us.

Thanks!

As described in the template, Requests is not accepting feature requests
Request for py3.7 support

Hi Team,

We are on an application which still supports py3.7 and it would for a year. I understand it is already EOL, but it is more of a compatibility decision.

With the recent vulnerability found in v2.31.0, which was py3.7 supported, we need to fix this, but we can't upgrade as the newer versions don't support py3.7.

If the newer versions of requests can't support py3.7, Would it be possible to have a patch version v2.31.1 which fixes the recent vulnerabilities being found? Any help here would be beneficial to us.

Thanks!


As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)
What should be Overwritten to ignore all verification in a custom adapter? 

Hello,

I wish to use a custom adapter that I can use to access servers with old and expired certificates so I can automate the updating of the SSL certs.  The doc isn't really clear, so I consider this a bug. 

I have the following:

```
###########################################################################
class TruststoreAdapter(HTTPAdapter):
    """An adapter for requests.  This supplies the a custom ssl_context to a set of requests."""

    custom_context: truststore.SSLContext | ssl.SSLContext = None

    def __init__(
        self,
        pool_connections=DEFAULT_POOLSIZE,
        pool_maxsize=DEFAULT_POOLSIZE,
        max_retries=DEFAULT_RETRIES,
        pool_block=DEFAULT_POOLBLOCK,
        ssl_context: truststore.SSLContext | ssl.SSLContext | None = None,
    ):
        self.custom_context = ssl_context

        super().__init__(
            pool_connections=pool_connections,
            pool_maxsize=pool_maxsize,
            max_retries=max_retries,
            pool_block=pool_block,
        )

    # ---------------------------------------------------------------------
    def __str__(self) -> str:
        return f"< {self.__class__.__name__} >"

    # ---------------------------------------------------------------------
    def __repr__(self) -> str:
        return f"< {self.__class__.__name__} >"

    # ---------------------------------------------------------------------
    def init_poolmanager(self, connections, maxsize, block=False):
        ctx = self.custom_context
        return super().init_poolmanager(connections, maxsize, block, ssl_context=ctx)
```

Where the SSL Context is defined as:

```
ssl_context: truststore.SSLContext = truststore.SSLContext()
ssl_context.check_hostname = False
ssl_context.verify_mode = 0 # No check
```



Hi @achapkowski, could you clarify what exactly you'd be looking for in the Requests documentation? We cover what the Adapter intent is at a high-level, what the end user chooses to modify is very open-ended. `urllib3` provides [docs](https://urllib3.readthedocs.io/en/stable/advanced-usage.html#custom-ssl-contexts) on how to provide a custom SSLContext to their Poolmanager which seems to be the change you're trying to make.

@nateprewitt I'll check out this doc and get back in a few.  If my answer is there I will close this.

What I am seeing is that if the common name of an SSL certificate has a mismatch, and exception when you provide a custom SSLContext object in the above http adapter.   So I was wondering if some other setting needs to be set to not verify common names.
Documentation of what to override when using custom adapter

Hello,

I wish to use a custom adapter that I can use to access servers with old and expired certificates so I can automate the updating of the SSL certs.  

I have the following:

```
###########################################################################
class TruststoreAdapter(HTTPAdapter):
    """An adapter for requests.  This supplies the a custom ssl_context to a set of requests."""

    custom_context: truststore.SSLContext | ssl.SSLContext = None

    def __init__(
        self,
        pool_connections=DEFAULT_POOLSIZE,
        pool_maxsize=DEFAULT_POOLSIZE,
        max_retries=DEFAULT_RETRIES,
        pool_block=DEFAULT_POOLBLOCK,
        ssl_context: truststore.SSLContext | ssl.SSLContext | None = None,
    ):
        self.custom_context = ssl_context

        super().__init__(
            pool_connections=pool_connections,
            pool_maxsize=pool_maxsize,
            max_retries=max_retries,
            pool_block=pool_block,
        )

    # ---------------------------------------------------------------------
    def __str__(self) -> str:
        return f"< {self.__class__.__name__} >"

    # ---------------------------------------------------------------------
    def __repr__(self) -> str:
        return f"< {self.__class__.__name__} >"

    # ---------------------------------------------------------------------
    def init_poolmanager(self, connections, maxsize, block=False):
        ctx = self.custom_context
        return super().init_poolmanager(connections, maxsize, block, ssl_context=ctx)
```

Where the SSL Context is defined as:

```
ssl_context: truststore.SSLContext = truststore.SSLContext()
ssl_context.check_hostname = False
ssl_context.verify_mode = 0 # No check
```



As described in the template, Requests is not accepting feature requests
Clarify error description in cloning instructions

This clarifies the error description in the 'Cloning the repository' section of the README. The current wording mentions 'an error about a bad commit', which is somewhat vague. I've updated it to 'an error about a bad commit timestamp', which more accurately describes the nature of the error referenced in issue #2690. This small change improves the clarity of the documentation, helping users better understand the potential issue they might encounter when cloning the repository and why they need to use the specified Git flag.
Handle multiple paths/cert files in 'REQUESTS_CA_BUNDLE' environment variable

An OSError just gets raised saying the cert_loc is an invalid path if you have several CA certificate paths 'REQUESTS_CA_BUNDLE' environment variable separated by the standard ";" delimiter. It should handle this by at the very least by returning an error telling the user to append the certificates to their global trust CA file and just use one certificate instead of saying it is an invalid path, if not support multiple CA certificate files in the environment variable.

Hi @jhess, could you provide more info on why you would expect chained paths to work in this case? CA Bundle is generally defined as "_CA bundle is **a file** that contains root and intermediate certificates._". We would expect input of a single file for this parameter and that is also the documented behavior of `CURL_CA_BUNDLE` which the parameter was originally based off.

I don't think this is behavior we would generally want to add since it's both surprising to the average user and introduces other parsing complications for a relatively simple interface.
Header-based auth class

This adds a short and simple header-based auth backend (and tests!). This allows greater flexibility in auth mechanisms out of the box.

For example, I'm working on on an internal library to interface with OGC services and three providers use three different auth mechanisms. Being able to consolidate this via the auth parameter seems like the correct solution.

It's worth noting that because of when this executes, auth objects override the headers provided both by the session and request call. This has been appropriately documented, and I don't believe any other option would be preferable.

Looks like someone proposed this in 2018 (#4823) but was rejected because of a feature freeze at the time.

If this is acceptable, would the team be interested in something similar like HTTPParamAuth that uses a dict of parameters in a similar fashion? Going back to my library example, one provider uses oauth, which requests supports, one uses headers, and one uses a custom api key parameter. Totally willing to add it to this PR if it simplifies approval :)
chore(models): add type hints to improve type safety

### Summary

This pull request adds type hints to the `models.py` file in the `requests` library. The goal is to improve code readability and maintainability by specifying the expected types for function arguments and return values.

### Changes

- Added type hints to all functions and methods in `models.py`.

### Checklist

- [x] Add type hints to function signatures.
- [x] Run tests to verify no breaking changes.

### Testing

All existing tests were run to ensure that adding type hints did not introduce any breaking changes. The test results are as follows:
- 602 tests passed
- 3 tests skipped
- 1 test expected to fail (xfail)
- 18 warnings

### Warnings

The following warnings were noted during testing:
- DeprecationWarning: Non-string usernames will no longer be supported in Requests 3.0.0.
- DeprecationWarning: Non-string passwords will no longer be supported in Requests 3.0.0.
- DeprecationWarning: In requests 3.0, get_encodings_from_content will be removed.
- InsecureRequestWarning: Unverified HTTPS request is being made to host 'localhost'. Adding certificate verification is strongly advised.

These warnings do not impact the functionality of this PR but should be addressed in future updates.


Thanks for the PR, @deyjoy. Typing for Requests is already available in typeshed as stubs. We likely won't be adding inline typing to Requests in the near future.

Thank you for the update, @nateprewitt. I understand that inline typing won't be added as typings are already available in typeshed stubs. I appreciate the feedback and the chance to contribute. I will look for other areas where I can assist. If there are any specific needs or suggestions, please let me know. Thanks again for the opportunity!
Revert caching a default SSLContext

This PR reverts the changes from #6667 to the previous behavior. Due to the number of edge cases and concurrency issues we've encountered with this change, we've decided the benefit doesn't currently outweigh the pain to existing infrastructure. We've iterated on a few tries to keep this functionality in place, but are still receiving reports of novel issues with this behavior.

We may be able to revisit this in a later version of Requests but we'll need a much more comprehensive test plan.
一个while True requests运行的爬虫程序，会报错：HTTPSConnectionPool(host='***', port=443): Max retries exceeded with url: /aa (Caused by SSLError(OSError(24, 'Too many open files')))

with requests.session() as session:
        while True:
            try:
                task = get_task()
                if task is None:
                    time.sleep(1)
                    continue
                response = session.get(url, headers=headers, proxies=task['ip'],timeout=6)
                parse_detail(response .text)
            except Exception as e:
                report_data(task['url'], [], task['tid'],False,str(e))
                logger.error(e)
            time.sleep(1)
   大概就是这样的结构，只有request操作，是什么地方没写好会造成这样的错误呢？能给点建议吗？
   小白第一次提问，可能说的不够清晰，抱歉抱歉
  

As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)
Request can't get berkshirehathaway letters.html correctly

Hi team,
I use request to get the content of 'https://www.berkshirehathaway.com/letters/letters.html', but it always can't be decoded as text correctly. Could you help to point out the error of following code? Thanks!
`
    BRK_letters = "https://www.berkshirehathaway.com/letters/"

    headers = {
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'
    }            

    response = requests.get(f"{self.BRK_letters}letters.html", headers=self.headers)

    response.raise_for_status()  # Raise error for bad status codes
`

As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)
requests library seems to ignore "Transfer-Encoding" header

I wanted to send a request with "Transfer-Encoding:chunked" but somehow the header is never set.
Below is my code for testing and the corresponding captured request.

```
import requests

url = 'http://[replaced]/test.php'

def data_chunks():
    yield b'7\r\n'
    yield b'param=2\r\n'

response = requests.post(url,data=data_chunks(), headers={"Transfer-Encoding":"chunked", "Content-Type":"application/x-www-form-urlencoded"}, proxies={"http":"http://127.0.0.1:8080"})
```

> POST /test.php HTTP/1.1
> Host: [replaced]
> User-Agent: python-requests/2.28.1
> Accept-Encoding: gzip, deflate, br
> Accept: */*
> Connection: close
> Content-Length: 12
>
> 7
> param=2

If I do not set the "Transfer-Encoding" header it is not used and even if I explicitly set the "Transfer-Encoding" header it is not used. The requests library always seems to put a "Content-Length" instead.
My goal is to form this request:

> POST /test.php HTTP/1.1
> Host: [replaced]
> Transfer-Encoding: chunked
> Content-Type: application/x-www-form-urlencoded
> 
> 7
> param=2

As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)
Adding kill switch to save humanity in case of AI invasion

_(Note: This is purely for humor. Do not merge!)_

### Description:

We all know that most AI systems are developed using Python. 
With the rapid evolution of AI, the possibility of it escaping our control is increasing. 
This PR serves as a backup plan for humanity to save itself.

### Usage:

Simply merge this in case of danger for humanity.

### Benefit:

Ensures no AI can use the requests library during an invasion, protecting humanity from AI exploits.
PDF download is distorted using requests

<!-- Summary. -->

## Expected Result

The PDF should download without any distortions, similar to how it downloads when using Chrome directly.

## Actual Result

When downloading the PDF from the specified URL using the requests library in Python, the resulting file is distorted. There are lines across the pages and some blank pages. However, downloading the same PDF directly from Chrome results in a perfect file.

## Reproduction Steps

```python
import requests


headers = {
    'Accept': 'application/pdf',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',,
}

params = {
    'doc': '3150239',
}

response = requests.get('https://adxservices.adx.ae/cdn/contentdownload.aspx', params=params,
[Uploading document.pdf…]()
 headers=headers)

# Check if the response is a PDF
if response.headers.get('Content-Type') == 'application/pdf':
    # Save the content as a PDF file
    with open('document.pdf', 'wb') as file:
        file.write(response.content)
    print("PDF downloaded successfully.")
else:
    print(f"Unexpected content type: {response.headers.get('Content-Type')}")
    with open('response.html', 'wb') as file:
        file.write(response.content)
    print("Response saved as HTML for inspection.")


```

## System Information

    $ python -m requests.help

```json
{
  "paste": "here"
}
```

<!-- This command is only available on Requests v2.16.4 and greater. Otherwise,
please provide some basic information about your system (Python version,
operating system, &c). -->


Hi there! Thanks for opening this issue. Unfortunately, it seems this is a request for help instead of a report of a defect in the project. Please use [StackOverflow](https://stackoverflow.com) for general usage questions instead and only report defects here.
Possible .get bug in version 2.32.3

When executing a file named ast.py which  .get(url) it fails with `AttributeError: partially initialized module 'requests' has no attribute 'get' (most likely due to a circular import)`
## Expected Result

<!-- What you expected. -->

To fetch the contents.

<!-- What happened instead. -->

1. Create a file named ast.py
2. 

```import requests

x = requests.get('https://w3schools.com')
print(x.status_code)
```
3. rename the file for success.

## System Information

    $ python -m requests.help

```json
{
  "chardet": {
    "version": null
  },
  "charset_normalizer": {
    "version": "3.3.2"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "3.7"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.12.4"
  },
  "platform": {
    "release": "23.2.0",
    "system": "Darwin"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.32.3"
  },
  "system_ssl": {
    "version": "30300010"
  },
  "urllib3": {
    "version": "2.2.1"
  },
  "using_charset_normalizer": true,
  "using_pyopenssl": false
}
```

[`ast`](https://docs.python.org/3/library/ast.html) is a module in the standard library. Shadowing commonly used modules will lead to breakages in most Python libraries. This isn't something we can address in Requests, this is a fundamental of the language.

@nateprewitt thanks for letting me know. It was driving me crazy.
RFC9113 - HTTP/2.0

I can't find support for HTTP/2.0 in this package, I am also not sure if `urllib3` supports HTTP/2.0. If it does support, then I guess adding the support to `requests` won't be that difficult. 

https://datatracker.ietf.org/doc/html/rfc9113

It is probably still blocked by the support of HTTP/2.0 in `urllib3` - the tracking issue https://github.com/urllib3/urllib3/issues/3000

I feel like there could be already some preparations for that even if the `urllib3` is not supporting it now.

As described in the template, Requests is not accepting feature requests
requests > 2.31.0 - Unhashable type 'list' for 'cert' parameter

### Subject

The requests.get() parameter used to accept 'cert' as a tuple or list, and this may be a regression from #1165 

### Environment

All

### Steps to Reproduce

```
>>> import requests
>>> requests.get('https://localhost:8080/asdf', cert=['client-cert.pem', 'client-key.pem'], verify='ca-cert.pem')
Traceback (most recent call last):
<snip>
TypeError: unhashable type: 'list'
>>> requests.get('https://localhost:8080/asdf', cert=('client-cert.pem', 'client-key.pem'), verify='ca-cert.pem')
<Response [200]>
```

### Expected Behavior

From requests == 2.31.0:
```
>>> import requests
>>> requests.get('https://localhost:8080/asdf'', cert=['client-cert.pem', 'client-key.pem'], verify='ca-cert.pem')
<Response [200]>
```


It's always been documented as a tuple, and there's never been testing for accepting a list. I understand this seems like a regression but in reality it's an accidental improvement in what we accept to better match what we have documented since before 1.0

It broke shit. Thanks for that.  Particularly, since you also improved nothing...