Repository: sanic-org/sanic

Issue:
Using a domain socket?
I'm trying to put sanic behind nginx using a domain socket. Is this possible at all?


Discussion:
So you need to expose sanic via a domain socket, right? I don't think that's supported but shouldn't be very hard to add.
You can utilize domain sockets through gunicorn and nginx as shown in gunicorn's documentation:

http://docs.gunicorn.org/en/stable/deploy.html

Refer to [our docs](http://sanic.readthedocs.io/en/latest/sanic/deploying.html#running-via-gunicorn) for how to run a sanic application through gunicorn
Gunicorn loads the class and creates a TCP listener as well. I need to use an existing setup that relies on domain sockets alone...

Right. Am willing to test and provide reference configs, of course.


 ya, i think unix socket support should be separate from wsgi compatibility. 

Resolving patch:
diff --git a/examples/unix_socket.py b/examples/unix_socket.py
new file mode 100644
--- /dev/null
+++ b/examples/unix_socket.py
@@ -0,0 +1,23 @@
+from sanic import Sanic
+from sanic import response
+import socket
+import sys
+import os
+
+app = Sanic(__name__)
+
+@app.route("/test")
+async def test(request):
+    return response.text("OK")
+
+if __name__ == '__main__':
+    server_address = './uds_socket'
+    # Make sure the socket does not already exist
+    try:
+            os.unlink(server_address)
+    except OSError:
+            if os.path.exists(server_address):
+                        raise
+    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    sock.bind(server_address)
+    app.run(sock=sock)
diff --git a/sanic/app.py b/sanic/app.py
--- a/sanic/app.py
+++ b/sanic/app.py
@@ -521,7 +521,7 @@ def test_client(self):
     # Execution
     # -------------------------------------------------------------------- #
 
-    def run(self, host="127.0.0.1", port=8000, debug=False, ssl=None,
+    def run(self, host=None, port=None, debug=False, ssl=None,
             sock=None, workers=1, protocol=None,
             backlog=100, stop_event=None, register_sys_signals=True,
             log_config=LOGGING):
@@ -580,7 +580,7 @@ def __call__(self):
         """gunicorn compatibility"""
         return self
 
-    async def create_server(self, host="127.0.0.1", port=8000, debug=False,
+    async def create_server(self, host=None, port=None, debug=False,
                             ssl=None, sock=None, protocol=None,
                             backlog=100, stop_event=None,
                             log_config=LOGGING):
@@ -629,11 +629,13 @@ async def _run_response_middleware(self, request, response):
                     break
         return response
 
-    def _helper(self, host="127.0.0.1", port=8000, debug=False,
+    def _helper(self, host=None, port=None, debug=False,
                 ssl=None, sock=None, workers=1, loop=None,
                 protocol=HttpProtocol, backlog=100, stop_event=None,
                 register_sys_signals=True, run_async=False, has_log=True):
         """Helper function used by `run` and `create_server`."""
+        if sock is None:
+            host, port = host or "127.0.0.1", port or 8000
 
         if isinstance(ssl, dict):
             # try common aliaseses
diff --git a/sanic/server.py b/sanic/server.py
--- a/sanic/server.py
+++ b/sanic/server.py
@@ -201,9 +201,10 @@ def write_response(self, response):
                 netlog.info('', extra={
                     'status': response.status,
                     'byte': len(response.body),
-                    'host': '%s:%d' % (self.request.ip[0], self.request.ip[1]),
-                    'request': '%s %s' % (self.request.method,
-                                          self.request.url)
+                    'host': '{0}:{1}'.format(self.request.ip[0],
+                                             self.request.ip[1]),
+                    'request': '{0} {1}'.format(self.request.method,
+                                                self.request.url)
                 })
         except AttributeError:
             log.error(
@@ -242,9 +243,10 @@ async def stream_response(self, response):
                 netlog.info('', extra={
                     'status': response.status,
                     'byte': -1,
-                    'host': '%s:%d' % self.request.ip,
-                    'request': '%s %s' % (self.request.method,
-                                          self.request.url)
+                    'host': '{0}:{1}'.format(self.request.ip[0],
+                                             self.request.ip[1]),
+                    'request': '{0} {1}'.format(self.request.method,
+                                                self.request.url)
                 })
         except AttributeError:
             log.error(


Test patch: