internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: encode/uvicorn

Issue:
--proxy-headers with supervisor get client ip failed
#### uvicorn version
`Running uvicorn 0.11.3 with CPython 3.8.2 on Linux` 
#### supervisor config
```
[fcgi-program:uvicorn]
socket=tcp://0.0.0.0:5000    
directory=/var/www/webapp/    
command=/usr/local/python3/bin/uvicorn --fd 0 --proxy-headers main:app    
numprocs=2    
process_name=uvicorn-%(process_num)d    
stdout_logfile_maxbytes=0    
stdout_logfile=/var/log/uvicorn.log    
```

### fastapi 
version 0.52.0

```
# cat /var/www/webapp/main.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from fastapi import FastAPI, Request

app = FastAPI(redoc_url=None)


@app.get('/')
def index(request: Request):
    return 'hello {}!'.format(request.client.host)

```

### run on supervisor
supervisord version 4.1.0
```
supervisord -n
curl  http://127.0.0.1:5000

```
why client.host is None?



Discussion:

Resolving patch:
diff --git a/uvicorn/protocols/utils.py b/uvicorn/protocols/utils.py
--- a/uvicorn/protocols/utils.py
+++ b/uvicorn/protocols/utils.py
@@ -1,5 +1,10 @@
 import socket
 
+if hasattr(socket, "AF_UNIX"):
+    SUPPORTED_SOCKET_FAMILIES = (socket.AF_INET, socket.AF_INET6, socket.AF_UNIX)
+else:
+    SUPPORTED_SOCKET_FAMILIES = (socket.AF_INET, socket.AF_INET6)
+
 
 def get_remote_addr(transport):
     socket_info = transport.get_extra_info("socket")
@@ -14,8 +19,9 @@ def get_remote_addr(transport):
         else:
             family = socket_info.family
 
-        if family in (socket.AF_INET, socket.AF_INET6):
+        if family in SUPPORTED_SOCKET_FAMILIES:
             return (str(info[0]), int(info[1]))
+
         return None
     info = transport.get_extra_info("peername")
     if info is not None and isinstance(info, (list, tuple)) and len(info) == 2:
@@ -28,7 +34,7 @@ def get_local_addr(transport):
     if socket_info is not None:
         info = socket_info.getsockname()
         family = socket_info.family
-        if family in (socket.AF_INET, socket.AF_INET6):
+        if family in SUPPORTED_SOCKET_FAMILIES:
             return (str(info[0]), int(info[1]))
         return None
     info = transport.get_extra_info("sockname")


Test patch:
Repository: encode/uvicorn

Issue:
Reload Behavior: Documentation != Code, Unnecessary Reloads
Hey! I upgraded to 0.11.4 shortly after release today, and it has a couple of quirks.

