Socket binding implemented properly for IPv6 and UNIX sockets. (#1641)

* Socket binding implemented properly for IPv6 and UNIX sockets.

- app.run("::1") for IPv6
- app.run("unix:/tmp/server.sock") for UNIX sockets
- app.run("localhost") retains old functionality (randomly either IPv4 or IPv6)

Do note that IPv6 and UNIX sockets are not fully supported by other Sanic facilities.
In particular, request.server_name and request.server_port are currently unreliable.

* Fix Windows compatibility by not referring to socket.AF_UNIX unless needed.

* Compatibility fix.

* Fix test of existing unix socket.

* Cleaner unix socket removal.

* Remove unix socket on exit also with workers=1.

* More pedantic UNIX socket implementation.

* Refactor app to take unix= argument instead of unix:-prefixed host. Goin' fast @ unix-socket fixed.

* Linter

* Proxy properties cleanup. Slight changes of semantics. SERVER_NAME now overrides everything.

* Have server fill in connection info instead of request asking the socket.

- Would be a good idea to remove request.transport entirely but I didn't dare to touch it yet.

* Linter 💣🌟💀

* Fix typing issues. request.server_name returns empty string if host header is missing.

* Fix tests

* Tests were failing, fix connection info.

* Linter nazi says you need that empty line.

* Rename a to addr, leave client empty for unix sockets.

* Add --unix support when sanic is run as module.

* Remove remove_route, deprecated in 19.6.

* Improved unix socket binding.

* More robust creating and unlinking of sockets. Show proper and not temporary name in conn_info.

* Add comprehensive tests for unix socket mode.

* Hide some imports inside functions to avoid Windows failure.

* Mention unix socket mode in deployment docs.

* Fix merge commit.

* Make test_unix_connection_multiple_workers pickleable for spawn mode multiprocessing.

Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
Co-authored-by: Adam Hopkins <admhpkns@gmail.com>
This commit is contained in:
L. Kärkkäinen
2020-06-29 08:55:32 +03:00
committed by GitHub
parent 4aba74d050
commit a62c84a954
9 changed files with 504 additions and 101 deletions

View File

@@ -454,11 +454,13 @@ def test_standard_forwarded(app):
"X-Real-IP": "127.0.0.2",
"X-Forwarded-For": "127.0.1.1",
"X-Scheme": "ws",
"Host": "local.site",
}
request, response = app.test_client.get("/", headers=headers)
assert response.json == {"for": "127.0.0.2", "proto": "ws"}
assert request.remote_addr == "127.0.0.2"
assert request.scheme == "ws"
assert request.server_name == "local.site"
assert request.server_port == 80
app.config.FORWARDED_SECRET = "mySecret"
@@ -1807,13 +1809,17 @@ def test_request_port(app):
port = request.port
assert isinstance(port, int)
delattr(request, "_socket")
delattr(request, "_port")
@pytest.mark.asyncio
async def test_request_port_asgi(app):
@app.get("/")
def handler(request):
return text("OK")
request, response = await app.asgi_client.get("/")
port = request.port
assert isinstance(port, int)
assert hasattr(request, "_socket")
assert hasattr(request, "_port")
def test_request_socket(app):
@@ -1832,12 +1838,6 @@ def test_request_socket(app):
assert ip == request.ip
assert port == request.port
delattr(request, "_socket")
socket = request.socket
assert isinstance(socket, tuple)
assert hasattr(request, "_socket")
def test_request_server_name(app):
@app.get("/")
@@ -1866,7 +1866,7 @@ def test_request_server_name_in_host_header(app):
request, response = app.test_client.get(
"/", headers={"Host": "mal_formed"}
)
assert request.server_name == None # For now (later maybe 127.0.0.1)
assert request.server_name == ""
def test_request_server_name_forwarded(app):
@@ -1893,7 +1893,7 @@ def test_request_server_port(app):
test_client = SanicTestClient(app)
request, response = test_client.get("/", headers={"Host": "my-server"})
assert request.server_port == test_client.port
assert request.server_port == 80
def test_request_server_port_in_host_header(app):
@@ -1952,12 +1952,12 @@ def test_server_name_and_url_for(app):
def handler(request):
return text("ok")
app.config.SERVER_NAME = "my-server"
app.config.SERVER_NAME = "my-server" # This means default port
assert app.url_for("handler", _external=True) == "http://my-server/foo"
request, response = app.test_client.get("/foo")
assert (
request.url_for("handler")
== f"http://my-server:{request.server_port}/foo"
== f"http://my-server/foo"
)
app.config.SERVER_NAME = "https://my-server/path"