commit
28bd09a2ea
|
@ -1,5 +1,5 @@
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import json
|
from sanic import response
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
|
@ -9,20 +9,18 @@ async def fetch(session, url):
|
||||||
"""
|
"""
|
||||||
Use session object to perform 'get' request on url
|
Use session object to perform 'get' request on url
|
||||||
"""
|
"""
|
||||||
async with session.get(url) as response:
|
async with session.get(url) as result:
|
||||||
return await response.json()
|
return await result.json()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route('/')
|
||||||
async def test(request):
|
async def handle_request(request):
|
||||||
"""
|
|
||||||
Download and serve example JSON
|
|
||||||
"""
|
|
||||||
url = "https://api.github.com/repos/channelcat/sanic"
|
url = "https://api.github.com/repos/channelcat/sanic"
|
||||||
|
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
response = await fetch(session, url)
|
result = await fetch(session, url)
|
||||||
return json(response)
|
return response.json(result)
|
||||||
|
|
||||||
|
|
||||||
app.run(host="0.0.0.0", port=8000, workers=2)
|
if __name__ == '__main__':
|
||||||
|
app.run(host="0.0.0.0", port=8000, workers=2)
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
"""
|
"""
|
||||||
Example intercepting uncaught exceptions using Sanic's error handler framework.
|
Example intercepting uncaught exceptions using Sanic's error handler framework.
|
||||||
|
|
||||||
This may be useful for developers wishing to use Sentry, Airbrake, etc.
|
This may be useful for developers wishing to use Sentry, Airbrake, etc.
|
||||||
or a custom system to log and monitor unexpected errors in production.
|
or a custom system to log and monitor unexpected errors in production.
|
||||||
|
|
||||||
First we create our own class inheriting from Handler in sanic.exceptions,
|
First we create our own class inheriting from Handler in sanic.exceptions,
|
||||||
and pass in an instance of it when we create our Sanic instance. Inside this
|
and pass in an instance of it when we create our Sanic instance. Inside this
|
||||||
class' default handler, we can do anything including sending exceptions to
|
class' default handler, we can do anything including sending exceptions to
|
||||||
|
@ -39,7 +37,7 @@ server's error_handler to an instance of our CustomHandler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import json
|
from sanic import response
|
||||||
|
|
||||||
app = Sanic(__name__)
|
app = Sanic(__name__)
|
||||||
|
|
||||||
|
@ -52,7 +50,7 @@ async def test(request):
|
||||||
# Here, something occurs which causes an unexpected exception
|
# Here, something occurs which causes an unexpected exception
|
||||||
# This exception will flow to our custom handler.
|
# This exception will flow to our custom handler.
|
||||||
1 / 0
|
1 / 0
|
||||||
return json({"test": True})
|
return response.json({"test": True})
|
||||||
|
|
||||||
|
|
||||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
app.run(host="0.0.0.0", port=8000, debug=True)
|
|
@ -2,7 +2,7 @@
|
||||||
# curl -d '{"name": "John Doe"}' localhost:8000
|
# curl -d '{"name": "John Doe"}' localhost:8000
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import html
|
from sanic import response
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
|
|
||||||
template = Template('Hello {{ name }}!')
|
template = Template('Hello {{ name }}!')
|
||||||
|
@ -12,7 +12,7 @@ app = Sanic(__name__)
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
async def test(request):
|
async def test(request):
|
||||||
data = request.json
|
data = request.json
|
||||||
return html(template.render(**data))
|
return response.html(template.render(**data))
|
||||||
|
|
||||||
|
|
||||||
app.run(host="0.0.0.0", port=8000)
|
app.run(host="0.0.0.0", port=8080, debug=True)
|
26
examples/modify_header_example.py
Normal file
26
examples/modify_header_example.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
"""
|
||||||
|
Modify header or status in response
|
||||||
|
"""
|
||||||
|
|
||||||
|
from sanic import Sanic
|
||||||
|
from sanic import response
|
||||||
|
|
||||||
|
app = Sanic(__name__)
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def handle_request(request):
|
||||||
|
return response.json(
|
||||||
|
{'message': 'Hello world!'},
|
||||||
|
headers={'X-Served-By': 'sanic'},
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
@app.route('/unauthorized')
|
||||||
|
def handle_request(request):
|
||||||
|
return response.json(
|
||||||
|
{'message': 'You are not authorized'},
|
||||||
|
headers={'X-Served-By': 'sanic'},
|
||||||
|
status=404
|
||||||
|
)
|
||||||
|
|
||||||
|
app.run(host="0.0.0.0", port=8000, debug=True)
|
|
@ -1,6 +1,5 @@
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import text
|
from sanic import response
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logging_format = "[%(asctime)s] %(process)d-%(levelname)s "
|
logging_format = "[%(asctime)s] %(process)d-%(levelname)s "
|
||||||
|
@ -18,6 +17,6 @@ sanic = Sanic()
|
||||||
@sanic.route("/")
|
@sanic.route("/")
|
||||||
def test(request):
|
def test(request):
|
||||||
log.info("received request; responding with 'hey'")
|
log.info("received request; responding with 'hey'")
|
||||||
return text("hey")
|
return response.text("hey")
|
||||||
|
|
||||||
sanic.run(host="0.0.0.0", port=8000)
|
sanic.run(host="0.0.0.0", port=8000)
|
||||||
|
|
85
examples/plotly_example/plotlyjs_example.py
Normal file
85
examples/plotly_example/plotlyjs_example.py
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
from sanic import Sanic
|
||||||
|
|
||||||
|
from sanic_session import InMemorySessionInterface
|
||||||
|
from sanic_jinja2 import SanicJinja2
|
||||||
|
|
||||||
|
import json
|
||||||
|
import plotly
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
app = Sanic(__name__)
|
||||||
|
|
||||||
|
jinja = SanicJinja2(app)
|
||||||
|
session = InMemorySessionInterface(cookie_name=app.name, prefix=app.name)
|
||||||
|
|
||||||
|
@app.middleware('request')
|
||||||
|
async def print_on_request(request):
|
||||||
|
print(request.headers)
|
||||||
|
await session.open(request)
|
||||||
|
|
||||||
|
@app.middleware('response')
|
||||||
|
async def print_on_response(request, response):
|
||||||
|
await session.save(request, response)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
async def index(request):
|
||||||
|
rng = pd.date_range('1/1/2011', periods=7500, freq='H')
|
||||||
|
ts = pd.Series(np.random.randn(len(rng)), index=rng)
|
||||||
|
|
||||||
|
graphs = [
|
||||||
|
dict(
|
||||||
|
data=[
|
||||||
|
dict(
|
||||||
|
x=[1, 2, 3],
|
||||||
|
y=[10, 20, 30],
|
||||||
|
type='scatter'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
layout=dict(
|
||||||
|
title='first graph'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
dict(
|
||||||
|
data=[
|
||||||
|
dict(
|
||||||
|
x=[1, 3, 5],
|
||||||
|
y=[10, 50, 30],
|
||||||
|
type='bar'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
layout=dict(
|
||||||
|
title='second graph'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
dict(
|
||||||
|
data=[
|
||||||
|
dict(
|
||||||
|
x=ts.index, # Can use the pandas data structures directly
|
||||||
|
y=ts
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add "ids" to each of the graphs to pass up to the client
|
||||||
|
# for templating
|
||||||
|
ids = ['graph-{}'.format(i) for i, _ in enumerate(graphs)]
|
||||||
|
|
||||||
|
# Convert the figures to JSON
|
||||||
|
# PlotlyJSONEncoder appropriately converts pandas, datetime, etc
|
||||||
|
# objects to their JSON equivalents
|
||||||
|
graphJSON = json.dumps(graphs, cls=plotly.utils.PlotlyJSONEncoder)
|
||||||
|
|
||||||
|
return jinja.render('index.html', request,
|
||||||
|
ids=ids,
|
||||||
|
graphJSON=graphJSON)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=8000, debug=True)
|
5
examples/plotly_example/requirements.txt
Normal file
5
examples/plotly_example/requirements.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pandas==0.19.2
|
||||||
|
plotly==2.0.7
|
||||||
|
sanic==0.5.0
|
||||||
|
sanic-jinja2==0.5.1
|
||||||
|
sanic-session==0.1.3
|
0
examples/plotly_example/templates/index.html
Normal file
0
examples/plotly_example/templates/index.html
Normal file
17
examples/redirect_example.py
Normal file
17
examples/redirect_example.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from sanic import Sanic
|
||||||
|
from sanic import response
|
||||||
|
|
||||||
|
app = Sanic(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def handle_request(request):
|
||||||
|
return response.redirect('/redirect')
|
||||||
|
|
||||||
|
@app.route('/redirect')
|
||||||
|
async def test(request):
|
||||||
|
return response.json({"Redirected": True})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host="0.0.0.0", port=8000)
|
|
@ -1,6 +1,6 @@
|
||||||
from sanic import Sanic
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from sanic.response import text
|
from sanic import Sanic
|
||||||
|
from sanic import response
|
||||||
from sanic.config import Config
|
from sanic.config import Config
|
||||||
from sanic.exceptions import RequestTimeout
|
from sanic.exceptions import RequestTimeout
|
||||||
|
|
||||||
|
@ -11,11 +11,11 @@ app = Sanic(__name__)
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
async def test(request):
|
async def test(request):
|
||||||
await asyncio.sleep(3)
|
await asyncio.sleep(3)
|
||||||
return text('Hello, world!')
|
return response.text('Hello, world!')
|
||||||
|
|
||||||
|
|
||||||
@app.exception(RequestTimeout)
|
@app.exception(RequestTimeout)
|
||||||
def timeout(request, exception):
|
def timeout(request, exception):
|
||||||
return text('RequestTimeout from error_handler.', 408)
|
return response.text('RequestTimeout from error_handler.', 408)
|
||||||
|
|
||||||
app.run(host='0.0.0.0', port=8000)
|
app.run(host='0.0.0.0', port=8000)
|
|
@ -1,5 +1,5 @@
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import json
|
from sanic import response
|
||||||
from multiprocessing import Event
|
from multiprocessing import Event
|
||||||
from signal import signal, SIGINT
|
from signal import signal, SIGINT
|
||||||
import asyncio
|
import asyncio
|
||||||
|
@ -9,10 +9,10 @@ app = Sanic(__name__)
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
async def test(request):
|
async def test(request):
|
||||||
return json({"answer": "42"})
|
return response.json({"answer": "42"})
|
||||||
|
|
||||||
asyncio.set_event_loop(uvloop.new_event_loop())
|
asyncio.set_event_loop(uvloop.new_event_loop())
|
||||||
server = app.create_server(host="0.0.0.0", port=8001)
|
server = app.create_server(host="0.0.0.0", port=8000)
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
task = asyncio.ensure_future(server)
|
task = asyncio.ensure_future(server)
|
||||||
signal(SIGINT, lambda s, f: loop.stop())
|
signal(SIGINT, lambda s, f: loop.stop())
|
||||||
|
|
|
@ -5,7 +5,7 @@ motor==1.1
|
||||||
sanic==0.2.0
|
sanic==0.2.0
|
||||||
"""
|
"""
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import json
|
from sanic import response
|
||||||
|
|
||||||
|
|
||||||
app = Sanic('motor_mongodb')
|
app = Sanic('motor_mongodb')
|
||||||
|
@ -25,7 +25,7 @@ async def get(request):
|
||||||
for doc in docs:
|
for doc in docs:
|
||||||
doc['id'] = str(doc['_id'])
|
doc['id'] = str(doc['_id'])
|
||||||
del doc['_id']
|
del doc['_id']
|
||||||
return json(docs)
|
return response.json(docs)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/post', methods=['POST'])
|
@app.route('/post', methods=['POST'])
|
||||||
|
@ -34,8 +34,8 @@ async def new(request):
|
||||||
print(doc)
|
print(doc)
|
||||||
db = get_db()
|
db = get_db()
|
||||||
object_id = await db.test_col.save(doc)
|
object_id = await db.test_col.save(doc)
|
||||||
return json({'object_id': str(object_id)})
|
return response.json({'object_id': str(object_id)})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host='127.0.0.1', port=8000)
|
app.run(host='0.0.0.0', port=8000, debug=True)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import json
|
from sanic import response
|
||||||
|
|
||||||
app = Sanic(__name__)
|
app = Sanic(__name__)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
async def test(request):
|
async def test(request):
|
||||||
return json({"test": True})
|
return response.json({"test": True})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -2,7 +2,7 @@ import os
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.log import log
|
from sanic.log import log
|
||||||
from sanic.response import json, text, file
|
from sanic import response
|
||||||
from sanic.exceptions import ServerError
|
from sanic.exceptions import ServerError
|
||||||
|
|
||||||
app = Sanic(__name__)
|
app = Sanic(__name__)
|
||||||
|
@ -10,17 +10,17 @@ app = Sanic(__name__)
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
async def test_async(request):
|
async def test_async(request):
|
||||||
return json({"test": True})
|
return response.json({"test": True})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/sync", methods=['GET', 'POST'])
|
@app.route("/sync", methods=['GET', 'POST'])
|
||||||
def test_sync(request):
|
def test_sync(request):
|
||||||
return json({"test": True})
|
return response.json({"test": True})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/dynamic/<name>/<id:int>")
|
@app.route("/dynamic/<name>/<id:int>")
|
||||||
def test_params(request, name, id):
|
def test_params(request, name, id):
|
||||||
return text("yeehaww {} {}".format(name, id))
|
return response.text("yeehaww {} {}".format(name, id))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/exception")
|
@app.route("/exception")
|
||||||
|
@ -31,11 +31,11 @@ def exception(request):
|
||||||
async def test_await(request):
|
async def test_await(request):
|
||||||
import asyncio
|
import asyncio
|
||||||
await asyncio.sleep(5)
|
await asyncio.sleep(5)
|
||||||
return text("I'm feeling sleepy")
|
return response.text("I'm feeling sleepy")
|
||||||
|
|
||||||
@app.route("/file")
|
@app.route("/file")
|
||||||
async def test_file(request):
|
async def test_file(request):
|
||||||
return await file(os.path.abspath("setup.py"))
|
return await response.file(os.path.abspath("setup.py"))
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------- #
|
# ----------------------------------------------- #
|
||||||
|
@ -44,7 +44,7 @@ async def test_file(request):
|
||||||
|
|
||||||
@app.exception(ServerError)
|
@app.exception(ServerError)
|
||||||
async def test(request, exception):
|
async def test(request, exception):
|
||||||
return json({"exception": "{}".format(exception), "status": exception.status_code}, status=exception.status_code)
|
return response.json({"exception": "{}".format(exception), "status": exception.status_code}, status=exception.status_code)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------- #
|
# ----------------------------------------------- #
|
||||||
|
@ -53,17 +53,17 @@ async def test(request, exception):
|
||||||
|
|
||||||
@app.route("/json")
|
@app.route("/json")
|
||||||
def post_json(request):
|
def post_json(request):
|
||||||
return json({"received": True, "message": request.json})
|
return response.json({"received": True, "message": request.json})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/form")
|
@app.route("/form")
|
||||||
def post_json(request):
|
def post_json(request):
|
||||||
return json({"received": True, "form_data": request.form, "test": request.form.get('test')})
|
return response.json({"received": True, "form_data": request.form, "test": request.form.get('test')})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/query_string")
|
@app.route("/query_string")
|
||||||
def query_string(request):
|
def query_string(request):
|
||||||
return json({"parsed": True, "args": request.args, "url": request.url, "query_string": request.query_string})
|
return response.json({"parsed": True, "args": request.args, "url": request.url, "query_string": request.query_string})
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------- #
|
# ----------------------------------------------- #
|
||||||
|
|
18
examples/url_for_example.py
Normal file
18
examples/url_for_example.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from sanic import Sanic
|
||||||
|
from sanic import response
|
||||||
|
|
||||||
|
app = Sanic(__name__)
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
async def index(request):
|
||||||
|
# generate a URL for the endpoint `post_handler`
|
||||||
|
url = app.url_for('post_handler', post_id=5)
|
||||||
|
# the URL is `/posts/5`, redirect to it
|
||||||
|
return response.redirect(url)
|
||||||
|
|
||||||
|
@app.route('/posts/<post_id>')
|
||||||
|
async def post_handler(request, post_id):
|
||||||
|
return response.text('Post - {}'.format(post_id))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host="0.0.0.0", port=8000, debug=True)
|
|
@ -1,4 +1,4 @@
|
||||||
from sanic.response import text
|
from sanic import response
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.blueprints import Blueprint
|
from sanic.blueprints import Blueprint
|
||||||
|
|
||||||
|
@ -15,23 +15,23 @@ bp = Blueprint("bp", host="bp.example.com")
|
||||||
"somethingelse.com",
|
"somethingelse.com",
|
||||||
"therestofyourdomains.com"])
|
"therestofyourdomains.com"])
|
||||||
async def hello(request):
|
async def hello(request):
|
||||||
return text("Some defaults")
|
return response.text("Some defaults")
|
||||||
|
|
||||||
@app.route('/', host="example.com")
|
@app.route('/', host="example.com")
|
||||||
async def hello(request):
|
async def hello(request):
|
||||||
return text("Answer")
|
return response.text("Answer")
|
||||||
|
|
||||||
@app.route('/', host="sub.example.com")
|
@app.route('/', host="sub.example.com")
|
||||||
async def hello(request):
|
async def hello(request):
|
||||||
return text("42")
|
return response.text("42")
|
||||||
|
|
||||||
@bp.route("/question")
|
@bp.route("/question")
|
||||||
async def hello(request):
|
async def hello(request):
|
||||||
return 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(request):
|
||||||
return text("42")
|
return response.text("42")
|
||||||
|
|
||||||
app.register_blueprint(bp)
|
app.register_blueprint(bp)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
aiofiles
|
aiofiles
|
||||||
aiohttp==1.3.5
|
aiohttp==1.3.5
|
||||||
|
chardet<=2.3.0
|
||||||
beautifulsoup4
|
beautifulsoup4
|
||||||
coverage
|
coverage
|
||||||
httptools
|
httptools
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from sanic.app import Sanic
|
from sanic.app import Sanic
|
||||||
from sanic.blueprints import Blueprint
|
from sanic.blueprints import Blueprint
|
||||||
|
|
||||||
__version__ = '0.4.1'
|
__version__ = '0.5.1'
|
||||||
|
|
||||||
__all__ = ['Sanic', 'Blueprint']
|
__all__ = ['Sanic', 'Blueprint']
|
||||||
|
|
|
@ -26,7 +26,7 @@ from sanic.websocket import WebSocketProtocol, ConnectionClosed
|
||||||
class Sanic:
|
class Sanic:
|
||||||
|
|
||||||
def __init__(self, name=None, router=None, error_handler=None,
|
def __init__(self, name=None, router=None, error_handler=None,
|
||||||
load_env=True):
|
load_env=True, request_class=None):
|
||||||
# Only set up a default log handler if the
|
# Only set up a default log handler if the
|
||||||
# end-user application didn't set anything up.
|
# end-user application didn't set anything up.
|
||||||
if not logging.root.handlers and log.level == logging.NOTSET:
|
if not logging.root.handlers and log.level == logging.NOTSET:
|
||||||
|
@ -44,6 +44,7 @@ class Sanic:
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.router = router or Router()
|
self.router = router or Router()
|
||||||
|
self.request_class = request_class
|
||||||
self.error_handler = error_handler or ErrorHandler()
|
self.error_handler = error_handler or ErrorHandler()
|
||||||
self.config = Config(load_env=load_env)
|
self.config = Config(load_env=load_env)
|
||||||
self.request_middleware = deque()
|
self.request_middleware = deque()
|
||||||
|
@ -668,6 +669,7 @@ class Sanic:
|
||||||
|
|
||||||
server_settings = {
|
server_settings = {
|
||||||
'protocol': protocol,
|
'protocol': protocol,
|
||||||
|
'request_class': self.request_class,
|
||||||
'host': host,
|
'host': host,
|
||||||
'port': port,
|
'port': port,
|
||||||
'sock': sock,
|
'sock': sock,
|
||||||
|
|
|
@ -129,7 +129,7 @@ class StreamingHTTPResponse(BaseHTTPResponse):
|
||||||
data = self._encode_body(data)
|
data = self._encode_body(data)
|
||||||
|
|
||||||
self.transport.write(
|
self.transport.write(
|
||||||
b"%b\r\n%b\r\n" % (str(len(data)).encode(), data))
|
b"%x\r\n%b\r\n" % (len(data), data))
|
||||||
|
|
||||||
async def stream(
|
async def stream(
|
||||||
self, version="1.1", keep_alive=False, keep_alive_timeout=None):
|
self, version="1.1", keep_alive=False, keep_alive_timeout=None):
|
||||||
|
|
|
@ -64,12 +64,13 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
'parser', 'request', 'url', 'headers',
|
'parser', 'request', 'url', 'headers',
|
||||||
# request config
|
# request config
|
||||||
'request_handler', 'request_timeout', 'request_max_size',
|
'request_handler', 'request_timeout', 'request_max_size',
|
||||||
|
'request_class',
|
||||||
# connection management
|
# connection management
|
||||||
'_total_request_size', '_timeout_handler', '_last_communication_time')
|
'_total_request_size', '_timeout_handler', '_last_communication_time')
|
||||||
|
|
||||||
def __init__(self, *, loop, request_handler, error_handler,
|
def __init__(self, *, loop, request_handler, error_handler,
|
||||||
signal=Signal(), connections=set(), request_timeout=60,
|
signal=Signal(), connections=set(), request_timeout=60,
|
||||||
request_max_size=None):
|
request_max_size=None, request_class=None):
|
||||||
self.loop = loop
|
self.loop = loop
|
||||||
self.transport = None
|
self.transport = None
|
||||||
self.request = None
|
self.request = None
|
||||||
|
@ -82,11 +83,16 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
self.error_handler = error_handler
|
self.error_handler = error_handler
|
||||||
self.request_timeout = request_timeout
|
self.request_timeout = request_timeout
|
||||||
self.request_max_size = request_max_size
|
self.request_max_size = request_max_size
|
||||||
|
self.request_class = request_class or Request
|
||||||
self._total_request_size = 0
|
self._total_request_size = 0
|
||||||
self._timeout_handler = None
|
self._timeout_handler = None
|
||||||
self._last_request_time = None
|
self._last_request_time = None
|
||||||
self._request_handler_task = None
|
self._request_handler_task = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def keep_alive(self):
|
||||||
|
return self.parser.should_keep_alive() and not self.signal.stopped
|
||||||
|
|
||||||
# -------------------------------------------- #
|
# -------------------------------------------- #
|
||||||
# Connection
|
# Connection
|
||||||
# -------------------------------------------- #
|
# -------------------------------------------- #
|
||||||
|
@ -151,7 +157,7 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
self.headers.append((name.decode().casefold(), value.decode()))
|
self.headers.append((name.decode().casefold(), value.decode()))
|
||||||
|
|
||||||
def on_headers_complete(self):
|
def on_headers_complete(self):
|
||||||
self.request = Request(
|
self.request = self.request_class(
|
||||||
url_bytes=self.url,
|
url_bytes=self.url,
|
||||||
headers=CIDict(self.headers),
|
headers=CIDict(self.headers),
|
||||||
version=self.parser.get_http_version(),
|
version=self.parser.get_http_version(),
|
||||||
|
@ -180,9 +186,7 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
Writes response content synchronously to the transport.
|
Writes response content synchronously to the transport.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
keep_alive = (
|
keep_alive = self.keep_alive
|
||||||
self.parser.should_keep_alive() and not self.signal.stopped)
|
|
||||||
|
|
||||||
self.transport.write(
|
self.transport.write(
|
||||||
response.output(
|
response.output(
|
||||||
self.request.version, keep_alive,
|
self.request.version, keep_alive,
|
||||||
|
@ -216,9 +220,7 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
keep_alive = (
|
keep_alive = self.keep_alive
|
||||||
self.parser.should_keep_alive() and not self.signal.stopped)
|
|
||||||
|
|
||||||
response.transport = self.transport
|
response.transport = self.transport
|
||||||
await response.stream(
|
await response.stream(
|
||||||
self.request.version, keep_alive, self.request_timeout)
|
self.request.version, keep_alive, self.request_timeout)
|
||||||
|
@ -320,7 +322,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
|
||||||
request_timeout=60, ssl=None, sock=None, request_max_size=None,
|
request_timeout=60, ssl=None, sock=None, request_max_size=None,
|
||||||
reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100,
|
reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100,
|
||||||
register_sys_signals=True, run_async=False, connections=None,
|
register_sys_signals=True, run_async=False, connections=None,
|
||||||
signal=Signal()):
|
signal=Signal(), request_class=None):
|
||||||
"""Start asynchronous HTTP Server on an individual process.
|
"""Start asynchronous HTTP Server on an individual process.
|
||||||
|
|
||||||
:param host: Address to host on
|
:param host: Address to host on
|
||||||
|
@ -345,6 +347,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
|
||||||
:param reuse_port: `True` for multiple workers
|
:param reuse_port: `True` for multiple workers
|
||||||
:param loop: asyncio compatible event loop
|
:param loop: asyncio compatible event loop
|
||||||
:param protocol: subclass of asyncio protocol class
|
:param protocol: subclass of asyncio protocol class
|
||||||
|
:param request_class: Request class to use
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
"""
|
"""
|
||||||
if not run_async:
|
if not run_async:
|
||||||
|
@ -366,6 +369,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
|
||||||
error_handler=error_handler,
|
error_handler=error_handler,
|
||||||
request_timeout=request_timeout,
|
request_timeout=request_timeout,
|
||||||
request_max_size=request_max_size,
|
request_max_size=request_max_size,
|
||||||
|
request_class=request_class,
|
||||||
)
|
)
|
||||||
|
|
||||||
server_coroutine = loop.create_server(
|
server_coroutine = loop.create_server(
|
||||||
|
|
|
@ -48,14 +48,18 @@ def register(app, uri, file_or_directory, pattern,
|
||||||
# Merge served directory and requested file if provided
|
# Merge served directory and requested file if provided
|
||||||
# Strip all / that in the beginning of the URL to help prevent python
|
# Strip all / that in the beginning of the URL to help prevent python
|
||||||
# from herping a derp and treating the uri as an absolute path
|
# from herping a derp and treating the uri as an absolute path
|
||||||
file_path = file_or_directory
|
root_path = file_path = file_or_directory
|
||||||
if file_uri:
|
if file_uri:
|
||||||
file_path = path.join(
|
file_path = path.join(
|
||||||
file_or_directory, sub('^[/]*', '', file_uri))
|
file_or_directory, sub('^[/]*', '', file_uri))
|
||||||
|
|
||||||
# URL decode the path sent by the browser otherwise we won't be able to
|
# URL decode the path sent by the browser otherwise we won't be able to
|
||||||
# match filenames which got encoded (filenames with spaces etc)
|
# match filenames which got encoded (filenames with spaces etc)
|
||||||
file_path = unquote(file_path)
|
file_path = path.abspath(unquote(file_path))
|
||||||
|
if not file_path.startswith(root_path):
|
||||||
|
raise FileNotFound('File not found',
|
||||||
|
path=file_or_directory,
|
||||||
|
relative_url=file_uri)
|
||||||
try:
|
try:
|
||||||
headers = {}
|
headers = {}
|
||||||
# Check if the client has been sent this file before
|
# Check if the client has been sent this file before
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import traceback
|
||||||
|
|
||||||
from sanic.log import log
|
from sanic.log import log
|
||||||
|
|
||||||
HOST = '127.0.0.1'
|
HOST = '127.0.0.1'
|
||||||
|
@ -50,6 +52,8 @@ class SanicTestClient:
|
||||||
**request_kwargs)
|
**request_kwargs)
|
||||||
results[-1] = response
|
results[-1] = response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
log.error(
|
||||||
|
'Exception:\n{}'.format(traceback.format_exc()))
|
||||||
exceptions.append(e)
|
exceptions.append(e)
|
||||||
self.app.stop()
|
self.app.stop()
|
||||||
|
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -64,7 +64,3 @@ except DistutilsPlatformError as exception:
|
||||||
print("Installing without uJSON or uvLoop")
|
print("Installing without uJSON or uvLoop")
|
||||||
setup_kwargs['install_requires'] = requirements
|
setup_kwargs['install_requires'] = requirements
|
||||||
setup(**setup_kwargs)
|
setup(**setup_kwargs)
|
||||||
|
|
||||||
# Installation was successful
|
|
||||||
print(u"\n\n\U0001F680 "
|
|
||||||
"Sanic version {} installation suceeded.\n".format(version))
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user