Merge "HTTP status value naming normalization"
This commit is contained in:
		@@ -36,6 +36,7 @@ from swift.common.utils import get_logger, get_param, hash_path, \
 | 
			
		||||
from swift.common.constraints import ACCOUNT_LISTING_LIMIT, \
 | 
			
		||||
    check_mount, check_float, check_utf8
 | 
			
		||||
from swift.common.db_replicator import ReplicatorRpc
 | 
			
		||||
from swift.common.http import HTTPInsufficientStorage
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DATADIR = 'accounts'
 | 
			
		||||
@@ -70,7 +71,7 @@ class AccountController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), content_type='text/plain',
 | 
			
		||||
                                                    request=req)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        if 'x-timestamp' not in req.headers or \
 | 
			
		||||
                    not check_float(req.headers['x-timestamp']):
 | 
			
		||||
            return HTTPBadRequest(body='Missing timestamp', request=req,
 | 
			
		||||
@@ -90,7 +91,7 @@ class AccountController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), content_type='text/plain',
 | 
			
		||||
                                  request=req)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_account_broker(drive, part, account)
 | 
			
		||||
        if container:   # put account container
 | 
			
		||||
            if 'x-trans-id' in req.headers:
 | 
			
		||||
@@ -149,7 +150,7 @@ class AccountController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), content_type='text/plain',
 | 
			
		||||
                                                    request=req)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_account_broker(drive, part, account)
 | 
			
		||||
        if not container:
 | 
			
		||||
            broker.pending_timeout = 0.1
 | 
			
		||||
@@ -180,7 +181,7 @@ class AccountController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), content_type='text/plain',
 | 
			
		||||
                                                    request=req)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_account_broker(drive, part, account)
 | 
			
		||||
        broker.pending_timeout = 0.1
 | 
			
		||||
        broker.stale_reads_ok = True
 | 
			
		||||
@@ -274,7 +275,7 @@ class AccountController(object):
 | 
			
		||||
                                                    request=req)
 | 
			
		||||
        drive, partition, hash = post_args
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        try:
 | 
			
		||||
            args = simplejson.load(req.environ['wsgi.input'])
 | 
			
		||||
        except ValueError, err:
 | 
			
		||||
@@ -295,7 +296,7 @@ class AccountController(object):
 | 
			
		||||
            return HTTPBadRequest(body='Missing or bad timestamp',
 | 
			
		||||
                request=req, content_type='text/plain')
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_account_broker(drive, part, account)
 | 
			
		||||
        if broker.is_deleted():
 | 
			
		||||
            return HTTPNotFound(request=req)
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ from eventlet.green.httplib import CannotSendRequest
 | 
			
		||||
from swift.common.utils import TRUE_VALUES
 | 
			
		||||
from swift.common import client
 | 
			
		||||
from swift.common import direct_client
 | 
			
		||||
from swift.common.http import HTTP_CONFLICT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ConnectionPool(eventlet.pools.Pool):
 | 
			
		||||
@@ -152,7 +153,7 @@ class BenchDELETE(Bench):
 | 
			
		||||
            try:
 | 
			
		||||
                client.delete_container(self.url, self.token, container)
 | 
			
		||||
            except client.ClientException, e:
 | 
			
		||||
                if e.http_status != 409:
 | 
			
		||||
                if e.http_status != HTTP_CONFLICT:
 | 
			
		||||
                    self._log_status("Unable to delete container '%s'. " \
 | 
			
		||||
                        "Got http status '%d'." % (container, e.http_status))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,8 @@ from eventlet import sleep, Timeout
 | 
			
		||||
from swift.common.bufferedhttp import http_connect
 | 
			
		||||
from swift.common.client import ClientException, json_loads
 | 
			
		||||
from swift.common.utils import normalize_timestamp
 | 
			
		||||
from swift.common.http import HTTP_NO_CONTENT, HTTP_INSUFFICIENT_STORAGE, \
 | 
			
		||||
    is_success, is_server_error
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def quote(value, safe='/'):
 | 
			
		||||
