Merge branch 'master' of git://github.com/facebook/tornado

This commit is contained in:
unknown 2010-03-24 08:25:23 -05:00
commit 73fbe2843d
13 changed files with 79 additions and 60 deletions

View File

@ -58,6 +58,7 @@ import urllib
import urlparse import urlparse
import uuid import uuid
_log = logging.getLogger("tornado.auth")
class OpenIdMixin(object): class OpenIdMixin(object):
"""Abstract implementation of OpenID and Attribute Exchange. """Abstract implementation of OpenID and Attribute Exchange.
@ -145,7 +146,7 @@ class OpenIdMixin(object):
def _on_authentication_verified(self, callback, response): def _on_authentication_verified(self, callback, response):
if response.error or u"is_valid:true" not in response.body: if response.error or u"is_valid:true" not in response.body:
logging.warning("Invalid OpenID response: %s", response.error or _log.warning("Invalid OpenID response: %s", response.error or
response.body) response.body)
callback(None) callback(None)
return return
@ -232,12 +233,12 @@ class OAuthMixin(object):
request_key = self.get_argument("oauth_token") request_key = self.get_argument("oauth_token")
request_cookie = self.get_cookie("_oauth_request_token") request_cookie = self.get_cookie("_oauth_request_token")
if not request_cookie: if not request_cookie:
logging.warning("Missing OAuth request token cookie") _log.warning("Missing OAuth request token cookie")
callback(None) callback(None)
return return
cookie_key, cookie_secret = request_cookie.split("|") cookie_key, cookie_secret = request_cookie.split("|")
if cookie_key != request_key: if cookie_key != request_key:
logging.warning("Request token does not match cookie") _log.warning("Request token does not match cookie")
callback(None) callback(None)
return return
token = dict(key=cookie_key, secret=cookie_secret) token = dict(key=cookie_key, secret=cookie_secret)
@ -289,7 +290,7 @@ class OAuthMixin(object):
def _on_access_token(self, callback, response): def _on_access_token(self, callback, response):
if response.error: if response.error:
logging.warning("Could not fetch access token") _log.warning("Could not fetch access token")
callback(None) callback(None)
return return
access_token = _oauth_parse_response(response.body) access_token = _oauth_parse_response(response.body)
@ -441,7 +442,7 @@ class TwitterMixin(OAuthMixin):
def _on_twitter_request(self, callback, response): def _on_twitter_request(self, callback, response):
if response.error: if response.error:
logging.warning("Error response %s fetching %s", response.error, _log.warning("Error response %s fetching %s", response.error,
response.request.url) response.request.url)
callback(None) callback(None)
return return
@ -561,7 +562,7 @@ class FriendFeedMixin(OAuthMixin):
def _on_friendfeed_request(self, callback, response): def _on_friendfeed_request(self, callback, response):
if response.error: if response.error:
logging.warning("Error response %s fetching %s", response.error, _log.warning("Error response %s fetching %s", response.error,
response.request.url) response.request.url)
callback(None) callback(None)
return return
@ -819,17 +820,17 @@ class FacebookMixin(object):
def _parse_response(self, callback, response): def _parse_response(self, callback, response):
if response.error: if response.error:
logging.warning("HTTP error from Facebook: %s", response.error) _log.warning("HTTP error from Facebook: %s", response.error)
callback(None) callback(None)
return return
try: try:
json = escape.json_decode(response.body) json = escape.json_decode(response.body)
except: except:
logging.warning("Invalid JSON from Facebook: %r", response.body) _log.warning("Invalid JSON from Facebook: %r", response.body)
callback(None) callback(None)
return return
if isinstance(json, dict) and json.get("error_code"): if isinstance(json, dict) and json.get("error_code"):
logging.warning("Facebook error: %d: %r", json["error_code"], _log.warning("Facebook error: %d: %r", json["error_code"],
json.get("error_msg")) json.get("error_msg"))
callback(None) callback(None)
return return

View File

