Merge branch 'master' into master

This commit is contained in:
Raphael Deem
2017-04-24 00:47:01 -07:00
committed by GitHub
27 changed files with 404 additions and 69 deletions

View File

@@ -17,7 +17,7 @@ from sanic.handlers import ErrorHandler
from sanic.log import log
from sanic.response import HTTPResponse, StreamingHTTPResponse
from sanic.router import Router
from sanic.server import serve, serve_multiple, HttpProtocol
from sanic.server import serve, serve_multiple, HttpProtocol, Signal
from sanic.static import register as static_register
from sanic.testing import SanicTestClient
from sanic.views import CompositionView
@@ -293,7 +293,7 @@ class Sanic:
attach_to=middleware_or_request)
# Static Files
def static(self, uri, file_or_directory, pattern='.+',
def static(self, uri, file_or_directory, pattern=r'/?.+',
use_modified_since=True, use_content_range=False):
"""Register a root to serve files from. The input can either be a
file or a directory. See
@@ -687,11 +687,13 @@ class Sanic:
'port': port,
'sock': sock,
'ssl': ssl,
'signal': Signal(),
'debug': debug,
'request_handler': self.handle_request,
'error_handler': self.error_handler,
'request_timeout': self.config.REQUEST_TIMEOUT,
'request_max_size': self.config.REQUEST_MAX_SIZE,
'keep_alive': self.config.KEEP_ALIVE,
'loop': loop,
'register_sys_signals': register_sys_signals,
'backlog': backlog,

View File

@@ -116,7 +116,7 @@ if type(_addr) is str and not os.path.exists(_addr):
class Config(dict):
def __init__(self, defaults=None, load_env=True):
def __init__(self, defaults=None, load_env=True, keep_alive=True):
super().__init__(defaults or {})
self.LOGO = """
▄▄▄▄▄
@@ -141,6 +141,7 @@ class Config(dict):
"""
self.REQUEST_MAX_SIZE = 100000000 # 100 megababies
self.REQUEST_TIMEOUT = 60 # 60 seconds
self.KEEP_ALIVE = keep_alive
if load_env:
self.load_environment_vars()
@@ -208,11 +209,11 @@ class Config(dict):
self[key] = getattr(obj, key)
def load_environment_vars(self):
"""
Looks for any SANIC_ prefixed environment variables and applies
them to the configuration if present.
"""
for k, v in os.environ.items():
"""
Looks for any SANIC_ prefixed environment variables and applies
them to the configuration if present.
"""
if k.startswith(SANIC_PREFIX):
_, config_key = k.split(SANIC_PREFIX, 1)
self[config_key] = v

View File

@@ -78,9 +78,10 @@ class Request(dict):
:return: token related to request
"""
auth_header = self.headers.get('Authorization')
if auth_header is not None:
return auth_header.split()[1]
return auth_header
if 'Token ' in auth_header:
return auth_header.partition('Token ')[-1]
else:
return auth_header
@property
def form(self):

View File

@@ -210,7 +210,7 @@ class HTTPResponse(BaseHTTPResponse):
# Speeds up response rate 6% over pulling from all
status = COMMON_STATUS_CODES.get(self.status)
if not status:
status = ALL_STATUS_CODES.get(self.status)
status = ALL_STATUS_CODES.get(self.status, b'UNKNOWN RESPONSE')
return (b'HTTP/%b %d %b\r\n'
b'Connection: %b\r\n'

View File

@@ -16,6 +16,7 @@ REGEX_TYPES = {
'int': (int, r'\d+'),
'number': (float, r'[0-9\\.]+'),
'alpha': (str, r'[A-Za-z]+'),
'path': (str, r'[^/].*?'),
}
ROUTER_CACHE_SIZE = 1024
@@ -71,7 +72,8 @@ class Router:
self.routes_always_check = []
self.hosts = set()
def parse_parameter_string(self, parameter_string):
@classmethod
def parse_parameter_string(cls, parameter_string):
"""Parse a parameter string into its constituent name, type, and
pattern
@@ -161,10 +163,10 @@ class Router:
parameters.append(parameter)
# Mark the whole route as unhashable if it has the hash key in it
if re.search('(^|[^^]){1}/', pattern):
if re.search(r'(^|[^^]){1}/', pattern):
properties['unhashable'] = True
# Mark the route as unhashable if it matches the hash key
elif re.search(pattern, '/'):
elif re.search(r'/', pattern):
properties['unhashable'] = True
return '({})'.format(pattern)

View File

@@ -73,7 +73,8 @@ class HttpProtocol(asyncio.Protocol):
def __init__(self, *, loop, request_handler, error_handler,
signal=Signal(), connections=set(), request_timeout=60,
request_max_size=None, request_class=None, has_log=True):
request_max_size=None, request_class=None, has_log=True,
keep_alive=True):
self.loop = loop
self.transport = None
self.request = None
@@ -92,10 +93,13 @@ class HttpProtocol(asyncio.Protocol):
self._timeout_handler = None
self._last_request_time = None
self._request_handler_task = None
self._keep_alive = keep_alive
@property
def keep_alive(self):
return self.parser.should_keep_alive() and not self.signal.stopped
return (self._keep_alive
and not self.signal.stopped
and self.parser.should_keep_alive())
# -------------------------------------------- #
# Connection
@@ -357,7 +361,8 @@ def serve(host, port, request_handler, error_handler, before_start=None,
request_timeout=60, ssl=None, sock=None, request_max_size=None,
reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100,
register_sys_signals=True, run_async=False, connections=None,
signal=Signal(), request_class=None, has_log=True):
signal=Signal(), request_class=None, has_log=True, keep_alive=True):
signal=Signal(), request_class=None, keep_alive=True):
"""Start asynchronous HTTP Server on an individual process.
:param host: Address to host on
@@ -406,7 +411,8 @@ def serve(host, port, request_handler, error_handler, before_start=None,
request_timeout=request_timeout,
request_max_size=request_max_size,
request_class=request_class,
has_log=has_log
has_log=has_log,
keep_alive=keep_alive,
)
server_coroutine = loop.create_server(

View File

@@ -48,14 +48,18 @@ def register(app, uri, file_or_directory, pattern,
# Merge served directory and requested file if provided
# 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
file_path = file_or_directory
root_path = file_path = file_or_directory
if file_uri:
file_path = path.join(
file_or_directory, sub('^[/]*', '', file_uri))
# URL decode the path sent by the browser otherwise we won't be able to
# 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(path.abspath(unquote(root_path))):
raise FileNotFound('File not found',
path=file_or_directory,
relative_url=file_uri)
try:
headers = {}
# Check if the client has been sent this file before

View File

@@ -3,6 +3,7 @@ import sys
import signal
import asyncio
import logging
try:
import ssl
except ImportError:
@@ -50,8 +51,8 @@ class GunicornWorker(base.Worker):
debug=is_debug,
protocol=protocol,
ssl=self.ssl_context,
run_async=True
)
run_async=True)
self._server_settings['signal'] = self.signal
self._server_settings.pop('sock')
trigger_events(self._server_settings.get('before_start', []),
self.loop)
@@ -97,7 +98,6 @@ class GunicornWorker(base.Worker):
self.servers.append(await serve(
sock=sock,
connections=self.connections,
signal=self.signal,
**self._server_settings
))