@@ -69,7 +71,7 @@ def direct_get_account(node, part, account, marker=None, limit=None,
 | 
			
		||||
                            'GET', path, query_string=qs)
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        resp.read()
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
            'Account server %s:%s direct GET %s gave status %s' % (node['ip'],
 | 
			
		||||
@@ -81,7 +83,7 @@ def direct_get_account(node, part, account, marker=None, limit=None,
 | 
			
		||||
    resp_headers = {}
 | 
			
		||||
    for header, value in resp.getheaders():
 | 
			
		||||
        resp_headers[header.lower()] = value
 | 
			
		||||
    if resp.status == 204:
 | 
			
		||||
    if resp.status == HTTP_NO_CONTENT:
 | 
			
		||||
        resp.read()
 | 
			
		||||
        return resp_headers, []
 | 
			
		||||
    return resp_headers, json_loads(resp.read())
 | 
			
		||||
@@ -108,7 +110,7 @@ def direct_head_container(node, part, account, container, conn_timeout=5,
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
        resp.read()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
                'Container server %s:%s direct HEAD %s gave status %s' %
 | 
			
		||||
                (node['ip'], node['port'],
 | 
			
		||||
@@ -157,7 +159,7 @@ def direct_get_container(node, part, account, container, marker=None,
 | 
			
		||||
                            'GET', path, query_string=qs)
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        resp.read()
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
            'Container server %s:%s direct GET %s gave stats %s' % (node['ip'],
 | 
			
		||||
@@ -169,7 +171,7 @@ def direct_get_container(node, part, account, container, marker=None,
 | 
			
		||||
    resp_headers = {}
 | 
			
		||||
    for header, value in resp.getheaders():
 | 
			
		||||
        resp_headers[header.lower()] = value
 | 
			
		||||
    if resp.status == 204:
 | 
			
		||||
    if resp.status == HTTP_NO_CONTENT:
 | 
			
		||||
        resp.read()
 | 
			
		||||
        return resp_headers, []
 | 
			
		||||
    return resp_headers, json_loads(resp.read())
 | 
			
		||||
@@ -185,7 +187,7 @@ def direct_delete_container(node, part, account, container, conn_timeout=5,
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
        resp.read()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
                'Container server %s:%s direct DELETE %s gave status %s' %
 | 
			
		||||
                (node['ip'], node['port'],
 | 
			
		||||
@@ -218,7 +220,7 @@ def direct_head_object(node, part, account, container, obj, conn_timeout=5,
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
        resp.read()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
                'Object server %s:%s direct HEAD %s gave status %s' %
 | 
			
		||||
                (node['ip'], node['port'],
 | 
			
		||||
@@ -256,7 +258,7 @@ def direct_get_object(node, part, account, container, obj, conn_timeout=5,
 | 
			
		||||
                'GET', path, headers=headers)
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        resp.read()
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
                'Object server %s:%s direct GET %s gave status %s' %
 | 
			
		||||
@@ -326,7 +328,7 @@ def direct_put_object(node, part, account, container, name, contents,
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
        resp.read()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
                'Object server %s:%s direct PUT %s gave status %s' %
 | 
			
		||||
                (node['ip'], node['port'],
 | 
			
		||||
@@ -361,7 +363,7 @@ def direct_post_object(node, part, account, container, name, headers,
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
        resp.read()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
                'Object server %s:%s direct POST %s gave status %s' %
 | 
			
		||||
                (node['ip'], node['port'],
 | 
			
		||||
@@ -394,7 +396,7 @@ def direct_delete_object(node, part, account, container, obj,
 | 
			
		||||
    with Timeout(response_timeout):
 | 
			
		||||
        resp = conn.getresponse()
 | 
			
		||||
        resp.read()
 | 
			
		||||
    if resp.status < 200 or resp.status >= 300:
 | 
			
		||||
    if not is_success(resp.status):
 | 
			
		||||
        raise ClientException(
 | 
			
		||||
                'Object server %s:%s direct DELETE %s gave status %s' %
 | 
			
		||||
                (node['ip'], node['port'],
 | 
			
		||||
@@ -440,8 +442,8 @@ def retry(func, *args, **kwargs):
 | 
			
		||||
        except ClientException, err:
 | 
			
		||||
            if error_log:
 | 
			
		||||
                error_log(err)
 | 
			
		||||
            if attempts > retries or err.http_status < 500 or \
 | 
			
		||||
                    err.http_status == 507 or err.http_status > 599:
 | 
			
		||||
            if attempts > retries or not is_server_error(err.http_status) or \
 | 
			
		||||
                    err.http_status == HTTP_INSUFFICIENT_STORAGE:
 | 
			
		||||
                raise
 | 
			
		||||
        sleep(backoff)
 | 
			
		||||
        backoff *= 2
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										193
									
								
								swift/common/http.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								swift/common/http.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
# Copyright (c) 2010-2012 OpenStack, LLC.
 | 
			
		||||
#
 | 
			
		||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
# you may not use this file except in compliance with the License.
 | 
			
		||||
# You may obtain a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
# Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
# implied.
 | 
			
		||||
# See the License for the specific language governing permissions and
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
 | 
			
		||||
from webob.exc import HTTPClientError,\
 | 
			
		||||
    HTTPInsufficientStorage as BaseHTTPInsufficientStorage
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HTTPClientDisconnect(HTTPClientError):
 | 
			
		||||
    """
 | 
			
		||||
    subclass of :class:`~HTTPClientError`
 | 
			
		||||
 | 
			
		||||
    This code is introduced to log the case when the connection is closed by
 | 
			
		||||
    client while HTTP server is processing its request
 | 
			
		||||
 | 
			
		||||
    code: 499, title: Client Disconnect
 | 
			
		||||
    """
 | 
			
		||||
    code = 499
 | 
			
		||||
    title = 'Client Disconnect'
 | 
			
		||||
    explanation = (
 | 
			
		||||
        'This code is introduced to log the case when the connection '
 | 
			
		||||
        'is closed by client while HTTP server is processing its request')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HTTPInsufficientStorage(BaseHTTPInsufficientStorage):
 | 
			
		||||
    """
 | 
			
		||||
    subclass of :class:`~HTTPInsufficientStorage`
 | 
			
		||||
 | 
			
		||||
    The server is unable to store the representation needed to
 | 
			
		||||
    complete the request.
 | 
			
		||||
 | 
			
		||||
    code: 507, title: Insufficient Storage
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, drive=None, *args, **kwargs):
 | 
			
		||||
        if drive:
 | 
			
		||||
            self.explanation = ('%s is not mounted' % drive)
 | 
			
		||||
        super(HTTPInsufficientStorage, self).__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_informational(status):
 | 
			
		||||
    """
 | 
			
		||||
    Check if HTTP status code is informational.
 | 
			
		||||
 | 
			
		||||
    :param status: http status code
 | 
			
		||||
    :returns: True if status is successful, else False
 | 
			
		||||
    """
 | 
			
		||||
    return 100 <= status and status <= 199
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_success(status):
 | 
			
		||||
    """
 | 
			
		||||
    Check if HTTP status code is successful.
 | 
			
		||||
 | 
			
		||||
    :param status: http status code
 | 
			
		||||
    :returns: True if status is successful, else False
 | 
			
		||||
    """
 | 
			
		||||
    return 200 <= status and status <= 299
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_redirection(status):
 | 
			
		||||
    """
 | 
			
		||||
    Check if HTTP status code is redirection.
 | 
			
		||||
 | 
			
		||||
    :param status: http status code
 | 
			
		||||
    :returns: True if status is redirection, else False
 | 
			
		||||
    """
 | 
			
		||||
    return 300 <= status and status <= 399
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_client_error(status):
 | 
			
		||||
    """
 | 
			
		||||
    Check if HTTP status code is client error.
 | 
			
		||||
 | 
			
		||||
    :param status: http status code
 | 
			
		||||
    :returns: True if status is client error, else False
 | 
			
		||||
    """
 | 
			
		||||
    return 400 <= status and status <= 499
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_server_error(status):
 | 
			
		||||
    """
 | 
			
		||||
    Check if HTTP status code is server error.
 | 
			
		||||
 | 
			
		||||
    :param status: http status code
 | 
			
		||||
    :returns: True if status is server error, else False
 | 
			
		||||
    """
 | 
			
		||||
    return 500 <= status and status <= 599
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# List of HTTP status codes
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
## 1xx Informational
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
HTTP_CONTINUE = 100
 | 
			
		||||
HTTP_SWITCHING_PROTOCOLS = 101
 | 
			
		||||
HTTP_PROCESSING = 102  # WebDAV
 | 
			
		||||
HTTP_CHECKPOINT = 103
 | 
			
		||||
HTTP_REQUEST_URI_TOO_LONG = 122
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
## 2xx Success
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
HTTP_OK = 200
 | 
			
		||||
HTTP_CREATED = 201
 | 
			
		||||
HTTP_ACCEPTED = 202
 | 
			
		||||
HTTP_NON_AUTHORITATIVE_INFORMATION = 203
 | 
			
		||||
HTTP_NO_CONTENT = 204
 | 
			
		||||
HTTP_RESET_CONTENT = 205
 | 
			
		||||
HTTP_PARTIAL_CONTENT = 206
 | 
			
		||||
HTTP_MULTI_STATUS = 207  # WebDAV
 | 
			
		||||
HTTP_IM_USED = 226
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
## 3xx Redirection
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
HTTP_MULTIPLE_CHOICES = 300
 | 
			
		||||
HTTP_MOVED_PERMANENTLY = 301
 | 
			
		||||
HTTP_FOUND = 302
 | 
			
		||||
HTTP_SEE_OTHER = 303
 | 
			
		||||
HTTP_NOT_MODIFIED = 304
 | 
			
		||||
HTTP_USE_PROXY = 305
 | 
			
		||||
HTTP_SWITCH_PROXY = 306
 | 
			
		||||
HTTP_TEMPORARY_REDIRECT = 307
 | 
			
		||||
HTTP_RESUME_INCOMPLETE = 308
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
## 4xx Client Error
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
HTTP_BAD_REQUEST = 400
 | 
			
		||||
HTTP_UNAUTHORIZED = 401
 | 
			
		||||
HTTP_PAYMENT_REQUIRED = 402
 | 
			
		||||
HTTP_FORBIDDEN = 403
 | 
			
		||||
HTTP_NOT_FOUND = 404
 | 
			
		||||
HTTP_METHOD_NOT_ALLOWED = 405
 | 
			
		||||
HTTP_NOT_ACCEPTABLE = 406
 | 
			
		||||
HTTP_PROXY_AUTHENTICATION_REQUIRED = 407
 | 
			
		||||
HTTP_REQUEST_TIMEOUT = 408
 | 
			
		||||
HTTP_CONFLICT = 409
 | 
			
		||||
HTTP_GONE = 410
 | 
			
		||||
HTTP_LENGTH_REQUIRED = 411
 | 
			
		||||
HTTP_PRECONDITION_FAILED = 412
 | 
			
		||||
HTTP_REQUEST_ENTITY_TOO_LARGE = 413
 | 
			
		||||
HTTP_REQUEST_URI_TOO_LONG = 414
 | 
			
		||||
HTTP_UNSUPPORTED_MEDIA_TYPE = 415
 | 
			
		||||
HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416
 | 
			
		||||
HTTP_EXPECTATION_FAILED = 417
 | 
			
		||||
HTTP_IM_A_TEAPOT = 418
 | 
			
		||||
HTTP_UNPROCESSABLE_ENTITY = 422  # WebDAV
 | 
			
		||||
HTTP_LOCKED = 423  # WebDAV
 | 
			
		||||
HTTP_FAILED_DEPENDENCY = 424  # WebDAV
 | 
			
		||||
HTTP_UNORDERED_COLLECTION = 425
 | 
			
		||||
HTTP_UPGRADE_REQUIED = 426
 | 
			
		||||
HTTP_PRECONDITION_REQUIRED = 428
 | 
			
		||||
HTTP_TOO_MANY_REQUESTS = 429
 | 
			
		||||
HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
 | 
			
		||||
HTTP_NO_RESPONSE = 444
 | 
			
		||||
HTTP_RETRY_WITH = 449
 | 
			
		||||
HTTP_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS = 450
 | 
			
		||||
HTTP_CLIENT_CLOSED_REQUEST = 499
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
## 5xx Server Error
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
HTTP_INTERNAL_SERVER_ERROR = 500
 | 
			
		||||
HTTP_NOT_IMPLEMENTED = 501
 | 
			
		||||
HTTP_BAD_GATEWAY = 502
 | 
			
		||||
HTTP_SERVICE_UNAVAILABLE = 503
 | 
			
		||||
HTTP_GATEWAY_TIMEOUT = 504
 | 
			
		||||
HTTP_VERSION_NOT_SUPPORTED = 505
 | 
			
		||||
HTTP_VARIANT_ALSO_NEGOTIATES = 506
 | 
			
		||||
HTTP_INSUFFICIENT_STORAGE = 507  # WebDAV
 | 
			
		||||
HTTP_BANDWIDTH_LIMIT_EXCEEDED = 509
 | 
			
		||||
HTTP_NOT_EXTENDED = 510
 | 
			
		||||
HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511
 | 
			
		||||
HTTP_NETWORK_READ_TIMEOUT_ERROR = 598     # not used in RFC
 | 
			
		||||
HTTP_NETWORK_CONNECT_TIMEOUT_ERROR = 599  # not used in RFC
 | 
			
		||||
@@ -112,6 +112,7 @@ from urllib import quote, unquote
 | 
			
		||||
 | 
			
		||||
from swift.common.utils import get_logger, streq_const_time
 | 
			
		||||
from swift.common.wsgi import make_pre_authed_env
 | 
			
		||||
from swift.common.http import HTTP_BAD_REQUEST
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#: The size of data to read from the form at any given time.
 | 
			
		||||
@@ -324,7 +325,7 @@ class FormPost(object):
 | 
			
		||||
                    return self._translate_form(env, start_response,
 | 
			
		||||
                                                attrs['boundary'])
 | 
			
		||||
            except (FormInvalid, EOFError), err:
 | 
			
		||||
                self._log_request(env, 400)
 | 
			
		||||
                self._log_request(env, HTTP_BAD_REQUEST)
 | 
			
		||||
                body = 'FormPost: %s' % err
 | 
			
		||||
                start_response('400 Bad Request',
 | 
			
		||||
                    (('Content-Type', 'text/plain'),
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,7 @@ from swift.common.utils import cache_from_env, get_logger, human_readable, \
 | 
			
		||||
                               split_path, TRUE_VALUES
 | 
			
		||||
from swift.common.wsgi import make_pre_authed_env, make_pre_authed_request, \
 | 
			
		||||
                              WSGIContext
 | 
			
		||||
from swift.common.http import is_success, is_redirection, HTTP_NOT_FOUND
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def quote(value, safe='/'):
 | 
			
		||||
@@ -183,7 +184,7 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
                '/%s/%s/%s/%s%s' % (self.version, self.account, self.container,
 | 
			
		||||
                                    self._get_status_int(), self._error),
 | 
			
		||||
                self.agent))
 | 
			
		||||
        if self._get_status_int() // 100 == 2:
 | 
			
		||||
        if is_success(self._get_status_int()):
 | 
			
		||||
            start_response(save_response_status, self._response_headers,
 | 
			
		||||
                           self._response_exc_info)
 | 
			
		||||
            return resp
 | 
			
		||||
@@ -213,7 +214,7 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
        resp = make_pre_authed_request(env, 'HEAD',
 | 
			
		||||
                '/%s/%s/%s' % (self.version, self.account, self.container),
 | 
			
		||||
                agent=self.agent).get_response(self.app)
 | 
			
		||||
        if resp.status_int // 100 == 2:
 | 
			
		||||
        if is_success(resp.status_int):
 | 
			
		||||
            self._index = \
 | 
			
		||||
                resp.headers.get('x-container-meta-web-index', '').strip()
 | 
			
		||||
            self._error = \
 | 
			
		||||
@@ -249,7 +250,7 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
        else:
 | 
			
		||||
            prefix = ''
 | 
			
		||||
        resp = self._app_call(tmp_env)
 | 
			
		||||
        if self._get_status_int() // 100 != 2:
 | 
			
		||||
        if not is_success(self._get_status_int()):
 | 
			
		||||
            return self._error_response(resp, env, start_response)
 | 
			
		||||
        listing = None
 | 
			
		||||
        body = ''.join(resp)
 | 
			
		||||
@@ -363,9 +364,10 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
        tmp_env['PATH_INFO'] += self._index
 | 
			
		||||
        resp = self._app_call(tmp_env)
 | 
			
		||||
        status_int = self._get_status_int()
 | 
			
		||||
        if status_int == 404:
 | 
			
		||||
        if status_int == HTTP_NOT_FOUND:
 | 
			
		||||
            return self._listing(env, start_response)
 | 
			
		||||
        elif self._get_status_int() // 100 not in (2, 3):
 | 
			
		||||
        elif not is_success(self._get_status_int()) or \
 | 
			
		||||
             not is_redirection(self._get_status_int()):
 | 
			
		||||
            return self._error_response(resp, env, start_response)
 | 
			
		||||
        start_response(self._response_status, self._response_headers,
 | 
			
		||||
                       self._response_exc_info)
 | 
			
		||||
@@ -384,16 +386,16 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
            '%s StaticWeb' % env.get('HTTP_USER_AGENT')
 | 
			
		||||
        resp = self._app_call(tmp_env)
 | 
			
		||||
        status_int = self._get_status_int()
 | 
			
		||||
        if status_int // 100 in (2, 3):
 | 
			
		||||
        if is_success(status_int) or is_redirection(status_int):
 | 
			
		||||
            start_response(self._response_status, self._response_headers,
 | 
			
		||||
                           self._response_exc_info)
 | 
			
		||||
            return resp
 | 
			
		||||
        if status_int != 404:
 | 
			
		||||
        if status_int != HTTP_NOT_FOUND:
 | 
			
		||||
            return self._error_response(resp, env, start_response)
 | 
			
		||||
        self._get_container_info(env)
 | 
			
		||||
        if not self._listings and not self._index:
 | 
			
		||||
            return self.app(env, start_response)
 | 
			
		||||
        status_int = 404
 | 
			
		||||
        status_int = HTTP_NOT_FOUND
 | 
			
		||||
        if self._index:
 | 
			
		||||
            tmp_env = dict(env)
 | 
			
		||||
            tmp_env['HTTP_USER_AGENT'] = \
 | 
			
		||||
@@ -403,7 +405,7 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
            tmp_env['PATH_INFO'] += self._index
 | 
			
		||||
            resp = self._app_call(tmp_env)
 | 
			
		||||
            status_int = self._get_status_int()
 | 
			
		||||
            if status_int // 100 in (2, 3):
 | 
			
		||||
            if is_success(status_int) or is_redirection(status_int):
 | 
			
		||||
                if env['PATH_INFO'][-1] != '/':
 | 
			
		||||
                    resp = HTTPMovedPermanently(
 | 
			
		||||
                        location=env['PATH_INFO'] + '/')
 | 
			
		||||
@@ -412,7 +414,7 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
                start_response(self._response_status, self._response_headers,
 | 
			
		||||
                               self._response_exc_info)
 | 
			
		||||
                return resp
 | 
			
		||||
        if status_int == 404:
 | 
			
		||||
        if status_int == HTTP_NOT_FOUND:
 | 
			
		||||
            if env['PATH_INFO'][-1] != '/':
 | 
			
		||||
                tmp_env = make_pre_authed_env(env, 'GET',
 | 
			
		||||
                            '/%s/%s/%s' % (self.version, self.account,
 | 
			
		||||
@@ -422,7 +424,7 @@ class _StaticWebContext(WSGIContext):
 | 
			
		||||
                    '=/&limit=1&prefix=%s' % quote(self.obj + '/')
 | 
			
		||||
                resp = self._app_call(tmp_env)
 | 
			
		||||
                body = ''.join(resp)
 | 
			
		||||
                if self._get_status_int() // 100 != 2 or not body or \
 | 
			
		||||
                if not is_success(self._get_status_int()) or not body or \
 | 
			
		||||
                        not json.loads(body):
 | 
			
		||||
                    resp = HTTPNotFound()(env, self._start_response)
 | 
			
		||||
                    return self._error_response(resp, env, start_response)
 | 
			
		||||
 
 | 
			
		||||
@@ -60,6 +60,9 @@ from simplejson import loads
 | 
			
		||||
 | 
			
		||||
from swift.common.utils import split_path
 | 
			
		||||
from swift.common.wsgi import WSGIContext
 | 
			
		||||
from swift.common.http import HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED, \
 | 
			
		||||
    HTTP_NO_CONTENT, HTTP_BAD_REQUEST, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, \
 | 
			
		||||
    HTTP_NOT_FOUND, HTTP_CONFLICT, is_success
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MAX_BUCKET_LISTING = 1000
 | 
			
		||||
@@ -74,24 +77,24 @@ def get_err_response(code):
 | 
			
		||||
    """
 | 
			
		||||
    error_table = {
 | 
			
		||||
        'AccessDenied':
 | 
			
		||||
            (403, 'Access denied'),
 | 
			
		||||
            (HTTP_FORBIDDEN, 'Access denied'),
 | 
			
		||||
        'BucketAlreadyExists':
 | 
			
		||||
            (409, 'The requested bucket name is not available'),
 | 
			
		||||
            (HTTP_CONFLICT, 'The requested bucket name is not available'),
 | 
			
		||||
        'BucketNotEmpty':
 | 
			
		||||
            (409, 'The bucket you tried to delete is not empty'),
 | 
			
		||||
            (HTTP_CONFLICT, 'The bucket you tried to delete is not empty'),
 | 
			
		||||
        'InvalidArgument':
 | 
			
		||||
            (400, 'Invalid Argument'),
 | 
			
		||||
            (HTTP_BAD_REQUEST, 'Invalid Argument'),
 | 
			
		||||
        'InvalidBucketName':
 | 
			
		||||
            (400, 'The specified bucket is not valid'),
 | 
			
		||||
            (HTTP_BAD_REQUEST, 'The specified bucket is not valid'),
 | 
			
		||||
        'InvalidURI':
 | 
			
		||||
            (400, 'Could not parse the specified URI'),
 | 
			
		||||
            (HTTP_BAD_REQUEST, 'Could not parse the specified URI'),
 | 
			
		||||
        'NoSuchBucket':
 | 
			
		||||
            (404, 'The specified bucket does not exist'),
 | 
			
		||||
            (HTTP_NOT_FOUND, 'The specified bucket does not exist'),
 | 
			
		||||
        'SignatureDoesNotMatch':
 | 
			
		||||
            (403, 'The calculated request signature does not match '\
 | 
			
		||||
            'your provided one'),
 | 
			
		||||
            (HTTP_FORBIDDEN, 'The calculated request signature does not '\
 | 
			
		||||
            'match your provided one'),
 | 
			
		||||
        'NoSuchKey':
 | 
			
		||||
            (404, 'The resource you requested does not exist')}
 | 
			
		||||
            (HTTP_NOT_FOUND, 'The resource you requested does not exist')}
 | 
			
		||||
 | 
			
		||||
    resp = Response(content_type='text/xml')
 | 
			
		||||
    resp.status = error_table[code][0]
 | 
			
		||||
@@ -169,8 +172,8 @@ class ServiceController(WSGIContext):
 | 
			
		||||
        body_iter = self._app_call(env)
 | 
			
		||||
        status = self._get_status_int()
 | 
			
		||||
 | 
			
		||||
        if status != 200:
 | 
			
		||||
            if status == 401:
 | 
			
		||||
        if status != HTTP_OK:
 | 
			
		||||
            if status == HTTP_UNAUTHORIZED:
 | 
			
		||||
                return get_err_response('AccessDenied')
 | 
			
		||||
            else:
 | 
			
		||||
                return get_err_response('InvalidURI')
 | 
			
		||||
@@ -186,7 +189,8 @@ class ServiceController(WSGIContext):
 | 
			
		||||
            % ("".join(['<Bucket><Name>%s</Name><CreationDate>' \
 | 
			
		||||
                         '2009-02-03T16:45:09.000Z</CreationDate></Bucket>' %
 | 
			
		||||
                         xml_escape(i['name']) for i in containers]))
 | 
			
		||||
        resp = Response(status=200, content_type='application/xml', body=body)
 | 
			
		||||
        resp = Response(status=HTTP_OK, content_type='application/xml',
 | 
			
		||||
            body=body)
 | 
			
		||||
        return resp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -222,10 +226,10 @@ class BucketController(WSGIContext):
 | 
			
		||||
        body_iter = self._app_call(env)
 | 
			
		||||
        status = self._get_status_int()
 | 
			
		||||
 | 
			
		||||
        if status != 200:
 | 
			
		||||
            if status == 401:
 | 
			
		||||
        if status != HTTP_OK:
 | 
			
		||||
            if status == HTTP_UNAUTHORIZED:
 | 
			
		||||
                return get_err_response('AccessDenied')
 | 
			
		||||
            elif status == 404:
 | 
			
		||||
            elif status == HTTP_NOT_FOUND:
 | 
			
		||||
                return get_err_response('NoSuchBucket')
 | 
			
		||||
            else:
 | 
			
		||||
                return get_err_response('InvalidURI')
 | 
			
		||||
@@ -271,17 +275,17 @@ class BucketController(WSGIContext):
 | 
			
		||||
        body_iter = self._app_call(env)
 | 
			
		||||
        status = self._get_status_int()
 | 
			
		||||
 | 
			
		||||
        if status != 201:
 | 
			
		||||
            if status == 401:
 | 
			
		||||
        if status != HTTP_CREATED:
 | 
			
		||||
            if status == HTTP_UNAUTHORIZED:
 | 
			
		||||
                return get_err_response('AccessDenied')
 | 
			
		||||
            elif status == 202:
 | 
			
		||||
            elif status == HTTP_ACCEPTED:
 | 
			
		||||
                return get_err_response('BucketAlreadyExists')
 | 
			
		||||
            else:
 | 
			
		||||
                return get_err_response('InvalidURI')
 | 
			
		||||
 | 
			
		||||
        resp = Response()
 | 
			
		||||
        resp.headers.add('Location', self.container_name)
 | 
			
		||||
        resp.status = 200
 | 
			
		||||
        resp.status = HTTP_OK
 | 
			
		||||
        return resp
 | 
			
		||||
 | 
			
		||||
    def DELETE(self, env, start_response):
 | 
			
		||||
@@ -291,18 +295,18 @@ class BucketController(WSGIContext):
 | 
			
		||||
        body_iter = self._app_call(env)
 | 
			
		||||
        status = self._get_status_int()
 | 
			
		||||
 | 
			
		||||
        if status != 204:
 | 
			
		||||
            if status == 401:
 | 
			
		||||
        if status != HTTP_NO_CONTENT:
 | 
			
		||||
            if status == HTTP_UNAUTHORIZED:
 | 
			
		||||
                return get_err_response('AccessDenied')
 | 
			
		||||
            elif status == 404:
 | 
			
		||||
            elif status == HTTP_NOT_FOUND:
 | 
			
		||||
                return get_err_response('NoSuchBucket')
 | 
			
		||||
            elif status == 409:
 | 
			
		||||
            elif status == HTTP_CONFLICT:
 | 
			
		||||
                return get_err_response('BucketNotEmpty')
 | 
			
		||||
            else:
 | 
			
		||||
                return get_err_response('InvalidURI')
 | 
			
		||||
 | 
			
		||||
        resp = Response()
 | 
			
		||||
        resp.status = 204
 | 
			
		||||
        resp.status = HTTP_NO_CONTENT
 | 
			
		||||
        return resp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -324,7 +328,7 @@ class ObjectController(WSGIContext):
 | 
			
		||||
        status = self._get_status_int()
 | 
			
		||||
        headers = dict(self._response_headers)
 | 
			
		||||
 | 
			
		||||
        if 200 <= status < 300:
 | 
			
		||||
        if is_success(status):
 | 
			
		||||
            if 'QUERY_STRING' in env:
 | 
			
		||||
                args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1))
 | 
			
		||||
            else:
 | 
			
		||||
@@ -342,9 +346,9 @@ class ObjectController(WSGIContext):
 | 
			
		||||
                              'etag', 'last-modified'):
 | 
			
		||||
                    new_hdrs[key] = val
 | 
			
		||||
            return Response(status=status, headers=new_hdrs, app_iter=app_iter)
 | 
			
		||||
        elif status == 401:
 | 
			
		||||
        elif status == HTTP_UNAUTHORIZED:
 | 
			
		||||
            return get_err_response('AccessDenied')
 | 
			
		||||
        elif status == 404:
 | 
			
		||||
        elif status == HTTP_NOT_FOUND:
 | 
			
		||||
            return get_err_response('NoSuchKey')
 | 
			
		||||
        else:
 | 
			
		||||
            return get_err_response('InvalidURI')
 | 
			
		||||
@@ -377,10 +381,10 @@ class ObjectController(WSGIContext):
 | 
			
		||||
        body_iter = self._app_call(env)
 | 
			
		||||
        status = self._get_status_int()
 | 
			
		||||
 | 
			
		||||
        if status != 201:
 | 
			
		||||
            if status == 401:
 | 
			
		||||
        if status != HTTP_CREATED:
 | 
			
		||||
            if status == HTTP_UNAUTHORIZED:
 | 
			
		||||
                return get_err_response('AccessDenied')
 | 
			
		||||
            elif status == 404:
 | 
			
		||||
            elif status == HTTP_NOT_FOUND:
 | 
			
		||||
                return get_err_response('NoSuchBucket')
 | 
			
		||||
            else:
 | 
			
		||||
                return get_err_response('InvalidURI')
 | 
			
		||||
@@ -389,7 +393,7 @@ class ObjectController(WSGIContext):
 | 
			
		||||
            body = '<CopyObjectResult>' \
 | 
			
		||||
                   '<ETag>"%s"</ETag>' \
 | 
			
		||||
                   '</CopyObjectResult>' % self._response_header_value('etag')
 | 
			
		||||
            return Response(status=200, body=body)
 | 
			
		||||
            return Response(status=HTTP_OK, body=body)
 | 
			
		||||
 | 
			
		||||
        return Response(status=200, etag=self._response_header_value('etag'))
 | 
			
		||||
 | 
			
		||||
@@ -400,16 +404,16 @@ class ObjectController(WSGIContext):
 | 
			
		||||
        body_iter = self._app_call(env)
 | 
			
		||||
        status = self._get_status_int()
 | 
			
		||||
 | 
			
		||||
        if status != 204:
 | 
			
		||||
            if status == 401:
 | 
			
		||||
        if status != HTTP_NO_CONTENT:
 | 
			
		||||
            if status == HTTP_UNAUTHORIZED:
 | 
			
		||||
                return get_err_response('AccessDenied')
 | 
			
		||||
            elif status == 404:
 | 
			
		||||
            elif status == HTTP_NOT_FOUND:
 | 
			
		||||
                return get_err_response('NoSuchKey')
 | 
			
		||||
            else:
 | 
			
		||||
                return get_err_response('InvalidURI')
 | 
			
		||||
 | 
			
		||||
        resp = Response()
 | 
			
		||||
        resp.status = 204
 | 
			
		||||
        resp.status = HTTP_NO_CONTENT
 | 
			
		||||
        return resp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPNotFound, \
 | 
			
		||||
from swift.common.middleware.acl import clean_acl, parse_acl, referrer_allowed
 | 
			
		||||
from swift.common.utils import cache_from_env, get_logger, get_remote_client, \
 | 
			
		||||
    split_path, TRUE_VALUES
 | 
			
		||||
from swift.common.http import HTTP_CLIENT_CLOSED_REQUEST
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TempAuth(object):
 | 
			
		||||
@@ -458,7 +459,7 @@ class TempAuth(object):
 | 
			
		||||
        status_int = response.status_int
 | 
			
		||||
        if getattr(req, 'client_disconnect', False) or \
 | 
			
		||||
                getattr(response, 'client_disconnect', False):
 | 
			
		||||
            status_int = 499
 | 
			
		||||
            status_int = HTTP_CLIENT_CLOSED_REQUEST
 | 
			
		||||
        self.logger.info(' '.join(quote(str(x)) for x in (client or '-',
 | 
			
		||||
            req.remote_addr or '-', strftime('%d/%b/%Y/%H/%M/%S', gmtime()),
 | 
			
		||||
            req.method, the_request, req.environ['SERVER_PROTOCOL'],
 | 
			
		||||
 
 | 
			
		||||
@@ -88,6 +88,7 @@ from urlparse import parse_qs
 | 
			
		||||
 | 
			
		||||
from swift.common.utils import get_logger
 | 
			
		||||
from swift.common.wsgi import make_pre_authed_env
 | 
			
		||||
from swift.common.http import HTTP_UNAUTHORIZED
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#: Default headers to remove from incoming requests. Simply a whitespace
 | 
			
		||||
@@ -376,7 +377,7 @@ class TempURL(object):
 | 
			
		||||
        :param start_response: The WSGI start_response hook.
 | 
			
		||||
        :returns: 401 response as per WSGI.
 | 
			
		||||
        """
 | 
			
		||||
        self._log_request(env, 401)
 | 
			
		||||
        self._log_request(env, HTTP_UNAUTHORIZED)
 | 
			
		||||
        body = '401 Unauthorized: Temp URL invalid\n'
 | 
			
		||||
        start_response('401 Unauthorized',
 | 
			
		||||
            [('Content-Type', 'text/plain'),
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,8 @@ from swift.common.constraints import CONTAINER_LISTING_LIMIT, \
 | 
			
		||||
from swift.common.bufferedhttp import http_connect
 | 
			
		||||
from swift.common.exceptions import ConnectionTimeout
 | 
			
		||||
from swift.common.db_replicator import ReplicatorRpc
 | 
			
		||||
from swift.common.http import HTTP_NOT_FOUND, is_success, \
 | 
			
		||||
    HTTPInsufficientStorage
 | 
			
		||||
 | 
			
		||||
DATADIR = 'containers'
 | 
			
		||||
 | 
			
		||||
@@ -119,10 +121,9 @@ class ContainerController(object):
 | 
			
		||||
                with Timeout(self.node_timeout):
 | 
			
		||||
                    account_response = conn.getresponse()
 | 
			
		||||
                    account_response.read()
 | 
			
		||||
                    if account_response.status == 404:
 | 
			
		||||
                    if account_response.status == HTTP_NOT_FOUND:
 | 
			
		||||
                        return HTTPNotFound(request=req)
 | 
			
		||||
                    elif account_response.status < 200 or \
 | 
			
		||||
                            account_response.status > 299:
 | 
			
		||||
                    elif not is_success(account_response.status):
 | 
			
		||||
                        self.logger.error(_('ERROR Account update failed '
 | 
			
		||||
                            'with %(ip)s:%(port)s/%(device)s (will retry '
 | 
			
		||||
                            'later): Response %(status)s %(reason)s'),
 | 
			
		||||
@@ -150,7 +151,7 @@ class ContainerController(object):
 | 
			
		||||
            return HTTPBadRequest(body='Missing timestamp', request=req,
 | 
			
		||||
                        content_type='text/plain')
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_container_broker(drive, part, account, container)
 | 
			
		||||
        if account.startswith(self.auto_create_account_prefix) and obj and \
 | 
			
		||||
                not os.path.exists(broker.db_file):
 | 
			
		||||
@@ -195,7 +196,7 @@ class ContainerController(object):
 | 
			
		||||
            if err:
 | 
			
		||||
                return HTTPBadRequest(err)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        timestamp = normalize_timestamp(req.headers['x-timestamp'])
 | 
			
		||||
        broker = self._get_container_broker(drive, part, account, container)
 | 
			
		||||
        if obj:     # put container object
 | 
			
		||||
@@ -245,7 +246,7 @@ class ContainerController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), content_type='text/plain',
 | 
			
		||||
                                request=req)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_container_broker(drive, part, account, container)
 | 
			
		||||
        broker.pending_timeout = 0.1
 | 
			
		||||
        broker.stale_reads_ok = True
 | 
			
		||||
@@ -273,7 +274,7 @@ class ContainerController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), content_type='text/plain',
 | 
			
		||||
                                request=req)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_container_broker(drive, part, account, container)
 | 
			
		||||
        broker.pending_timeout = 0.1
 | 
			
		||||
        broker.stale_reads_ok = True
 | 
			
		||||
@@ -388,7 +389,7 @@ class ContainerController(object):
 | 
			
		||||
                                request=req)
 | 
			
		||||
        drive, partition, hash = post_args
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        try:
 | 
			
		||||
            args = simplejson.load(req.environ['wsgi.input'])
 | 
			
		||||
        except ValueError, err:
 | 
			
		||||
@@ -414,7 +415,7 @@ class ContainerController(object):
 | 
			
		||||
            if err:
 | 
			
		||||
                return HTTPBadRequest(err)
 | 
			
		||||
        if self.mount_check and not check_mount(self.root, drive):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % drive)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=drive, request=req)
 | 
			
		||||
        broker = self._get_container_broker(drive, part, account, container)
 | 
			
		||||
        if broker.is_deleted():
 | 
			
		||||
            return HTTPNotFound(request=req)
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ from swift.common.db import ContainerBroker
 | 
			
		||||
from swift.common.utils import audit_location_generator, get_logger, \
 | 
			
		||||
    hash_path, TRUE_VALUES, validate_sync_to, whataremyips
 | 
			
		||||
from swift.common.daemon import Daemon
 | 
			
		||||
from swift.common.http import HTTP_UNAUTHORIZED, HTTP_NOT_FOUND
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _Iter2FileLikeObject(object):
 | 
			
		||||
@@ -349,7 +350,7 @@ class ContainerSync(Daemon):
 | 
			
		||||
                                 'x-container-sync-key': sync_key},
 | 
			
		||||
                        proxy=self.proxy)
 | 
			
		||||
                except ClientException, err:
 | 
			
		||||
                    if err.http_status != 404:
 | 
			
		||||
                    if err.http_status != HTTP_NOT_FOUND:
 | 
			
		||||
                        raise
 | 
			
		||||
                self.container_deletes += 1
 | 
			
		||||
            else:
 | 
			
		||||
@@ -376,7 +377,7 @@ class ContainerSync(Daemon):
 | 
			
		||||
                        # non-404 one. We don't want to mistakenly assume the
 | 
			
		||||
                        # object no longer exists just because one says so and
 | 
			
		||||
                        # the others errored for some other reason.
 | 
			
		||||
                        if not exc or exc.http_status == 404:
 | 
			
		||||
                        if not exc or exc.http_status == HTTP_NOT_FOUND:
 | 
			
		||||
                            exc = err
 | 
			
		||||
                if timestamp < looking_for_timestamp:
 | 
			
		||||
                    if exc:
 | 
			
		||||
@@ -398,13 +399,13 @@ class ContainerSync(Daemon):
 | 
			
		||||
                    contents=_Iter2FileLikeObject(body), proxy=self.proxy)
 | 
			
		||||
                self.container_puts += 1
 | 
			
		||||
        except ClientException, err:
 | 
			
		||||
            if err.http_status == 401:
 | 
			
		||||
            if err.http_status == HTTP_UNAUTHORIZED:
 | 
			
		||||
                self.logger.info(_('Unauth %(sync_from)r '
 | 
			
		||||
                    '=> %(sync_to)r'),
 | 
			
		||||
                    {'sync_from': '%s/%s' %
 | 
			
		||||
                        (quote(info['account']), quote(info['container'])),
 | 
			
		||||
                     'sync_to': sync_to})
 | 
			
		||||
            elif err.http_status == 404:
 | 
			
		||||
            elif err.http_status == HTTP_NOT_FOUND:
 | 
			
		||||
                self.logger.info(_('Not found %(sync_from)r '
 | 
			
		||||
                    '=> %(sync_to)r'),
 | 
			
		||||
                    {'sync_from': '%s/%s' %
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,7 @@ from swift.common.exceptions import ConnectionTimeout
 | 
			
		||||
from swift.common.ring import Ring
 | 
			
		||||
from swift.common.utils import get_logger, TRUE_VALUES
 | 
			
		||||
from swift.common.daemon import Daemon
 | 
			
		||||
from swift.common.http import is_success, HTTP_INTERNAL_SERVER_ERROR
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ContainerUpdater(Daemon):
 | 
			
		||||
@@ -214,7 +215,7 @@ class ContainerUpdater(Daemon):
 | 
			
		||||
            successes = 0
 | 
			
		||||
            failures = 0
 | 
			
		||||
            for event in events:
 | 
			
		||||
                if 200 <= event.wait() < 300:
 | 
			
		||||
                if is_success(event.wait()):
 | 
			
		||||
                    successes += 1
 | 
			
		||||
                else:
 | 
			
		||||
                    failures += 1
 | 
			
		||||
@@ -265,7 +266,7 @@ class ContainerUpdater(Daemon):
 | 
			
		||||
            except (Exception, Timeout):
 | 
			
		||||
                self.logger.exception(_('ERROR account update failed with '
 | 
			
		||||
                    '%(ip)s:%(port)s/%(device)s (will retry later): '), node)
 | 
			
		||||
                return 500
 | 
			
		||||
                return HTTP_INTERNAL_SERVER_ERROR
 | 
			
		||||
        with Timeout(self.node_timeout):
 | 
			
		||||
            try:
 | 
			
		||||
                resp = conn.getresponse()
 | 
			
		||||
@@ -275,4 +276,4 @@ class ContainerUpdater(Daemon):
 | 
			
		||||
                if self.logger.getEffectiveLevel() <= logging.DEBUG:
 | 
			
		||||
                    self.logger.exception(
 | 
			
		||||
                        _('Exception with %(ip)s:%(port)s/%(device)s'), node)
 | 
			
		||||
                return 500
 | 
			
		||||
                return HTTP_INTERNAL_SERVER_ERROR
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@ from webob import Request
 | 
			
		||||
 | 
			
		||||
from swift.common.daemon import Daemon
 | 
			
		||||
from swift.common.utils import get_logger
 | 
			
		||||
from swift.common.http import HTTP_NO_CONTENT, HTTP_NOT_FOUND, HTTP_CONFLICT, \
 | 
			
		||||
    HTTP_PRECONDITION_FAILED
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    import simplejson as json
 | 
			
		||||
@@ -161,8 +163,9 @@ class ObjectExpirer(Daemon):
 | 
			
		||||
        the hidden expiration account.
 | 
			
		||||
        """
 | 
			
		||||
        resp = self.get_response('HEAD',
 | 
			
		||||
            '/v1/' + quote(self.expiring_objects_account), {}, (2, 404))
 | 
			
		||||
        if resp.status_int == 404:
 | 
			
		||||
            '/v1/' + quote(self.expiring_objects_account), {},
 | 
			
		||||
            (2, HTTP_NOT_FOUND))
 | 
			
		||||
        if resp.status_int == HTTP_NOT_FOUND:
 | 
			
		||||
            return (0, 0)
 | 
			
		||||
        return (int(resp.headers['x-account-container-count']),
 | 
			
		||||
                int(resp.headers['x-account-object-count']))
 | 
			
		||||
@@ -176,8 +179,8 @@ class ObjectExpirer(Daemon):
 | 
			
		||||
        marker = ''
 | 
			
		||||
        while True:
 | 
			
		||||
            resp = self.get_response('GET', path + '&marker=' + quote(marker),
 | 
			
		||||
                                     {}, (2, 404))
 | 
			
		||||
            if resp.status_int in (204, 404):
 | 
			
		||||
                                     {}, (2, HTTP_NOT_FOUND))
 | 
			
		||||
            if resp.status_int in (HTTP_NO_CONTENT, HTTP_NOT_FOUND):
 | 
			
		||||
                break
 | 
			
		||||
            data = json.loads(resp.body)
 | 
			
		||||
            if not data:
 | 
			
		||||
@@ -198,8 +201,8 @@ class ObjectExpirer(Daemon):
 | 
			
		||||
        marker = ''
 | 
			
		||||
        while True:
 | 
			
		||||
            resp = self.get_response('GET', path + '&marker=' + quote(marker),
 | 
			
		||||
                                     {}, (2, 404))
 | 
			
		||||
            if resp.status_int in (204, 404):
 | 
			
		||||
                                     {}, (2, HTTP_NOT_FOUND))
 | 
			
		||||
            if resp.status_int in (HTTP_NO_CONTENT, HTTP_NOT_FOUND):
 | 
			
		||||
                break
 | 
			
		||||
            data = json.loads(resp.body)
 | 
			
		||||
            if not data:
 | 
			
		||||
@@ -220,7 +223,8 @@ class ObjectExpirer(Daemon):
 | 
			
		||||
                          perform the actual delete.
 | 
			
		||||
        """
 | 
			
		||||
        self.get_response('DELETE', '/v1/%s' % (quote(actual_obj),),
 | 
			
		||||
                          {'X-If-Delete-At': str(timestamp)}, (2, 404, 412))
 | 
			
		||||
                          {'X-If-Delete-At': str(timestamp)},
 | 
			
		||||
                          (2, HTTP_NOT_FOUND, HTTP_PRECONDITION_FAILED))
 | 
			
		||||
 | 
			
		||||
    def delete_object(self, container, obj):
 | 
			
		||||
        """
 | 
			
		||||
@@ -232,7 +236,7 @@ class ObjectExpirer(Daemon):
 | 
			
		||||
        self.get_response('DELETE',
 | 
			
		||||
            '/v1/%s/%s/%s' % (quote(self.expiring_objects_account),
 | 
			
		||||
                              quote(container), quote(obj)),
 | 
			
		||||
            {}, (2, 404))
 | 
			
		||||
            {}, (2, HTTP_NOT_FOUND))
 | 
			
		||||
 | 
			
		||||
    def delete_container(self, container):
 | 
			
		||||
        """
 | 
			
		||||
@@ -243,4 +247,4 @@ class ObjectExpirer(Daemon):
 | 
			
		||||
        self.get_response('DELETE',
 | 
			
		||||
            '/v1/%s/%s' % (quote(self.expiring_objects_account),
 | 
			
		||||
                           quote(container)),
 | 
			
		||||
            {}, (2, 404, 409))
 | 
			
		||||
            {}, (2, HTTP_NOT_FOUND, HTTP_CONFLICT))
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@ from swift.common.utils import whataremyips, unlink_older_than, lock_path, \
 | 
			
		||||
        TRUE_VALUES
 | 
			
		||||
from swift.common.bufferedhttp import http_connect
 | 
			
		||||
from swift.common.daemon import Daemon
 | 
			
		||||
from swift.common.http import HTTP_OK, HTTP_INSUFFICIENT_STORAGE
 | 
			
		||||
 | 
			
		||||
hubs.use_hub('poll')
 | 
			
		||||
 | 
			
		||||
@@ -408,12 +409,12 @@ class ObjectReplicator(Daemon):
 | 
			
		||||
                        resp = http_connect(node['ip'], node['port'],
 | 
			
		||||
                                node['device'], job['partition'], 'REPLICATE',
 | 
			
		||||
                            '', headers={'Content-Length': '0'}).getresponse()
 | 
			
		||||
                        if resp.status == 507:
 | 
			
		||||
                        if resp.status == HTTP_INSUFFICIENT_STORAGE:
 | 
			
		||||
                            self.logger.error(_('%(ip)s/%(device)s responded'
 | 
			
		||||
                                    ' as unmounted'), node)
 | 
			
		||||
                            attempts_left += 1
 | 
			
		||||
                            continue
 | 
			
		||||
                        if resp.status != 200:
 | 
			
		||||
                        if resp.status != HTTP_OK:
 | 
			
		||||
                            self.logger.error(_("Invalid response %(resp)s "
 | 
			
		||||
                                "from %(ip)s"),
 | 
			
		||||
                                {'resp': resp.status, 'ip': node['ip']})
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,8 @@ from swift.common.exceptions import ConnectionTimeout, DiskFileError, \
 | 
			
		||||
    DiskFileNotExist
 | 
			
		||||
from swift.obj.replicator import tpooled_get_hashes, invalidate_hash, \
 | 
			
		||||
    quarantine_renamer
 | 
			
		||||
from swift.common.http import is_success, HTTPInsufficientStorage, \
 | 
			
		||||
    HTTPClientDisconnect
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DATADIR = 'objects'
 | 
			
		||||
@@ -404,7 +406,7 @@ class ObjectController(object):
 | 
			
		||||
                with Timeout(self.node_timeout):
 | 
			
		||||
                    response = conn.getresponse()
 | 
			
		||||
                    response.read()
 | 
			
		||||
                    if 200 <= response.status < 300:
 | 
			
		||||
                    if is_success(response.status):
 | 
			
		||||
                        return
 | 
			
		||||
                    else:
 | 
			
		||||
                        self.logger.error(_('ERROR Container update failed '
 | 
			
		||||
@@ -492,7 +494,7 @@ class ObjectController(object):
 | 
			
		||||
            return HTTPBadRequest(body='X-Delete-At in past', request=request,
 | 
			
		||||
                                  content_type='text/plain')
 | 
			
		||||
        if self.mount_check and not check_mount(self.devices, device):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % device)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=device, request=request)
 | 
			
		||||
        file = DiskFile(self.devices, device, partition, account, container,
 | 
			
		||||
                        obj, self.logger, disk_chunk_size=self.disk_chunk_size)
 | 
			
		||||
 | 
			
		||||
@@ -536,7 +538,7 @@ class ObjectController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), request=request,
 | 
			
		||||
                        content_type='text/plain')
 | 
			
		||||
        if self.mount_check and not check_mount(self.devices, device):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % device)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=device, request=request)
 | 
			
		||||
        if 'x-timestamp' not in request.headers or \
 | 
			
		||||
                    not check_float(request.headers['x-timestamp']):
 | 
			
		||||
            return HTTPBadRequest(body='Missing timestamp', request=request,
 | 
			
		||||
@@ -575,7 +577,7 @@ class ObjectController(object):
 | 
			
		||||
 | 
			
		||||
            if 'content-length' in request.headers and \
 | 
			
		||||
                    int(request.headers['content-length']) != upload_size:
 | 
			
		||||
                return Response(status='499 Client Disconnect')
 | 
			
		||||
                return HTTPClientDisconnect(request=request)
 | 
			
		||||
            etag = etag.hexdigest()
 | 
			
		||||
            if 'etag' in request.headers and \
 | 
			
		||||
                            request.headers['etag'].lower() != etag:
 | 
			
		||||
@@ -625,7 +627,7 @@ class ObjectController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(err), request=request,
 | 
			
		||||
                        content_type='text/plain')
 | 
			
		||||
        if self.mount_check and not check_mount(self.devices, device):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % device)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=device, request=request)
 | 
			
		||||
        file = DiskFile(self.devices, device, partition, account, container,
 | 
			
		||||
                        obj, self.logger, keep_data_fp=True,
 | 
			
		||||
                        disk_chunk_size=self.disk_chunk_size)
 | 
			
		||||
@@ -701,7 +703,7 @@ class ObjectController(object):
 | 
			
		||||
            resp.body = str(err)
 | 
			
		||||
            return resp
 | 
			
		||||
        if self.mount_check and not check_mount(self.devices, device):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % device)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=device, request=request)
 | 
			
		||||
        file = DiskFile(self.devices, device, partition, account, container,
 | 
			
		||||
                        obj, self.logger, disk_chunk_size=self.disk_chunk_size)
 | 
			
		||||
        if file.is_deleted() or ('X-Delete-At' in file.metadata and
 | 
			
		||||
@@ -742,7 +744,7 @@ class ObjectController(object):
 | 
			
		||||
            return HTTPBadRequest(body='Missing timestamp', request=request,
 | 
			
		||||
                        content_type='text/plain')
 | 
			
		||||
        if self.mount_check and not check_mount(self.devices, device):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % device)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=device, request=request)
 | 
			
		||||
        response_class = HTTPNoContent
 | 
			
		||||
        file = DiskFile(self.devices, device, partition, account, container,
 | 
			
		||||
                        obj, self.logger, disk_chunk_size=self.disk_chunk_size)
 | 
			
		||||
@@ -785,7 +787,7 @@ class ObjectController(object):
 | 
			
		||||
            return HTTPBadRequest(body=str(e), request=request,
 | 
			
		||||
                                  content_type='text/plain')
 | 
			
		||||
        if self.mount_check and not check_mount(self.devices, device):
 | 
			
		||||
            return Response(status='507 %s is not mounted' % device)
 | 
			
		||||
            return HTTPInsufficientStorage(drive=device, request=request)
 | 
			
		||||
        path = os.path.join(self.devices, device, DATADIR, partition)
 | 
			
		||||
        if not os.path.exists(path):
 | 
			
		||||
            mkdirs(path)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,8 @@ from swift.common.ring import Ring
 | 
			
		||||
from swift.common.utils import get_logger, renamer, write_pickle
 | 
			
		||||
from swift.common.daemon import Daemon
 | 
			
		||||
from swift.obj.server import ASYNCDIR
 | 
			
		||||
from swift.common.http import is_success, HTTP_NOT_FOUND, \
 | 
			
		||||
    HTTP_INTERNAL_SERVER_ERROR
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ObjectUpdater(Daemon):
 | 
			
		||||
@@ -178,7 +180,7 @@ class ObjectUpdater(Daemon):
 | 
			
		||||
            if node['id'] not in successes:
 | 
			
		||||
                status = self.object_update(node, part, update['op'], obj,
 | 
			
		||||
                                        update['headers'])
 | 
			
		||||
                if not (200 <= status < 300) and status != 404:
 | 
			
		||||
                if not is_success(status) and status != HTTP_NOT_FOUND:
 | 
			
		||||
                    success = False
 | 
			
		||||
                else:
 | 
			
		||||
                    successes.append(node['id'])
 | 
			
		||||
@@ -217,4 +219,4 @@ class ObjectUpdater(Daemon):
 | 
			
		||||
        except (Exception, Timeout):
 | 
			
		||||
            self.logger.exception(_('ERROR with remote server '
 | 
			
		||||
                '%(ip)s:%(port)s/%(device)s'), node)
 | 
			
		||||
        return 500
 | 
			
		||||
        return HTTP_INTERNAL_SERVER_ERROR
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,12 @@ from swift.common.constraints import check_metadata, check_object_creation, \
 | 
			
		||||
from swift.common.exceptions import ChunkReadTimeout, \
 | 
			
		||||
    ChunkWriteTimeout, ConnectionTimeout, ListingIterNotFound, \
 | 
			
		||||
    ListingIterNotAuthorized, ListingIterError
 | 
			
		||||
from swift.common.http import is_informational, is_success, is_redirection, \
 | 
			
		||||
    is_client_error, is_server_error, HTTP_CONTINUE, HTTP_OK, HTTP_CREATED, \
 | 
			
		||||
    HTTP_ACCEPTED, HTTP_PARTIAL_CONTENT, HTTP_MULTIPLE_CHOICES, \
 | 
			
		||||
    HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_REQUESTED_RANGE_NOT_SATISFIABLE, \
 | 
			
		||||
    HTTP_CLIENT_CLOSED_REQUEST, HTTP_INTERNAL_SERVER_ERROR, \
 | 
			
		||||
    HTTP_SERVICE_UNAVAILABLE, HTTP_INSUFFICIENT_STORAGE, HTTPClientDisconnect
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def update_headers(response, headers):
 | 
			
		||||
@@ -181,7 +187,7 @@ class SegmentedIterable(object):
 | 
			
		||||
                self.controller.iter_nodes(partition, nodes,
 | 
			
		||||
                self.controller.app.object_ring), path,
 | 
			
		||||
                self.controller.app.object_ring.replica_count)
 | 
			
		||||
            if resp.status_int // 100 != 2:
 | 
			
		||||
            if not is_success(resp.status_int):
 | 
			
		||||
                raise Exception(_('Could not load object segment %(path)s:' \
 | 
			
		||||
                    ' %(status)s') % {'path': path, 'status': resp.status_int})
 | 
			
		||||
            self.segment_iter = resp.app_iter
 | 
			
		||||
@@ -197,7 +203,7 @@ class SegmentedIterable(object):
 | 
			
		||||
                     'cont': self.controller.container_name,
 | 
			
		||||
                     'obj': self.controller.object_name})
 | 
			
		||||
                err.swift_logged = True
 | 
			
		||||
                self.response.status_int = 503
 | 
			
		||||
                self.response.status_int = HTTP_SERVICE_UNAVAILABLE
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
    def next(self):
 | 
			
		||||
@@ -230,7 +236,7 @@ class SegmentedIterable(object):
 | 
			
		||||
                     'cont': self.controller.container_name,
 | 
			
		||||
                     'obj': self.controller.object_name})
 | 
			
		||||
                err.swift_logged = True
 | 
			
		||||
                self.response.status_int = 503
 | 
			
		||||
                self.response.status_int = HTTP_SERVICE_UNAVAILABLE
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
    def app_iter_range(self, start, stop):
 | 
			
		||||
@@ -291,7 +297,7 @@ class SegmentedIterable(object):
 | 
			
		||||
                     'cont': self.controller.container_name,
 | 
			
		||||
                     'obj': self.controller.object_name})
 | 
			
		||||
                err.swift_logged = True
 | 
			
		||||
                self.response.status_int = 503
 | 
			
		||||
                self.response.status_int = HTTP_SERVICE_UNAVAILABLE
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -402,9 +408,9 @@ class Controller(object):
 | 
			
		||||
            else:
 | 
			
		||||
                result_code = cache_value['status']
 | 
			
		||||
                container_count = cache_value['container_count']
 | 
			
		||||
            if result_code == 200:
 | 
			
		||||
            if result_code == HTTP_OK:
 | 
			
		||||
                return partition, nodes, container_count
 | 
			
		||||
            elif result_code == 404 and not autocreate:
 | 
			
		||||
            elif result_code == HTTP_NOT_FOUND and not autocreate:
 | 
			
		||||
                return None, None, None
 | 
			
		||||
        result_code = 0
 | 
			
		||||
        container_count = 0
 | 
			
		||||
@@ -419,17 +425,17 @@ class Controller(object):
 | 
			
		||||
                with Timeout(self.app.node_timeout):
 | 
			
		||||
                    resp = conn.getresponse()
 | 
			
		||||
                    body = resp.read()
 | 
			
		||||
                    if 200 <= resp.status <= 299:
 | 
			
		||||
                        result_code = 200
 | 
			
		||||
                    if is_success(resp.status):
 | 
			
		||||
                        result_code = HTTP_OK
 | 
			
		||||
                        container_count = int(
 | 
			
		||||
                            resp.getheader('x-account-container-count') or 0)
 | 
			
		||||
                        break
 | 
			
		||||
                    elif resp.status == 404:
 | 
			
		||||
                    elif resp.status == HTTP_NOT_FOUND:
 | 
			
		||||
                        if result_code == 0:
 | 
			
		||||
                            result_code = 404
 | 
			
		||||
                        elif result_code != 404:
 | 
			
		||||
                            result_code = HTTP_NOT_FOUND
 | 
			
		||||
                        elif result_code != HTTP_NOT_FOUND:
 | 
			
		||||
                            result_code = -1
 | 
			
		||||
                    elif resp.status == 507:
 | 
			
		||||
                    elif resp.status == HTTP_INSUFFICIENT_STORAGE:
 | 
			
		||||
                        self.error_limit(node)
 | 
			
		||||
                        continue
 | 
			
		||||
                    else:
 | 
			
		||||
@@ -440,7 +446,7 @@ class Controller(object):
 | 
			
		||||
            except (Exception, Timeout):
 | 
			
		||||
                self.exception_occurred(node, _('Account'),
 | 
			
		||||
                    _('Trying to get account info for %s') % path)
 | 
			
		||||
        if result_code == 404 and autocreate:
 | 
			
		||||
        if result_code == HTTP_NOT_FOUND and autocreate:
 | 
			
		||||
            if len(account) > MAX_ACCOUNT_NAME_LENGTH:
 | 
			
		||||
                return None, None, None
 | 
			
		||||
            headers = {'X-Timestamp': normalize_timestamp(time.time()),
 | 
			
		||||
@@ -449,18 +455,18 @@ class Controller(object):
 | 
			
		||||
            resp = self.make_requests(Request.blank('/v1' + path),
 | 
			
		||||
                self.app.account_ring, partition, 'PUT',
 | 
			
		||||
                path, [headers] * len(nodes))
 | 
			
		||||
            if resp.status_int // 100 != 2:
 | 
			
		||||
            if not is_success(resp.status_int):
 | 
			
		||||
                raise Exception('Could not autocreate account %r' % path)
 | 
			
		||||
            result_code = 200
 | 
			
		||||
        if self.app.memcache and result_code in (200, 404):
 | 
			
		||||
            if result_code == 200:
 | 
			
		||||
            result_code = HTTP_OK
 | 
			
		||||
        if self.app.memcache and result_code in (HTTP_OK, HTTP_NOT_FOUND):
 | 
			
		||||
            if result_code == HTTP_OK:
 | 
			
		||||
                cache_timeout = self.app.recheck_account_existence
 | 
			
		||||
            else:
 | 
			
		||||
                cache_timeout = self.app.recheck_account_existence * 0.1
 | 
			
		||||
            self.app.memcache.set(cache_key,
 | 
			
		||||
                {'status': result_code, 'container_count': container_count},
 | 
			
		||||
                timeout=cache_timeout)
 | 
			
		||||
        if result_code == 200:
 | 
			
		||||
        if result_code == HTTP_OK:
 | 
			
		||||
            return partition, nodes, container_count
 | 
			
		||||
        return None, None, None
 | 
			
		||||
 | 
			
		||||
@@ -488,10 +494,10 @@ class Controller(object):
 | 
			
		||||
                write_acl = cache_value['write_acl']
 | 
			
		||||
                sync_key = cache_value.get('sync_key')
 | 
			
		||||
                versions = cache_value.get('versions')
 | 
			
		||||
                if status == 200:
 | 
			
		||||
                if status == HTTP_OK:
 | 
			
		||||
                    return partition, nodes, read_acl, write_acl, sync_key, \
 | 
			
		||||
                            versions
 | 
			
		||||
                elif status == 404:
 | 
			
		||||
                elif status == HTTP_NOT_FOUND:
 | 
			
		||||
                    return None, None, None, None, None, None
 | 
			
		||||
        if not self.account_info(account, autocreate=account_autocreate)[1]:
 | 
			
		||||
            return None, None, None, None, None, None
 | 
			
		||||
@@ -511,8 +517,8 @@ class Controller(object):
 | 
			
		||||
                with Timeout(self.app.node_timeout):
 | 
			
		||||
                    resp = conn.getresponse()
 | 
			
		||||
                    body = resp.read()
 | 
			
		||||
                    if 200 <= resp.status <= 299:
 | 
			
		||||
                        result_code = 200
 | 
			
		||||
                    if is_success(resp.status):
 | 
			
		||||
                        result_code = HTTP_OK
 | 
			
		||||
                        read_acl = resp.getheader('x-container-read')
 | 
			
		||||
                        write_acl = resp.getheader('x-container-write')
 | 
			
		||||
                        sync_key = resp.getheader('x-container-sync-key')
 | 
			
		||||
@@ -520,12 +526,12 @@ class Controller(object):
 | 
			
		||||
                            resp.getheader('X-Container-Object-Count')
 | 
			
		||||
                        versions = resp.getheader('x-versions-location')
 | 
			
		||||
                        break
 | 
			
		||||
                    elif resp.status == 404:
 | 
			
		||||
                    elif resp.status == HTTP_NOT_FOUND:
 | 
			
		||||
                        if result_code == 0:
 | 
			
		||||
                            result_code = 404
 | 
			
		||||
                        elif result_code != 404:
 | 
			
		||||
                            result_code = HTTP_NOT_FOUND
 | 
			
		||||
                        elif result_code != HTTP_NOT_FOUND:
 | 
			
		||||
                            result_code = -1
 | 
			
		||||
                    elif resp.status == 507:
 | 
			
		||||
                    elif resp.status == HTTP_INSUFFICIENT_STORAGE:
 | 
			
		||||
                        self.error_limit(node)
 | 
			
		||||
                        continue
 | 
			
		||||
                    else:
 | 
			
		||||
@@ -536,8 +542,8 @@ class Controller(object):
 | 
			
		||||
            except (Exception, Timeout):
 | 
			
		||||
                self.exception_occurred(node, _('Container'),
 | 
			
		||||
                    _('Trying to get container info for %s') % path)
 | 
			
		||||
        if self.app.memcache and result_code in (200, 404):
 | 
			
		||||
            if result_code == 200:
 | 
			
		||||
        if self.app.memcache and result_code in (HTTP_OK, HTTP_NOT_FOUND):
 | 
			
		||||
            if result_code == HTTP_OK:
 | 
			
		||||
                cache_timeout = self.app.recheck_container_existence
 | 
			
		||||
            else:
 | 
			
		||||
                cache_timeout = self.app.recheck_container_existence * 0.1
 | 
			
		||||
@@ -549,7 +555,7 @@ class Controller(object):
 | 
			
		||||
                                   'container_size': container_size,
 | 
			
		||||
                                   'versions': versions},
 | 
			
		||||
                                  timeout=cache_timeout)
 | 
			
		||||
        if result_code == 200:
 | 
			
		||||
        if result_code == HTTP_OK:
 | 
			
		||||
            return partition, nodes, read_acl, write_acl, sync_key, versions
 | 
			
		||||
        return None, None, None, None, None, None
 | 
			
		||||
 | 
			
		||||
@@ -579,9 +585,10 @@ class Controller(object):
 | 
			
		||||
                    conn.node = node
 | 
			
		||||
                with Timeout(self.app.node_timeout):
 | 
			
		||||
                    resp = conn.getresponse()
 | 
			
		||||
                    if 200 <= resp.status < 500:
 | 
			
		||||
                    if not is_informational(resp.status) and \
 | 
			
		||||
                       not is_server_error(resp.status):
 | 
			
		||||
                        return resp.status, resp.reason, resp.read()
 | 
			
		||||
                    elif resp.status == 507:
 | 
			
		||||
                    elif resp.status == HTTP_INSUFFICIENT_STORAGE:
 | 
			
		||||
                        self.error_limit(node)
 | 
			
		||||
            except (Exception, Timeout):
 | 
			
		||||
                self.exception_occurred(node, self.server_type,
 | 
			
		||||
@@ -606,7 +613,7 @@ class Controller(object):
 | 
			
		||||
                    head, query_string)
 | 
			
		||||
        response = [resp for resp in pile if resp]
 | 
			
		||||
        while len(response) < ring.replica_count:
 | 
			
		||||
            response.append((503, '', ''))
 | 
			
		||||
            response.append((HTTP_SERVICE_UNAVAILABLE, '', ''))
 | 
			
		||||
        statuses, reasons, bodies = zip(*response)
 | 
			
		||||
        return self.best_response(req, statuses, reasons, bodies,
 | 
			
		||||
                  '%s %s' % (self.server_type, req.method))
 | 
			
		||||
@@ -627,7 +634,7 @@ class Controller(object):
 | 
			
		||||
        """
 | 
			
		||||
        resp = Response(request=req)
 | 
			
		||||
        if len(statuses):
 | 
			
		||||
            for hundred in (200, 300, 400):
 | 
			
		||||
            for hundred in (HTTP_OK, HTTP_MULTIPLE_CHOICES, HTTP_BAD_REQUEST):
 | 
			
		||||
                hstatuses = \
 | 
			
		||||
                    [s for s in statuses if hundred <= s < hundred + 100]
 | 
			
		||||
                if len(hstatuses) > len(statuses) / 2:
 | 
			
		||||
@@ -782,13 +789,14 @@ class Controller(object):
 | 
			
		||||
                    _('Trying to %(method)s %(path)s') %
 | 
			
		||||
                    {'method': req.method, 'path': req.path})
 | 
			
		||||
                continue
 | 
			
		||||
            if possible_source.status == 507:
 | 
			
		||||
            if possible_source.status == HTTP_INSUFFICIENT_STORAGE:
 | 
			
		||||
                self.error_limit(node)
 | 
			
		||||
                continue
 | 
			
		||||
            if 200 <= possible_source.status <= 399:
 | 
			
		||||
            if is_success(possible_source.status) or \
 | 
			
		||||
               is_redirection(possible_source.status):
 | 
			
		||||
                # 404 if we know we don't have a synced copy
 | 
			
		||||
                if not float(possible_source.getheader('X-PUT-Timestamp', 1)):
 | 
			
		||||
                    statuses.append(404)
 | 
			
		||||
                    statuses.append(HTTP_NOT_FOUND)
 | 
			
		||||
                    reasons.append('')
 | 
			
		||||
                    bodies.append('')
 | 
			
		||||
                    possible_source.read()
 | 
			
		||||
@@ -811,13 +819,14 @@ class Controller(object):
 | 
			
		||||
            statuses.append(possible_source.status)
 | 
			
		||||
            reasons.append(possible_source.reason)
 | 
			
		||||
            bodies.append(possible_source.read())
 | 
			
		||||
            if possible_source.status >= 500:
 | 
			
		||||
            if is_server_error(possible_source.status):
 | 
			
		||||
                self.error_occurred(node, _('ERROR %(status)d %(body)s ' \
 | 
			
		||||
                    'From %(type)s Server') %
 | 
			
		||||
                    {'status': possible_source.status,
 | 
			
		||||
                    'body': bodies[-1][:1024], 'type': server_type})
 | 
			
		||||
        if source:
 | 
			
		||||
            if req.method == 'GET' and source.status in (200, 206):
 | 
			
		||||
            if req.method == 'GET' and \
 | 
			
		||||
               source.status in (HTTP_OK, HTTP_PARTIAL_CONTENT):
 | 
			
		||||
                res = Response(request=req, conditional_response=True)
 | 
			
		||||
                res.bytes_transferred = 0
 | 
			
		||||
                res.app_iter = self._make_app_iter(node, source, res)
 | 
			
		||||
@@ -834,7 +843,7 @@ class Controller(object):
 | 
			
		||||
                    res.charset = None
 | 
			
		||||
                    res.content_type = source.getheader('Content-Type')
 | 
			
		||||
                return res
 | 
			
		||||
            elif 200 <= source.status <= 399:
 | 
			
		||||
            elif is_success(source.status) or is_redirection(source.status):
 | 
			
		||||
                res = status_map[source.status](request=req)
 | 
			
		||||
                update_headers(res, source.getheaders())
 | 
			
		||||
                # Used by container sync feature
 | 
			
		||||
@@ -883,9 +892,9 @@ class ObjectController(Controller):
 | 
			
		||||
                aresp = env['swift.authorize'](lreq)
 | 
			
		||||
                if aresp:
 | 
			
		||||
                    raise ListingIterNotAuthorized(aresp)
 | 
			
		||||
            if lresp.status_int == 404:
 | 
			
		||||
            if lresp.status_int == HTTP_NOT_FOUND:
 | 
			
		||||
                raise ListingIterNotFound()
 | 
			
		||||
            elif lresp.status_int // 100 != 2:
 | 
			
		||||
            elif not is_success(lresp.status_int):
 | 
			
		||||
                raise ListingIterError()
 | 
			
		||||
            if not lresp.body:
 | 
			
		||||
                break
 | 
			
		||||
@@ -914,7 +923,7 @@ class ObjectController(Controller):
 | 
			
		||||
        # If we get a 416 Requested Range Not Satisfiable we have to check if
 | 
			
		||||
        # we were actually requesting a manifest and then redo
 | 
			
		||||
        # the range request on the whole object.
 | 
			
		||||
        if resp.status_int == 416:
 | 
			
		||||
        if resp.status_int == HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
 | 
			
		||||
            req_range = req.range
 | 
			
		||||
            req.range = None
 | 
			
		||||
            resp2 = self.GETorHEAD_base(req, _('Object'), partition,
 | 
			
		||||
@@ -1022,7 +1031,7 @@ class ObjectController(Controller):
 | 
			
		||||
            # Older editions returned 202 Accepted on object POSTs, so we'll
 | 
			
		||||
            # convert any 201 Created responses to that for compatibility with
 | 
			
		||||
            # picky clients.
 | 
			
		||||
            if resp.status_int != 201:
 | 
			
		||||
            if resp.status_int != HTTP_CREATED:
 | 
			
		||||
                return resp
 | 
			
		||||
            return HTTPAccepted(request=req)
 | 
			
		||||
        else:
 | 
			
		||||
@@ -1098,10 +1107,10 @@ class ObjectController(Controller):
 | 
			
		||||
                            node['device'], part, 'PUT', path, headers)
 | 
			
		||||
                with Timeout(self.app.node_timeout):
 | 
			
		||||
                    resp = conn.getexpect()
 | 
			
		||||
                if resp.status == 100:
 | 
			
		||||
                if resp.status == HTTP_CONTINUE:
 | 
			
		||||
                    conn.node = node
 | 
			
		||||
                    return conn
 | 
			
		||||
                elif resp.status == 507:
 | 
			
		||||
                elif resp.status == HTTP_INSUFFICIENT_STORAGE:
 | 
			
		||||
                    self.error_limit(node)
 | 
			
		||||
            except:
 | 
			
		||||
                self.exception_occurred(node, _('Object'),
 | 
			
		||||
@@ -1183,7 +1192,7 @@ class ObjectController(Controller):
 | 
			
		||||
        if object_versions and not req.environ.get('swift_versioned_copy'):
 | 
			
		||||
            is_manifest = 'x-object-manifest' in req.headers or \
 | 
			
		||||
                          'x-object-manifest' in hresp.headers
 | 
			
		||||
            if hresp.status_int != 404 and not is_manifest:
 | 
			
		||||
            if hresp.status_int != HTTP_NOT_FOUND and not is_manifest:
 | 
			
		||||
                # This is a version manifest and needs to be handled
 | 
			
		||||
                # differently. First copy the existing data to a new object,
 | 
			
		||||
                # then write the data from this request to the version manifest
 | 
			
		||||
@@ -1206,10 +1215,10 @@ class ObjectController(Controller):
 | 
			
		||||
                copy_req = Request.blank(req.path_info, headers=copy_headers,
 | 
			
		||||
                                environ=copy_environ)
 | 
			
		||||
                copy_resp = self.COPY(copy_req)
 | 
			
		||||
                if copy_resp.status_int // 100 == 4:
 | 
			
		||||
                if is_client_error(copy_resp.status_int):
 | 
			
		||||
                    # missing container or bad permissions
 | 
			
		||||
                    return HTTPPreconditionFailed(request=req)
 | 
			
		||||
                elif copy_resp.status_int // 100 != 2:
 | 
			
		||||
                elif not is_success(copy_resp.status_int):
 | 
			
		||||
                    # could not copy the data, bail
 | 
			
		||||
                    return HTTPServiceUnavailable(request=req)
 | 
			
		||||
 | 
			
		||||
@@ -1238,7 +1247,7 @@ class ObjectController(Controller):
 | 
			
		||||
            self.object_name = src_obj_name
 | 
			
		||||
            self.container_name = src_container_name
 | 
			
		||||
            source_resp = self.GET(source_req)
 | 
			
		||||
            if source_resp.status_int >= 300:
 | 
			
		||||
            if source_resp.status_int >= HTTP_MULTIPLE_CHOICES:
 | 
			
		||||
                return source_resp
 | 
			
		||||
            self.object_name = orig_obj_name
 | 
			
		||||
            self.container_name = orig_container_name
 | 
			
		||||
@@ -1332,12 +1341,12 @@ class ObjectController(Controller):
 | 
			
		||||
            req.client_disconnect = True
 | 
			
		||||
            self.app.logger.exception(
 | 
			
		||||
                _('ERROR Exception causing client disconnect'))
 | 
			
		||||
            return Response(status='499 Client Disconnect')
 | 
			
		||||
            return HTTPClientDisconnect(request=req)
 | 
			
		||||
        if req.content_length and req.bytes_transferred < req.content_length:
 | 
			
		||||
            req.client_disconnect = True
 | 
			
		||||
            self.app.logger.warn(
 | 
			
		||||
                _('Client disconnected without sending enough data'))
 | 
			
		||||
            return Response(status='499 Client Disconnect')
 | 
			
		||||
            return HTTPClientDisconnect(request=req)
 | 
			
		||||
        statuses = []
 | 
			
		||||
        reasons = []
 | 
			
		||||
        bodies = []
 | 
			
		||||
@@ -1349,12 +1358,12 @@ class ObjectController(Controller):
 | 
			
		||||
                    statuses.append(response.status)
 | 
			
		||||
                    reasons.append(response.reason)
 | 
			
		||||
                    bodies.append(response.read())
 | 
			
		||||
                    if response.status >= 500:
 | 
			
		||||
                    if response.status >= HTTP_INTERNAL_SERVER_ERROR:
 | 
			
		||||
                        self.error_occurred(conn.node,
 | 
			
		||||
                            _('ERROR %(status)d %(body)s From Object Server ' \
 | 
			
		||||
                            're: %(path)s') % {'status': response.status,
 | 
			
		||||
                            'body': bodies[-1][:1024], 'path': req.path})
 | 
			
		||||
                    elif 200 <= response.status < 300:
 | 
			
		||||
                    elif is_success(response.status):
 | 
			
		||||
                        etags.add(response.getheader('etag').strip('"'))
 | 
			
		||||
            except (Exception, Timeout):
 | 
			
		||||
                self.exception_occurred(conn.node, _('Object'),
 | 
			
		||||
@@ -1365,7 +1374,7 @@ class ObjectController(Controller):
 | 
			
		||||
            return HTTPServerError(request=req)
 | 
			
		||||
        etag = len(etags) and etags.pop() or None
 | 
			
		||||
        while len(statuses) < len(nodes):
 | 
			
		||||
            statuses.append(503)
 | 
			
		||||
            statuses.append(HTTP_SERVICE_UNAVAILABLE)
 | 
			
		||||
            reasons.append('')
 | 
			
		||||
            bodies.append('')
 | 
			
		||||
        resp = self.best_response(req, statuses, reasons, bodies,
 | 
			
		||||
@@ -1426,10 +1435,10 @@ class ObjectController(Controller):
 | 
			
		||||
                creq = Request.blank(copy_path, headers=copy_headers,
 | 
			
		||||
                                 environ=copy_environ)
 | 
			
		||||
                copy_resp = self.COPY(creq)
 | 
			
		||||
                if copy_resp.status_int // 100 == 4:
 | 
			
		||||
                if is_client_error(copy_resp.status_int):
 | 
			
		||||
                    # some user error, maybe permissions
 | 
			
		||||
                    return HTTPPreconditionFailed(request=req)
 | 
			
		||||
                elif copy_resp.status_int // 100 != 2:
 | 
			
		||||
                elif not is_success(copy_resp.status_int):
 | 
			
		||||
                    # could not copy the data, bail
 | 
			
		||||
                    return HTTPServiceUnavailable(request=req)
 | 
			
		||||
                # reset these because the COPY changed them
 | 
			
		||||
@@ -1666,7 +1675,8 @@ class ContainerController(Controller):
 | 
			
		||||
            self.app.memcache.delete(cache_key)
 | 
			
		||||
        resp = self.make_requests(req, self.app.container_ring,
 | 
			
		||||
                    container_partition, 'DELETE', req.path_info, headers)
 | 
			
		||||
        if resp.status_int == 202:  # Indicates no server had the container
 | 
			
		||||
        # Indicates no server had the container
 | 
			
		||||
        if resp.status_int == HTTP_ACCEPTED:
 | 
			
		||||
            return HTTPNotFound(request=req)
 | 
			
		||||
        return resp
 | 
			
		||||
 | 
			
		||||
@@ -1685,7 +1695,7 @@ class AccountController(Controller):
 | 
			
		||||
        shuffle(nodes)
 | 
			
		||||
        resp = self.GETorHEAD_base(req, _('Account'), partition, nodes,
 | 
			
		||||
                req.path_info.rstrip('/'), self.app.account_ring.replica_count)
 | 
			
		||||
        if resp.status_int == 404 and self.app.account_autocreate:
 | 
			
		||||
        if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
 | 
			
		||||
            if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
 | 
			
		||||
                resp = HTTPBadRequest(request=req)
 | 
			
		||||
                resp.body = 'Account name length of %d longer than %d' % \
 | 
			
		||||
@@ -1698,7 +1708,7 @@ class AccountController(Controller):
 | 
			
		||||
                Request.blank('/v1/' + self.account_name),
 | 
			
		||||
                self.app.account_ring, partition, 'PUT',
 | 
			
		||||
                '/' + self.account_name, [headers] * len(nodes))
 | 
			
		||||
            if resp.status_int // 100 != 2:
 | 
			
		||||
            if not is_success(resp.status_int):
 | 
			
		||||
                raise Exception('Could not autocreate account %r' %
 | 
			
		||||
                                self.account_name)
 | 
			
		||||
            resp = self.GETorHEAD_base(req, _('Account'), partition, nodes,
 | 
			
		||||
@@ -1746,7 +1756,7 @@ class AccountController(Controller):
 | 
			
		||||
        resp = self.make_requests(req, self.app.account_ring,
 | 
			
		||||
            account_partition, 'POST', req.path_info,
 | 
			
		||||
            [headers] * len(accounts))
 | 
			
		||||
        if resp.status_int == 404 and self.app.account_autocreate:
 | 
			
		||||
        if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
 | 
			
		||||
            if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH:
 | 
			
		||||
                resp = HTTPBadRequest(request=req)
 | 
			
		||||
                resp.body = 'Account name length of %d longer than %d' % \
 | 
			
		||||
@@ -1756,7 +1766,7 @@ class AccountController(Controller):
 | 
			
		||||
                Request.blank('/v1/' + self.account_name),
 | 
			
		||||
                self.app.account_ring, account_partition, 'PUT',
 | 
			
		||||
                '/' + self.account_name, [headers] * len(accounts))
 | 
			
		||||
            if resp.status_int // 100 != 2:
 | 
			
		||||
            if not is_success(resp.status_int):
 | 
			
		||||
                raise Exception('Could not autocreate account %r' %
 | 
			
		||||
                                self.account_name)
 | 
			
		||||
        return resp
 | 
			
		||||
@@ -1996,7 +2006,7 @@ class Application(BaseApplication):
 | 
			
		||||
        status_int = response.status_int
 | 
			
		||||
        if getattr(req, 'client_disconnect', False) or \
 | 
			
		||||
                getattr(response, 'client_disconnect', False):
 | 
			
		||||
            status_int = 499
 | 
			
		||||
            status_int = HTTP_CLIENT_CLOSED_REQUEST
 | 
			
		||||
        self.access_logger.info(' '.join(quote(str(x)) for x in (
 | 
			
		||||
                client or '-',
 | 
			
		||||
                req.remote_addr or '-',
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user