@ -29,6 +29,7 @@ import os.path
import sys import sys
import types import types
_log = logging.getLogger('tornado.autoreload')
def start(io_loop=None, check_time=500): def start(io_loop=None, check_time=500):
"""Restarts the process automatically when a module is modified. """Restarts the process automatically when a module is modified.
@ -68,7 +69,7 @@ def _reload_on_update(io_loop, modify_times):
modify_times[path] = modified modify_times[path] = modified
continue continue
if modify_times[path] != modified: if modify_times[path] != modified:
logging.info("%s modified; restarting server", path) _log.info("%s modified; restarting server", path)
_reload_attempted = True _reload_attempted = True
for fd in io_loop._handlers.keys(): for fd in io_loop._handlers.keys():
try: try:

View File

@ -24,6 +24,7 @@ import MySQLdb.cursors
import itertools import itertools
import logging import logging
_log = logging.getLogger('tornado.database')
class Connection(object): class Connection(object):
"""A lightweight wrapper around MySQLdb DB-API connections. """A lightweight wrapper around MySQLdb DB-API connections.
@ -71,7 +72,7 @@ class Connection(object):
try: try:
self.reconnect() self.reconnect()
except: except:
logging.error("Cannot connect to MySQL on %s", self.host, _log.error("Cannot connect to MySQL on %s", self.host,
exc_info=True) exc_info=True)
def __del__(self): def __del__(self):
@ -150,7 +151,7 @@ class Connection(object):
try: try:
return cursor.execute(query, parameters) return cursor.execute(query, parameters)
except OperationalError: except OperationalError:
logging.error("Error connecting to MySQL on %s", self.host) _log.error("Error connecting to MySQL on %s", self.host)
self.close() self.close()
raise raise

View File

@ -29,6 +29,7 @@ import pycurl
import time import time
import weakref import weakref
_log = logging.getLogger('tornado.httpclient')
class HTTPClient(object): class HTTPClient(object):
"""A blocking HTTP client backed with pycurl. """A blocking HTTP client backed with pycurl.
@ -342,7 +343,7 @@ class CurlError(HTTPError):
def _curl_create(max_simultaneous_connections=None): def _curl_create(max_simultaneous_connections=None):
curl = pycurl.Curl() curl = pycurl.Curl()
if logging.getLogger().isEnabledFor(logging.DEBUG): if _log.isEnabledFor(logging.DEBUG):
curl.setopt(pycurl.VERBOSE, 1) curl.setopt(pycurl.VERBOSE, 1)
curl.setopt(pycurl.DEBUGFUNCTION, _curl_debug) curl.setopt(pycurl.DEBUGFUNCTION, _curl_debug)
curl.setopt(pycurl.MAXCONNECTS, max_simultaneous_connections or 5) curl.setopt(pycurl.MAXCONNECTS, max_simultaneous_connections or 5)
@ -417,11 +418,11 @@ def _curl_setup_request(curl, request, buffer, headers):
userpwd = "%s:%s" % (request.auth_username, request.auth_password) userpwd = "%s:%s" % (request.auth_username, request.auth_password)
curl.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC) curl.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
curl.setopt(pycurl.USERPWD, userpwd) curl.setopt(pycurl.USERPWD, userpwd)
logging.info("%s %s (username: %r)", request.method, request.url, _log.info("%s %s (username: %r)", request.method, request.url,
request.auth_username) request.auth_username)
else: else:
curl.unsetopt(pycurl.USERPWD) curl.unsetopt(pycurl.USERPWD)
logging.info("%s %s", request.method, request.url) _log.info("%s %s", request.method, request.url)
if request.prepare_curl_callback is not None: if request.prepare_curl_callback is not None:
request.prepare_curl_callback(curl) request.prepare_curl_callback(curl)
@ -434,7 +435,7 @@ def _curl_header_callback(headers, header_line):
return return
parts = header_line.split(": ") parts = header_line.split(": ")
if len(parts) != 2: if len(parts) != 2:
logging.warning("Invalid HTTP response header line %r", header_line) _log.warning("Invalid HTTP response header line %r", header_line)
return return
name = parts[0].strip() name = parts[0].strip()
value = parts[1].strip() value = parts[1].strip()
@ -447,12 +448,12 @@ def _curl_header_callback(headers, header_line):
def _curl_debug(debug_type, debug_msg): def _curl_debug(debug_type, debug_msg):
debug_types = ('I', '<', '>', '<', '>') debug_types = ('I', '<', '>', '<', '>')
if debug_type == 0: if debug_type == 0:
logging.debug('%s', debug_msg.strip()) _log.debug('%s', debug_msg.strip())
elif debug_type in (1, 2): elif debug_type in (1, 2):
for line in debug_msg.splitlines(): for line in debug_msg.splitlines():
logging.debug('%s %s', debug_types[debug_type], line) _log.debug('%s %s', debug_types[debug_type], line)
elif debug_type == 4: elif debug_type == 4:
logging.debug('%s %r', debug_types[debug_type], debug_msg) _log.debug('%s %r', debug_types[debug_type], debug_msg)
def _utf8(value): def _utf8(value):