1. The documentation [here](https://github.com/encode/uvicorn/compare/0.11.3...0.11.4#diff-1819b1daaccb3d358620ade9c67e9118R22) says "python file changes" but the code says ["all non-dotfile changes"](https://github.com/encode/uvicorn/compare/0.11.3...0.11.4#diff-b0da863c7164698a2ef0fa805e4a9197R40).
2. That behavior, while from the test cases seems to be intended to roll up things like `.graphql` files, also unfortunately rolls up `.pyc` files, meaning every restart is a double restart:

```
WARNING:  Detected file change in 'app/main.py'. Reloading...
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [87024]
INFO:     Started server process [87080]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
WARNING:  Detected file change in 'app/__pycache__/main.cpython-37.pyc'. Reloading...
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [87080]
INFO:     Started server process [87093]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
```

It might be better to use [Path.glob](https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob) so users can specify file extensions and paths more explicitly than with `os.walk`, but it's published already so maybe as another flag?

3. A minor point, but worth noting in the docs: `--reload_dir` on the CLI becomes `reload_dirs=['my_dir']` in code: `uvicorn.run('app.main:app', host="0.0.0.0", port=8000, reload=True, reload_dirs=['app'])`

Thanks for making this great library!


Discussion:
Can you please paste the output just above what you pasted just to see what reloader it uses? 
ok it's on statreloader, will send a PR asap

Resolving patch:
diff --git a/uvicorn/__init__.py b/uvicorn/__init__.py
--- a/uvicorn/__init__.py
+++ b/uvicorn/__init__.py
@@ -1,5 +1,5 @@
 from uvicorn.config import Config
 from uvicorn.main import Server, main, run
 
-__version__ = "0.11.4"
+__version__ = "0.11.5"
 __all__ = ["main", "run", "Config", "Server"]


Test patch:
Repository: encode/uvicorn

Issue:
color codes in windows console not escaped
Fixes https://github.com/tiangolo/fastapi/issues/815 that should have been reported upstream

There are many ways to handle the case obviously, I choose to use click.clear() since we use already click.style and because it already performs the os check and issues the right command for that.


Use optional package installs.
Instead of the platform detection I’d like uvicorn to use optional installs.

* `pip install uvicorn` - Just the package itself.
* `pip install uvicorn[standard]` - uvloop/httptools/websockets
* `pip install uvicorn[pure]` - asyncio/h11/wsproto
* `pip install uvicorn[full]` - Everything


Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -34,21 +34,28 @@ def get_packages(package):
     ]
 
 
