Fix some examples and docs (#2052)
This commit is contained in:
parent
5ca8bb85cd
commit
ec7e4390e8
|
@ -1,11 +1,8 @@
|
||||||
FROM python:3.5
|
FROM sanicframework/sanic:LTS
|
||||||
MAINTAINER Channel Cat <channelcat@gmail.com>
|
|
||||||
|
|
||||||
ADD . /code
|
RUN mkdir /srv
|
||||||
RUN pip3 install git+https://github.com/channelcat/sanic
|
COPY . /srv
|
||||||
|
|
||||||
EXPOSE 8000
|
WORKDIR /srv
|
||||||
|
|
||||||
WORKDIR /code
|
CMD ["sanic", "simple_server.app"]
|
||||||
|
|
||||||
CMD ["python", "simple_server.py"]
|
|
||||||
|
|
|
@ -1,86 +1,75 @@
|
||||||
'''
|
|
||||||
Based on example from https://github.com/Skyscanner/aiotask-context
|
|
||||||
and `examples/{override_logging,run_async}.py`.
|
|
||||||
|
|
||||||
Needs https://github.com/Skyscanner/aiotask-context/tree/52efbc21e2e1def2d52abb9a8e951f3ce5e6f690 or newer
|
|
||||||
|
|
||||||
$ pip install git+https://github.com/Skyscanner/aiotask-context.git
|
|
||||||
'''
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import uuid
|
|
||||||
import logging
|
import logging
|
||||||
from signal import signal, SIGINT
|
|
||||||
|
|
||||||
from sanic import Sanic
|
|
||||||
from sanic import response
|
|
||||||
|
|
||||||
import uvloop
|
|
||||||
import aiotask_context as context
|
import aiotask_context as context
|
||||||
|
|
||||||
|
from sanic import Sanic, response
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RequestIdFilter(logging.Filter):
|
class RequestIdFilter(logging.Filter):
|
||||||
def filter(self, record):
|
def filter(self, record):
|
||||||
record.request_id = context.get('X-Request-ID')
|
try:
|
||||||
|
record.request_id = context.get("X-Request-ID")
|
||||||
|
except ValueError:
|
||||||
|
record.request_id = "n/a"
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
LOG_SETTINGS = {
|
LOG_SETTINGS = {
|
||||||
'version': 1,
|
"version": 1,
|
||||||
'disable_existing_loggers': False,
|
"disable_existing_loggers": False,
|
||||||
'handlers': {
|
"handlers": {
|
||||||
'console': {
|
"console": {
|
||||||
'class': 'logging.StreamHandler',
|
"class": "logging.StreamHandler",
|
||||||
'level': 'DEBUG',
|
"level": "DEBUG",
|
||||||
'formatter': 'default',
|
"formatter": "default",
|
||||||
'filters': ['requestid'],
|
"filters": ["requestid"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'filters': {
|
"filters": {
|
||||||
'requestid': {
|
"requestid": {
|
||||||
'()': RequestIdFilter,
|
"()": RequestIdFilter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'formatters': {
|
"formatters": {
|
||||||
'default': {
|
"default": {
|
||||||
'format': '%(asctime)s %(levelname)s %(name)s:%(lineno)d %(request_id)s | %(message)s',
|
"format": "%(asctime)s %(levelname)s %(name)s:%(lineno)d %(request_id)s | %(message)s",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'loggers': {
|
"loggers": {
|
||||||
'': {
|
"": {"level": "DEBUG", "handlers": ["console"], "propagate": True},
|
||||||
'level': 'DEBUG',
|
},
|
||||||
'handlers': ['console'],
|
|
||||||
'propagate': True
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
app = Sanic(__name__, log_config=LOG_SETTINGS)
|
app = Sanic(__name__, log_config=LOG_SETTINGS)
|
||||||
|
|
||||||
|
|
||||||
@app.middleware('request')
|
@app.on_request
|
||||||
async def set_request_id(request):
|
async def set_request_id(request):
|
||||||
request_id = request.headers.get('X-Request-ID') or str(uuid.uuid4())
|
request_id = request.id
|
||||||
context.set("X-Request-ID", request_id)
|
context.set("X-Request-ID", request_id)
|
||||||
|
log.info(f"Setting {request.id=}")
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_response
|
||||||
|
async def set_request_header(request, response):
|
||||||
|
response.headers["X-Request-ID"] = request.id
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
async def test(request):
|
async def test(request):
|
||||||
log.debug('X-Request-ID: %s', context.get('X-Request-ID'))
|
log.debug("X-Request-ID: %s", context.get("X-Request-ID"))
|
||||||
log.info('Hello from test!')
|
log.info("Hello from test!")
|
||||||
return response.json({"test": True})
|
return response.json({"test": True})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
@app.before_server_start
|
||||||
asyncio.set_event_loop(uvloop.new_event_loop())
|
def setup(app, loop):
|
||||||
server = app.create_server(host="0.0.0.0", port=8000, return_asyncio_server=True)
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.set_task_factory(context.task_factory)
|
loop.set_task_factory(context.task_factory)
|
||||||
task = asyncio.ensure_future(server)
|
|
||||||
try:
|
|
||||||
loop.run_forever()
|
if __name__ == "__main__":
|
||||||
except:
|
app.run(port=9999, debug=True)
|
||||||
loop.stop()
|
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
from sanic import Sanic
|
|
||||||
from sanic import response
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from sanic import Sanic, text
|
||||||
|
|
||||||
|
|
||||||
logging_format = "[%(asctime)s] %(process)d-%(levelname)s "
|
logging_format = "[%(asctime)s] %(process)d-%(levelname)s "
|
||||||
logging_format += "%(module)s::%(funcName)s():l%(lineno)d: "
|
logging_format += "%(module)s::%(funcName)s():l%(lineno)d: "
|
||||||
logging_format += "%(message)s"
|
logging_format += "%(message)s"
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(format=logging_format, level=logging.DEBUG)
|
||||||
format=logging_format,
|
|
||||||
level=logging.DEBUG
|
|
||||||
)
|
|
||||||
log = logging.getLogger()
|
log = logging.getLogger()
|
||||||
|
|
||||||
# Set logger to override default basicConfig
|
# Set logger to override default basicConfig
|
||||||
sanic = Sanic()
|
app = Sanic("app")
|
||||||
|
|
||||||
|
|
||||||
@sanic.route("/")
|
@app.route("/")
|
||||||
def test(request):
|
def test(request):
|
||||||
log.info("received request; responding with 'hey'")
|
log.info("received request; responding with 'hey'")
|
||||||
return response.text("hey")
|
return text("hey")
|
||||||
|
|
||||||
sanic.run(host="0.0.0.0", port=8000)
|
|
||||||
|
app.run(host="0.0.0.0", port=8000)
|
||||||
|
|
|
@ -9,15 +9,19 @@ Run with xdist params:
|
||||||
$ pytest examples/pytest_xdist.py -n 8 # 8 workers
|
$ pytest examples/pytest_xdist.py -n 8 # 8 workers
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from sanic_testing import SanicTestClient
|
||||||
|
from sanic_testing.testing import PORT as PORT_BASE
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import text
|
from sanic.response import text
|
||||||
from sanic.testing import PORT as PORT_BASE, SanicTestClient
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def test_port(worker_id):
|
def test_port(worker_id):
|
||||||
m = re.search(r'[0-9]+', worker_id)
|
m = re.search(r"[0-9]+", worker_id)
|
||||||
if m:
|
if m:
|
||||||
num_id = m.group(0)
|
num_id = m.group(0)
|
||||||
else:
|
else:
|
||||||
|
@ -30,9 +34,9 @@ def test_port(worker_id):
|
||||||
def app():
|
def app():
|
||||||
app = Sanic()
|
app = Sanic()
|
||||||
|
|
||||||
@app.route('/')
|
@app.route("/")
|
||||||
async def index(request):
|
async def index(request):
|
||||||
return text('OK')
|
return text("OK")
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
@ -42,8 +46,8 @@ def client(app, test_port):
|
||||||
return SanicTestClient(app, test_port)
|
return SanicTestClient(app, test_port)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('run_id', range(100))
|
@pytest.mark.parametrize("run_id", range(100))
|
||||||
def test_index(client, run_id):
|
def test_index(client, run_id):
|
||||||
request, response = client._sanic_endpoint_test('get', '/')
|
request, response = client._sanic_endpoint_test("get", "/")
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert response.text == 'OK'
|
assert response.text == "OK"
|
||||||
|
|
|
@ -1,39 +1,45 @@
|
||||||
from sanic import response
|
from sanic import Sanic, response
|
||||||
from sanic import Sanic
|
|
||||||
from sanic.blueprints import Blueprint
|
from sanic.blueprints import Blueprint
|
||||||
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
# curl -H "Host: example.com" localhost:8000
|
# curl -H "Host: example.com" localhost:8000
|
||||||
# curl -H "Host: sub.example.com" localhost:8000
|
# curl -H "Host: sub.example.com" localhost:8000
|
||||||
# curl -H "Host: bp.example.com" localhost:8000/question
|
# curl -H "Host: bp.example.com" localhost:8000/question
|
||||||
# curl -H "Host: bp.example.com" localhost:8000/answer
|
# curl -H "Host: bp.example.com" localhost:8000/answer
|
||||||
|
|
||||||
app = Sanic()
|
app = Sanic(__name__)
|
||||||
bp = Blueprint("bp", host="bp.example.com")
|
bp = Blueprint("bp", host="bp.example.com")
|
||||||
|
|
||||||
|
|
||||||
@app.route('/', host=["example.com",
|
@app.route(
|
||||||
"somethingelse.com",
|
"/", host=["example.com", "somethingelse.com", "therestofyourdomains.com"]
|
||||||
"therestofyourdomains.com"])
|
)
|
||||||
async def hello(request):
|
async def hello_0(request):
|
||||||
return response.text("Some defaults")
|
return response.text("Some defaults")
|
||||||
|
|
||||||
|
|
||||||
@app.route('/', host="sub.example.com")
|
@app.route("/", host="sub.example.com")
|
||||||
async def hello(request):
|
async def hello_1(request):
|
||||||
return response.text("42")
|
return response.text("42")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/question")
|
@bp.route("/question")
|
||||||
async def hello(request):
|
async def hello_2(request):
|
||||||
return response.text("What is the meaning of life?")
|
return response.text("What is the meaning of life?")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/answer")
|
@bp.route("/answer")
|
||||||
async def hello(request):
|
async def hello_3(request):
|
||||||
return response.text("42")
|
return response.text("42")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/name")
|
||||||
|
def name(request):
|
||||||
|
return response.text(request.app.url_for("name", _external=True))
|
||||||
|
|
||||||
|
|
||||||
app.blueprint(bp)
|
app.blueprint(bp)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
app.run(host="0.0.0.0", port=8000)
|
app.run(host="0.0.0.0", port=8000)
|
22
sanic/app.py
22
sanic/app.py
|
@ -358,6 +358,28 @@ class Sanic(BaseSanic):
|
||||||
Keyword arguments that are not request parameters will be included in
|
Keyword arguments that are not request parameters will be included in
|
||||||
the output URL's query string.
|
the output URL's query string.
|
||||||
|
|
||||||
|
There are several _special_ keyword arguments that will alter how the
|
||||||
|
URL will be returned:
|
||||||
|
|
||||||
|
1. **_anchor**: ``str`` - Adds an ``#anchor`` to the end
|
||||||
|
2. **_scheme**: ``str`` - Should be either ``"http"`` or ``"https"``,
|
||||||
|
default is ``"http"``
|
||||||
|
3. **_external**: ``bool`` - Whether to return the path or a full URL
|
||||||
|
with scheme and host
|
||||||
|
4. **_host**: ``str`` - Used when one or more hosts are defined for a
|
||||||
|
route to tell Sanic which to use
|
||||||
|
(only applies with ``_external=True``)
|
||||||
|
5. **_server**: ``str`` - If not using ``_host``, this will be used
|
||||||
|
for defining the hostname of the URL
|
||||||
|
(only applies with ``_external=True``),
|
||||||
|
defaults to ``app.config.SERVER_NAME``
|
||||||
|
|
||||||
|
If you want the PORT to appear in your URL, you should set it in:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
app.config.SERVER_NAME = "myserver:7777"
|
||||||
|
|
||||||
`See user guide
|
`See user guide
|
||||||
<https://sanicframework.org/guide/basics/routing.html#generating-a-url>`__
|
<https://sanicframework.org/guide/basics/routing.html#generating-a-url>`__
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user