View File

@ -40,6 +40,7 @@ try:
except ImportError: except ImportError:
ssl = None ssl = None
_log = logging.getLogger('tornado.httpserver')
class HTTPServer(object): class HTTPServer(object):
"""A non-blocking, single-threaded HTTP server. """A non-blocking, single-threaded HTTP server.
@ -171,16 +172,16 @@ class HTTPServer(object):
try: try:
num_processes = os.sysconf("SC_NPROCESSORS_CONF") num_processes = os.sysconf("SC_NPROCESSORS_CONF")
except ValueError: except ValueError:
logging.error("Could not get num processors from sysconf; " _log.error("Could not get num processors from sysconf; "
"running with one process") "running with one process")
num_processes = 1 num_processes = 1
if num_processes > 1 and ioloop.IOLoop.initialized(): if num_processes > 1 and ioloop.IOLoop.initialized():
logging.error("Cannot run in multiple processes: IOLoop instance " _log.error("Cannot run in multiple processes: IOLoop instance "
"has already been initialized. You cannot call " "has already been initialized. You cannot call "
"IOLoop.instance() before calling start()") "IOLoop.instance() before calling start()")
num_processes = 1 num_processes = 1
if num_processes > 1: if num_processes > 1:
logging.info("Pre-forking %d server processes", num_processes) _log.info("Pre-forking %d server processes", num_processes)
for i in range(num_processes): for i in range(num_processes):
if os.fork() == 0: if os.fork() == 0:
self.io_loop = ioloop.IOLoop.instance() self.io_loop = ioloop.IOLoop.instance()
@ -217,7 +218,7 @@ class HTTPServer(object):
HTTPConnection(stream, address, self.request_callback, HTTPConnection(stream, address, self.request_callback,
self.no_keep_alive, self.xheaders) self.no_keep_alive, self.xheaders)
except: except:
logging.error("Error in connection callback", exc_info=True) _log.error("Error in connection callback", exc_info=True)
class HTTPConnection(object): class HTTPConnection(object):
@ -320,13 +321,13 @@ class HTTPConnection(object):
if not part: continue if not part: continue
eoh = part.find("\r\n\r\n") eoh = part.find("\r\n\r\n")
if eoh == -1: if eoh == -1:
logging.warning("multipart/form-data missing headers") _log.warning("multipart/form-data missing headers")
continue continue
headers = HTTPHeaders.parse(part[:eoh]) headers = HTTPHeaders.parse(part[:eoh])
name_header = headers.get("Content-Disposition", "") name_header = headers.get("Content-Disposition", "")
if not name_header.startswith("form-data;") or \ if not name_header.startswith("form-data;") or \
not part.endswith("\r\n"): not part.endswith("\r\n"):
logging.warning("Invalid multipart/form-data") _log.warning("Invalid multipart/form-data")
continue continue
value = part[eoh + 4:-2] value = part[eoh + 4:-2]
name_values = {} name_values = {}
@ -334,7 +335,7 @@ class HTTPConnection(object):
name, name_value = name_part.strip().split("=", 1) name, name_value = name_part.strip().split("=", 1)
name_values[name] = name_value.strip('"').decode("utf-8") name_values[name] = name_value.strip('"').decode("utf-8")
if not name_values.get("name"): if not name_values.get("name"):
logging.warning("multipart/form-data value missing name") _log.warning("multipart/form-data value missing name")
continue continue
name = name_values["name"] name = name_values["name"]
if name_values.get("filename"): if name_values.get("filename"):

View File

@ -32,6 +32,8 @@ import select
import time import time
_log = logging.getLogger("tornado.ioloop")
class IOLoop(object): class IOLoop(object):
"""A level-triggered I/O loop. """A level-triggered I/O loop.
@ -152,7 +154,7 @@ class IOLoop(object):
try: try:
self._impl.unregister(fd) self._impl.unregister(fd)
except (OSError, IOError): except (OSError, IOError):
logging.debug("Error deleting fd from IOLoop", exc_info=True) _log.debug("Error deleting fd from IOLoop", exc_info=True)
def start(self): def start(self):
"""Starts the I/O loop. """Starts the I/O loop.
@ -196,7 +198,7 @@ class IOLoop(object):
event_pairs = self._impl.poll(poll_timeout) event_pairs = self._impl.poll(poll_timeout)
except Exception, e: except Exception, e:
if e.errno == errno.EINTR: if e.errno == errno.EINTR:
logging.warning("Interrupted system call", exc_info=1) _log.warning("Interrupted system call", exc_info=1)
continue continue
else: else:
raise raise
@ -217,10 +219,10 @@ class IOLoop(object):
# Happens when the client closes the connection # Happens when the client closes the connection
pass pass
else: else:
logging.error("Exception in I/O handler for fd %d", _log.error("Exception in I/O handler for fd %d",
fd, exc_info=True) fd, exc_info=True)
except: except:
logging.error("Exception in I/O handler for fd %d", _log.error("Exception in I/O handler for fd %d",
fd, exc_info=True) fd, exc_info=True)
# reset the stopped flag so another start/stop pair can be issued # reset the stopped flag so another start/stop pair can be issued
self._stopped = False self._stopped = False
@ -288,7 +290,7 @@ class IOLoop(object):
The exception itself is not passed explicitly, but is available The exception itself is not passed explicitly, but is available
in sys.exc_info. in sys.exc_info.
""" """
logging.error("Exception in callback %r", callback, exc_info=True) _log.error("Exception in callback %r", callback, exc_info=True)
def _read_waker(self, fd, events): def _read_waker(self, fd, events):
try: try:
@ -308,6 +310,10 @@ class IOLoop(object):
class _Timeout(object): class _Timeout(object):
"""An IOLoop timeout, a UNIX timestamp and a callback""" """An IOLoop timeout, a UNIX timestamp and a callback"""
# Reduce memory overhead when there are lots of pending callbacks
__slots__ = ['deadline', 'callback']
def __init__(self, deadline, callback): def __init__(self, deadline, callback):
self.deadline = deadline self.deadline = deadline
self.callback = callback self.callback = callback
@ -342,7 +348,7 @@ class PeriodicCallback(object):
except (KeyboardInterrupt, SystemExit): except (KeyboardInterrupt, SystemExit):
raise raise
except: except:
logging.error("Error in periodic callback", exc_info=True) _log.error("Error in periodic callback", exc_info=True)
self.start() self.start()
@ -473,5 +479,5 @@ else:
# All other systems # All other systems
import sys import sys
if "linux" in sys.platform: if "linux" in sys.platform:
logging.warning("epoll module not found; using select()") _log.warning("epoll module not found; using select()")
_poll = _Select _poll = _Select

View File

@ -21,6 +21,7 @@ import ioloop
import logging import logging
import socket import socket
_log = logging.getLogger('tornado.iostream')
class IOStream(object): class IOStream(object):
"""A utility class to write to and read from a non-blocking socket. """A utility class to write to and read from a non-blocking socket.
@ -138,7 +139,7 @@ class IOStream(object):
def _handle_events(self, fd, events): def _handle_events(self, fd, events):
if not self.socket: if not self.socket:
logging.warning("Got events for closed stream %d", fd) _log.warning("Got events for closed stream %d", fd)
return return
if events & self.io_loop.READ: if events & self.io_loop.READ:
self._handle_read() self._handle_read()
@ -167,7 +168,7 @@ class IOStream(object):
if e[0] in (errno.EWOULDBLOCK, errno.EAGAIN): if e[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
return return
else: else:
logging.warning("Read error on %d: %s", _log.warning("Read error on %d: %s",
self.socket.fileno(), e) self.socket.fileno(), e)
self.close() self.close()
return return
@ -176,7 +177,7 @@ class IOStream(object):
return return
self._read_buffer += chunk self._read_buffer += chunk
if len(self._read_buffer) >= self.max_buffer_size: if len(self._read_buffer) >= self.max_buffer_size:
logging.error("Reached maximum read buffer size") _log.error("Reached maximum read buffer size")
self.close() self.close()
return return
if self._read_bytes: if self._read_bytes:
@ -204,7 +205,7 @@ class IOStream(object):
if e[0] in (errno.EWOULDBLOCK, errno.EAGAIN): if e[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
break break
else: else:
logging.warning("Write error on %d: %s", _log.warning("Write error on %d: %s",
self.socket.fileno(), e) self.socket.fileno(), e)
self.close() self.close()
return return

View File

@ -45,6 +45,7 @@ _default_locale = "en_US"
_translations = {} _translations = {}
_supported_locales = frozenset([_default_locale]) _supported_locales = frozenset([_default_locale])
_log = logging.getLogger('tornado.locale')
def get(*locale_codes): def get(*locale_codes):
"""Returns the closest match for the given locale codes. """Returns the closest match for the given locale codes.
@ -105,7 +106,7 @@ def load_translations(directory):
if not path.endswith(".csv"): continue if not path.endswith(".csv"): continue
locale, extension = path.split(".") locale, extension = path.split(".")
if locale not in LOCALE_NAMES: if locale not in LOCALE_NAMES:
logging.error("Unrecognized locale %r (path: %s)", locale, _log.error("Unrecognized locale %r (path: %s)", locale,
os.path.join(directory, path)) os.path.join(directory, path))
continue continue
f = open(os.path.join(directory, path), "r") f = open(os.path.join(directory, path), "r")
@ -119,13 +120,13 @@ def load_translations(directory):
else: else:
plural = "unknown" plural = "unknown"
if plural not in ("plural", "singular", "unknown"): if plural not in ("plural", "singular", "unknown"):
logging.error("Unrecognized plural indicator %r in %s line %d", _log.error("Unrecognized plural indicator %r in %s line %d",
plural, path, i + 1) plural, path, i + 1)
continue continue
_translations[locale].setdefault(plural, {})[english] = translation _translations[locale].setdefault(plural, {})[english] = translation
f.close() f.close()
_supported_locales = frozenset(_translations.keys() + [_default_locale]) _supported_locales = frozenset(_translations.keys() + [_default_locale])
logging.info("Supported locales: %s", sorted(_supported_locales)) _log.info("Supported locales: %s", sorted(_supported_locales))
def get_supported_locales(cls): def get_supported_locales(cls):

View File

@ -49,6 +49,7 @@ for define() below.
""" """
import datetime import datetime
import logging
import logging.handlers import logging.handlers
import re import re
import sys import sys

View File

@ -88,6 +88,7 @@ import logging
import os.path import os.path
import re import re
_log = logging.getLogger('tornado.template')
class Template(object): class Template(object):
"""A compiled template. """A compiled template.
@ -108,7 +109,7 @@ class Template(object):
self.compiled = compile(self.code, self.name, "exec") self.compiled = compile(self.code, self.name, "exec")
except: except:
formatted_code = _format_code(self.code).rstrip() formatted_code = _format_code(self.code).rstrip()
logging.error("%s code:\n%s", self.name, formatted_code) _log.error("%s code:\n%s", self.name, formatted_code)
raise raise
def generate(self, **kwargs): def generate(self, **kwargs):
@ -127,7 +128,7 @@ class Template(object):
return execute() return execute()
except: except:
formatted_code = _format_code(self.code).rstrip() formatted_code = _format_code(self.code).rstrip()
logging.error("%s code:\n%s", self.name, formatted_code) _log.error("%s code:\n%s", self.name, formatted_code)
raise raise
def _generate_python(self, loader, compress_whitespace): def _generate_python(self, loader, compress_whitespace):

View File

@ -70,6 +70,7 @@ import urllib
import urlparse import urlparse
import uuid import uuid
_log = logging.getLogger('tornado.web')
class RequestHandler(object): class RequestHandler(object):
"""Subclass this class and define get() or post() to make a handler. """Subclass this class and define get() or post() to make a handler.
@ -285,11 +286,11 @@ class RequestHandler(object):
else: else:
signature = self._cookie_signature(parts[0], parts[1]) signature = self._cookie_signature(parts[0], parts[1])
if not _time_independent_equals(parts[2], signature): if not _time_independent_equals(parts[2], signature):
logging.warning("Invalid cookie signature %r", value) _log.warning("Invalid cookie signature %r", value)
return None return None
timestamp = int(parts[1]) timestamp = int(parts[1])
if timestamp < time.time() - 31 * 86400: if timestamp < time.time() - 31 * 86400:
logging.warning("Expired cookie %r", value) _log.warning("Expired cookie %r", value)
return None return None
try: try:
return base64.b64decode(parts[0]) return base64.b64decode(parts[0])
@ -499,7 +500,7 @@ class RequestHandler(object):
for your application. for your application.
""" """
if self._headers_written: if self._headers_written:
logging.error("Cannot send error response after headers written") _log.error("Cannot send error response after headers written")
if not self._finished: if not self._finished:
self.finish() self.finish()
return return
@ -673,7 +674,7 @@ class RequestHandler(object):
hashes[path] = hashlib.md5(f.read()).hexdigest() hashes[path] = hashlib.md5(f.read()).hexdigest()
f.close() f.close()
except: except:
logging.error("Could not open static file %r", path) _log.error("Could not open static file %r", path)
hashes[path] = None hashes[path] = None
base = self.request.protocol + "://" + self.request.host \ base = self.request.protocol + "://" + self.request.host \
if getattr(self, "include_host", False) else "" if getattr(self, "include_host", False) else ""
@ -697,7 +698,7 @@ class RequestHandler(object):
return callback(*args, **kwargs) return callback(*args, **kwargs)
except Exception, e: except Exception, e:
if self._headers_written: if self._headers_written:
logging.error("Exception after headers written", _log.error("Exception after headers written",
exc_info=True) exc_info=True)
else: else:
self._handle_request_exception(e) self._handle_request_exception(e)
@ -742,11 +743,11 @@ class RequestHandler(object):
def _log(self): def _log(self):
if self._status_code < 400: if self._status_code < 400:
log_method = logging.info log_method = _log.info
elif self._status_code < 500: elif self._status_code < 500:
log_method = logging.warning log_method = _log.warning
else: else:
log_method = logging.error log_method = _log.error
request_time = 1000.0 * self.request.request_time() request_time = 1000.0 * self.request.request_time()
log_method("%d %s %.2fms", self._status_code, log_method("%d %s %.2fms", self._status_code,
self._request_summary(), request_time) self._request_summary(), request_time)
@ -760,14 +761,14 @@ class RequestHandler(object):
if e.log_message: if e.log_message:
format = "%d %s: " + e.log_message format = "%d %s: " + e.log_message
args = [e.status_code, self._request_summary()] + list(e.args) args = [e.status_code, self._request_summary()] + list(e.args)
logging.warning(format, *args) _log.warning(format, *args)
if e.status_code not in httplib.responses: if e.status_code not in httplib.responses:
logging.error("Bad HTTP status code: %d", e.status_code) _log.error("Bad HTTP status code: %d", e.status_code)
self.send_error(500, exception=e) self.send_error(500, exception=e)
else: else:
self.send_error(e.status_code, exception=e) self.send_error(e.status_code, exception=e)
else: else:
logging.error("Uncaught exception %s\n%r", self._request_summary(), _log.error("Uncaught exception %s\n%r", self._request_summary(),
self.request, exc_info=e) self.request, exc_info=e)
self.send_error(500, exception=e) self.send_error(500, exception=e)

View File

@ -19,6 +19,8 @@ import logging
import tornado.escape import tornado.escape
import tornado.web import tornado.web
_log = logging.getLogger('tornado.websocket')
class WebSocketHandler(tornado.web.RequestHandler): class WebSocketHandler(tornado.web.RequestHandler):
"""A request handler for HTML 5 Web Sockets. """A request handler for HTML 5 Web Sockets.
@ -114,7 +116,7 @@ class WebSocketHandler(tornado.web.RequestHandler):
try: try:
return callback(*args, **kwargs) return callback(*args, **kwargs)
except Exception, e: except Exception, e:
logging.error("Uncaught exception in %s", _log.error("Uncaught exception in %s",
self.request.path, exc_info=True) self.request.path, exc_info=True)
self.stream.close() self.stream.close()
return wrapper return wrapper

View File

@ -60,6 +60,7 @@ import time
import urllib import urllib
import web import web
_log = logging.getLogger('tornado.wsgi')
class WSGIApplication(web.Application): class WSGIApplication(web.Application):
"""A WSGI-equivalent of web.Application. """A WSGI-equivalent of web.Application.
@ -158,13 +159,13 @@ class HTTPRequest(object):
if not part: continue if not part: continue
eoh = part.find("\r\n\r\n") eoh = part.find("\r\n\r\n")
if eoh == -1: if eoh == -1:
logging.warning("multipart/form-data missing headers") _log.warning("multipart/form-data missing headers")
continue continue
headers = HTTPHeaders.parse(part[:eoh]) headers = HTTPHeaders.parse(part[:eoh])
name_header = headers.get("Content-Disposition", "") name_header = headers.get("Content-Disposition", "")
if not name_header.startswith("form-data;") or \ if not name_header.startswith("form-data;") or \
not part.endswith("\r\n"): not part.endswith("\r\n"):
logging.warning("Invalid multipart/form-data") _log.warning("Invalid multipart/form-data")
continue continue
value = part[eoh + 4:-2] value = part[eoh + 4:-2]
name_values = {} name_values = {}
@ -172,7 +173,7 @@ class HTTPRequest(object):
name, name_value = name_part.strip().split("=", 1) name, name_value = name_part.strip().split("=", 1)
name_values[name] = name_value.strip('"').decode("utf-8") name_values[name] = name_value.strip('"').decode("utf-8")
if not name_values.get("name"): if not name_values.get("name"):
logging.warning("multipart/form-data value missing name") _log.warning("multipart/form-data value missing name")
continue continue
name = name_values["name"] name = name_values["name"]
if name_values.get("filename"): if name_values.get("filename"):
@ -276,11 +277,11 @@ class WSGIContainer(object):
def _log(self, status_code, request): def _log(self, status_code, request):
if status_code < 400: if status_code < 400:
log_method = logging.info log_method = _log.info
elif status_code < 500: elif status_code < 500:
log_method = logging.warning log_method = _log.warning
else: else:
log_method = logging.error log_method = _log.error
request_time = 1000.0 * request.request_time() request_time = 1000.0 * request.request_time()
summary = request.method + " " + request.uri + " (" + \ summary = request.method + " " + request.uri + " (" + \
request.remote_ip + ")" request.remote_ip + ")"