-env_marker = (
+env_marker_cpython = (
     "sys_platform != 'win32'"
     " and sys_platform != 'cygwin'"
     " and platform_python_implementation != 'PyPy'"
 )
 
-requirements = [
+env_marker_win = "sys_platform == 'win32'"
+
+
+minimal_requirements = [
     "click==7.*",
     "h11>=0.8,<0.10",
-    "websockets==8.*",
-    "httptools==0.1.* ;" + env_marker,
-    "uvloop>=0.14.0 ;" + env_marker,
 ]
 
-extras_require = {"watchgodreload": ["watchgod>=0.6,<0.7"]}
+extra_requirements = [
+    "websockets==8.*",
+    "httptools==0.1.* ;" + env_marker_cpython,
+    "uvloop>=0.14.0 ;" + env_marker_cpython,
+    "colorama>=0.4.*;" + env_marker_win,
+    "watchgod>=0.6,<0.7",
+    "python-dotenv==0.13.*",
+]
 
 
 setup(
@@ -62,8 +69,8 @@ def get_packages(package):
     author="Tom Christie",
     author_email="tom@tomchristie.com",
     packages=get_packages("uvicorn"),
-    install_requires=requirements,
-    extras_require=extras_require,
+    install_requires=minimal_requirements,
+    extras_require={"standard": extra_requirements},
     include_package_data=True,
     classifiers=[
         "Development Status :: 4 - Beta",


Test patch:
Repository: encode/uvicorn

Issue:
CVE-2020-7694 ANSI escape sequence injection
Looks like there is a [critical](https://vuldb.com/?id.159010) [security issue in "all versions" of uvicorn](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7694).

I presume there is a typo in the original CVE description, so "ASNI" should be "ANSI".


Discussion:

Resolving patch:
diff --git a/uvicorn/logging.py b/uvicorn/logging.py
--- a/uvicorn/logging.py
+++ b/uvicorn/logging.py
@@ -1,6 +1,7 @@
 import http
 import logging
 import sys
+import urllib
 from copy import copy
 
 import click
@@ -77,14 +78,14 @@ def get_client_addr(self, scope):
         return "%s:%d" % (client[0], client[1])
 
     def get_path(self, scope):
-        return scope.get("root_path", "") + scope["path"]
+        return urllib.parse.quote(scope.get("root_path", "") + scope["path"])
 
     def get_full_path(self, scope):
         path = scope.get("root_path", "") + scope["path"]
         query_string = scope.get("query_string", b"").decode("ascii")
         if query_string:
-            return path + "?" + query_string
-        return path
+            return urllib.parse.quote(path) + "?" + query_string
+        return urllib.parse.quote(path)
 
     def get_status_code(self, record):
         status_code = record.__dict__["status_code"]
diff --git a/uvicorn/protocols/utils.py b/uvicorn/protocols/utils.py
--- a/uvicorn/protocols/utils.py
+++ b/uvicorn/protocols/utils.py
@@ -1,4 +1,5 @@
 import socket
+import urllib
 
 
 def get_remote_addr(transport):
@@ -49,7 +50,9 @@ def get_client_addr(scope):
 
 
 def get_path_with_query_string(scope):
-    path_with_query_string = scope.get("root_path", "") + scope["path"]
+    path_with_query_string = urllib.parse.quote(
+        scope.get("root_path", "") + scope["path"]
+    )
     if scope["query_string"]:
         path_with_query_string = "{}?{}".format(
             path_with_query_string, scope["query_string"].decode("ascii")


Test patch:
Repository: encode/uvicorn

Issue:
HTTP response splitting vulnerability
See https://app.snyk.io/vuln/SNYK-PYTHON-UVICORN-570471



Discussion:
Heya, so it looks like this needs to be resolved in `httptools`, right?
@tomchristie if that question is directed at me... honestly I have no idea.
Just a dumb client using the library with no time to dig under the hood... :-)
Hey @tomchristie, what part of the uvicorn deals with parsing http headers? could be a `httptools` problem.  i believe it would be a case of adding some extra validation to check for `%0d`(CR),`%0a`(LF) characters. Maybe the below commits from similar issues would help

- [CVE-2018-1000164](https://github.com/fofanov/gunicorn/commit/6c3d8f9c205f541a6ae0a1d5eba32b1cfca252ee)

- [https://snyk.io/vuln/SNYK-PYTHON-WAITRESS-564339](https://github.com/Pylons/waitress/commit/4deab9f23f9eb273971da247981aa85b7a16e946)
Yup first step is double checking if it's *directly* in `httptools` that this needs addressing. (Looks like it but I've not dived into it.)

Really this ought to be getting dealt with privatly, but that's my bad, Snyk did notify me about this via email, but I've been too over-committed with everything to have dug into it yet.

Resolving patch:
diff --git a/uvicorn/protocols/http/httptools_impl.py b/uvicorn/protocols/http/httptools_impl.py
--- a/uvicorn/protocols/http/httptools_impl.py
+++ b/uvicorn/protocols/http/httptools_impl.py
@@ -1,6 +1,7 @@
 import asyncio
 import http
 import logging
+import re
 import urllib
 
 import httptools
@@ -13,6 +14,9 @@
     is_ssl,
 )
 
+HEADER_RE = re.compile(b'[\x00-\x1F\x7F()<>@,;:[]={} \t\\"]')
+HEADER_VALUE_RE = re.compile(b"[\x00-\x1F\x7F]")
+
 
 def _get_status_line(status_code):
     try:
@@ -459,6 +463,11 @@ async def send(self, message):
             content = [STATUS_LINE[status_code]]
 
             for name, value in headers:
+                if HEADER_RE.search(name):
+                    raise RuntimeError("Invalid HTTP header name.")
+                if HEADER_VALUE_RE.search(value):
+                    raise RuntimeError("Invalid HTTP header value.")
+
                 name = name.lower()
                 if name == b"content-length" and self.chunked_encoding is None:
                     self.expected_content_length = int(value.decode())


Test patch:
Repository: encode/uvicorn

Issue:
Lifespan scope is missing asgi dict
the lifespan scope (https://asgi.readthedocs.io/en/latest/specs/lifespan.html#scope) is missing the asgi dict

prompted by

_Originally posted by @florimondmanca in https://github.com/encode/uvicorn/pull/751_


Discussion:

Resolving patch:
diff --git a/uvicorn/lifespan/on.py b/uvicorn/lifespan/on.py
--- a/uvicorn/lifespan/on.py
+++ b/uvicorn/lifespan/on.py
@@ -44,7 +44,10 @@ async def shutdown(self):
     async def main(self):
         try:
             app = self.config.loaded_app
-            scope = {"type": "lifespan"}
+            scope = {
+                "type": "lifespan",
+                "asgi": {"version": self.config.asgi_version, "spec_version": "2.0"},
+            }
             await app(scope, self.receive, self.send)
         except BaseException as exc:
             self.asgi = None


Test patch:
diff --git a/tests/test_lifespan.py b/tests/test_lifespan.py
--- a/tests/test_lifespan.py
+++ b/tests/test_lifespan.py
@@ -144,3 +144,40 @@ async def test():
 
     loop = asyncio.new_event_loop()
     loop.run_until_complete(test())
+
+
+@pytest.mark.parametrize("mode", ("auto", "on"))
+def test_lifespan_scope_asgi3app(mode):
+    async def asgi3app(scope, receive, send):
+        assert scope == {"version": "3.0", "spec_version": "2.0"}
+
+    async def test():
+        config = Config(app=asgi3app, lifespan=mode)
+        lifespan = LifespanOn(config)
+
+        await lifespan.startup()
+        await lifespan.shutdown()
+
+    loop = asyncio.new_event_loop()
+    loop.run_until_complete(test())
+
+
+@pytest.mark.parametrize("mode", ("auto", "on"))
+def test_lifespan_scope_asgi2app(mode):
+    def asgi2app(scope):
+        assert scope == {"version": "2.0", "spec_version": "2.0"}
+
+        async def asgi(receive, send):
+            pass
+
+        return asgi
+
+    async def test():
+        config = Config(app=asgi2app, lifespan=mode)
+        lifespan = LifespanOn(config)
+
+        await lifespan.startup()
+        await lifespan.shutdown()
+
+    loop = asyncio.new_event_loop()
+    loop.run_until_complete(test())
Repository: encode/uvicorn

Issue:
Websockets implementation does not clean properly tasks if handshake fails
this is a good explanation of what we see in those 2 tests and that causes flaky tests:


FWIW there's an asyncio warning when I try to run `test_send_before_handshake` or `test_missing_handshake` in isolation. Doesn't show if I run either along with other tests, eg either the full test suite, with `-k websocket`, or the two tests together with `-k "missing_handshake or before_handshake"`.

```console
$ pytest -k test_missing_handshake
====================================================== test session starts =======================================================
platform darwin -- Python 3.9.0, pytest-6.1.1, py-1.9.0, pluggy-0.13.1
rootdir: /Users/florimond/Developer/python-projects/uvicorn, configfile: setup.cfg
plugins: mock-3.3.1, asyncio-0.14.0
collected 213 items / 211 deselected / 2 selected                                                                                

tests/protocols/test_websocket.py ..                                                                                       [100%]

=============================================== 2 passed, 211 deselected in 2.30s ================================================
Task was destroyed but it is pending!
task: <Task pending name='Task-11' coro=<WebSocketServerProtocol.handler() done, defined at /Users/florimond/Developer/python-projects/uvicorn/venv/lib/python3.9/site-packages/websockets/server.py:118> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10a7e1760>()]>>
```

_Originally posted by @florimondmanca in https://github.com/encode/uvicorn/issues/918#issuecomment-751691297_


Discussion:

Resolving patch:
diff --git a/uvicorn/protocols/websockets/websockets_impl.py b/uvicorn/protocols/websockets/websockets_impl.py
--- a/uvicorn/protocols/websockets/websockets_impl.py
+++ b/uvicorn/protocols/websockets/websockets_impl.py
@@ -135,6 +135,9 @@ def send_500_response(self):
             msg,
         ]
         self.transport.write(b"".join(content))
+        # Allow handler task to terminate cleanly, as websockets doesn't cancel it by
+        # itself (see https://github.com/encode/uvicorn/issues/920)
+        self.handshake_started_event.set()
 
     async def ws_handler(self, protocol, path):
         """


Test patch:
Repository: encode/uvicorn

Issue:
Docs: workers = 1 when WEB_CONCURRENCY is not set
Hello, thanks for this great ASGI server 🙂 

I have an application that must use only one worker (it's not thread-safe), and so I wanted to confirm that, by default, uvicorn only uses one worker. But I had to read the source code

https://github.com/encode/uvicorn/blob/afb2d565c8dae859bcef4c76b3c6dc3f3077314d/uvicorn/config.py#L177

...to confirm that when `WEB_CONCURRENCY` is not defined, and `workers` is not specified, 1 is used.

Would you accept a PR adding that information to the docs (there are 4-5 places where this can be added)?


Discussion:

> I have an application that must use only one worker (it's not thread-safe), and so I wanted to confirm that, by default, uvicorn only uses one worker. But I had to read the source code

`workers` set the number of processes not threads, just to be clear

> ...to confirm that when `WEB_CONCURENCY` is not defined, and `workers` is not specified, 1 is used.
> 
> Would you accept a PR adding that information to the docs (there are 4-5 places where this can be added)?

sure why not, I edited your title to put 2 Rs though, easier to find


Thanks!

> workers set the number of processes not threads, just to be clear

Oh yes, I used "thread-safe" because I'm not sure there's a "process-safe" term? 😅 

OK I'll try to send a PR soon 🙂 
seems like there is :_)

Queues are thread and process safe.


in https://docs.python.org/3/library/multiprocessing.html#exchanging-objects-between-processes


On Thu, Jan 21, 2021 at 3:06 PM Timothée Mazzucotelli
<notifications@github.com> wrote:
>
> Thanks!
>
> workers set the number of processes not threads, just to be clear
>
> Oh yes, I used "thread-safe" because I'm not sure there's a "process-safe" term?
>
> OK I'll try to send a PR soon
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub, or unsubscribe.



-- 
benoit barthelet
http://pgp.mit.edu/pks/lookup?op=get&search=0xF150E01A72F6D2EE


Resolving patch:
diff --git a/uvicorn/main.py b/uvicorn/main.py
--- a/uvicorn/main.py
+++ b/uvicorn/main.py
@@ -90,7 +90,7 @@ def print_version(ctx, param, value):
     default=None,
     type=int,
     help="Number of worker processes. Defaults to the $WEB_CONCURRENCY environment"
-    " variable if available. Not valid with --reload.",
+    " variable if available, or 1. Not valid with --reload.",
 )
 @click.option(
     "--loop",


Test patch:
Repository: encode/uvicorn

Issue:
improve user experience by complaining when reload_dirs is given a string instead of a list

Passing a string to reload_dirs as in the following, causes reload to silently not work :

```
    uvicorn.run(
        "dp.server:app",
        host="127.0.0.1", port=5000,
        log_level="info",
        reload=True,
        reload_dirs="/home/maxou/dev/proj",
        reload_delay=2.0
    )
```

Giving reload_dirs an array : ["/home/maxou/dev/proj"]  fixes the problem


It's not really a bug, but complaining with an error message would improve the user experience.



Discussion:
definitely something that could be improved and that would have been detected by mypy I think.

Resolving patch:
diff --git a/uvicorn/config.py b/uvicorn/config.py
--- a/uvicorn/config.py
+++ b/uvicorn/config.py
@@ -200,7 +200,10 @@ def __init__(
         if reload_dirs is None:
             self.reload_dirs = [os.getcwd()]
         else:
-            self.reload_dirs = reload_dirs
+            if isinstance(reload_dirs, str):
+                self.reload_dirs = [reload_dirs]
+            else:
+                self.reload_dirs = reload_dirs
 
         if env_file is not None:
             from dotenv import load_dotenv


Test patch:
diff --git a/tests/test_config.py b/tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -63,6 +63,11 @@ def test_config_should_reload_is_set(app, expected_should_reload):
     assert config_reload.should_reload is expected_should_reload
 
 
+def test_reload_dir_is_set():
+    config = Config(app=asgi_app, reload=True, reload_dirs="reload_me")
+    assert config.reload_dirs == ["reload_me"]
+
+
 def test_wsgi_app():
     config = Config(app=wsgi_app, interface="wsgi", proxy_headers=False)
     config.load()
Repository: encode/uvicorn

Issue:
Missing user feedback if no ws-library has been installed - with httptools installed
### Checklist

- [X] The bug is reproducible against the latest release and/or `master`.
- [X] There are no similar issues or pull requests to fix it yet.

### Describe the bug

#797 still persists with `httptools` installed in the environment.

### To reproduce

1. ```pip install uvicorn httptools fastapi```
2. Create a simple app
```python
from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    ...
``` 
3. Open a web-socket connection.
```js
new WebSocket(`ws://localhost:8000/ws`)
```

### Expected behavior

Proper user feedback if no ws-supported library has been installed.

### Actual behavior

```
INFO:     Started server process [19637]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
WARNING:  Unsupported upgrade request.
^C
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [19637]
```

### Environment

- Running uvicorn (master) with CPython 3.9.0 on Linux
- `uvicorn main:app`

```
fastapi==0.63.0
h11==0.12.0
httptools==0.2.0
```

### Additional context
#926 Fixes #797 for `h11`


Discussion:

Resolving patch:
diff --git a/uvicorn/protocols/http/httptools_impl.py b/uvicorn/protocols/http/httptools_impl.py
--- a/uvicorn/protocols/http/httptools_impl.py
+++ b/uvicorn/protocols/http/httptools_impl.py
@@ -181,6 +181,13 @@ def handle_upgrade(self):
         if upgrade_value != b"websocket" or self.ws_protocol_class is None:
             msg = "Unsupported upgrade request."
             self.logger.warning(msg)
+
+            from uvicorn.protocols.websockets.auto import AutoWebSocketsProtocol
+
+            if AutoWebSocketsProtocol is None:
+                msg = "No supported WebSocket library detected. Please use 'pip install uvicorn[standard]', or install 'websockets' or 'wsproto' manually."  # noqa: E501
+                self.logger.warning(msg)
+
             content = [STATUS_LINE[400]]
             for name, value in self.default_headers:
                 content.extend([name, b": ", value, b"\r\n"])


Test patch:
Repository: encode/uvicorn

Issue:
typo in `--reload-dir` is passed silently (watchgod)
### Checklist

### Describe the bug
if I supply a directory to `--reload-dir` which does not exist, the server starts.

```
./bin/uvicorn --host localhost --port 8000 --reload  --reload-dir asdfasfsrc foo.asgi:application
INFO:     Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [123571] using watchgod
INFO:     Started server process [123573]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
```
```
./bin/uvicorn  --version
Running uvicorn 0.13.4 with CPython 3.8.5 on Linux
```

### Expected behavior

I want the server to not start, if the reload-dir does not exist.

### Actual behavior

The server starts.




Discussion:
Why is it an issue for you ? iirc we don't add that unexisting directory to watched ones so there's no perf penalty or stuff that is looked at unnecessarily.
@euri10 not starting with an error message gives a better user (developer) experience !

Resolving patch:
diff --git a/uvicorn/main.py b/uvicorn/main.py
--- a/uvicorn/main.py
+++ b/uvicorn/main.py
@@ -77,6 +77,7 @@ def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> No
     multiple=True,
     help="Set reload directories explicitly, instead of using the current working"
     " directory.",
+    type=click.Path(exists=True),
 )
 @click.option(
     "--reload-delay",


Test patch: