~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/_urllib2_wrappers.py

  • Committer: Vincent Ladeuil
  • Date: 2007-06-20 13:56:21 UTC
  • mto: (2574.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 2575.
  • Revision ID: v.ladeuil+lp@free.fr-20070620135621-x43c0hnmzu0iuo6m
Fix #115209 by issuing a single range request on 400: Bad Request

* bzrlib/transport/http/response.py:
(handle_response): Consider 400 as an indication that too much
ranges were specified.

* bzrlib/transport/http/_urllib2_wrappers.py:
(Request): Add an 'accpeted_errors' parameters describing what
error codes the caller will handle.
(HTTPErrorProcessor): Mention that Request specific accepted error
codes takes precedence.
(HTTPDefaultErrorHandler.http_error_default): Remove dead code.

* bzrlib/transport/http/_urllib.py:
(HttpTransport_urllib._get): Add 400 as an accepted error iff
ranges are specified.
(HttpTransport_urllib._head): Restrict accepted errors.

* bzrlib/transport/http/__init__.py:
(HttpTransportBase._degrade_range_hint,
HttpTransportBase._get_ranges_hinted): Replace _retry_get.
(HttpTransportBase.readv): Simplified and avoid the spurious _get()
issued when _get was successful.

* bzrlib/tests/test_http.py:
(TestLimitedRangeRequestServer,
TestLimitedRangeRequestServer_urllib,
TestLimitedRangeRequestServer_pycurl): Bug #115209 specific tests.

* bzrlib/tests/HTTPTestUtil.py:
(LimitedRangeRequestHandler, LimitedRangeHTTPServer): New test
classes to emulate apache throwing 400: Bad Request when too much
ranges are specified.
(AuthRequestHandler.do_GET): Remove dead code. Yeah, I know,
not related to the bug :-/

Show diffs side-by-side

added added

removed removed

Lines of Context:
153
153
 
154
154
    def __init__(self, method, url, data=None, headers={},
155
155
                 origin_req_host=None, unverifiable=False,
156
 
                 connection=None, parent=None,):
 
156
                 connection=None, parent=None,
 
157
                 accepted_errors=None):
157
158
        urllib2.Request.__init__(self, url, data, headers,
158
159
                                 origin_req_host, unverifiable)
159
160
        self.method = method
160
161
        self.connection = connection
 
162
        self.accepted_errors = accepted_errors
161
163
        # To handle redirections
162
164
        self.parent = parent
163
165
        self.redirected_to = None
1133
1135
    instead, we leave our Transport handle them.
1134
1136
    """
1135
1137
 
 
1138
    accepted_errors = [200, # Ok
 
1139
                       206, # Partial content
 
1140
                       404, # Not found
 
1141
                       ]
 
1142
    """The error codes the caller will handle.
 
1143
 
 
1144
    This can be specialized in the request on a case-by case basis, but the
 
1145
    common cases are covered here.
 
1146
    """
 
1147
 
1136
1148
    def http_response(self, request, response):
1137
1149
        code, msg, hdrs = response.code, response.msg, response.info()
1138
1150
 
1139
 
        if code not in (200, # Ok
1140
 
                        206, # Partial content
1141
 
                        404, # Not found
1142
 
                        ):
 
1151
        accepted_errors = request.accepted_errors
 
1152
        if accepted_errors is None:
 
1153
            accepted_errors = self.accepted_errors
 
1154
 
 
1155
        if code not in accepted_errors:
1143
1156
            response = self.parent.error('http', request, response,
1144
1157
                                         code, msg, hdrs)
1145
1158
        return response
1151
1164
    """Translate common errors into bzr Exceptions"""
1152
1165
 
1153
1166
    def http_error_default(self, req, fp, code, msg, hdrs):
1154
 
        if code == 404:
1155
 
            raise errors.NoSuchFile(req.get_selector(),
1156
 
                                    extra=HTTPError(req.get_full_url(),
1157
 
                                                    code, msg,
1158
 
                                                    hdrs, fp))
1159
 
        elif code == 403:
 
1167
        if code == 403:
1160
1168
            raise errors.TransportError('Server refuses to fullfil the request')
1161
1169
        elif code == 416:
1162
1170
            # We don't know which, but one of the ranges we
1168
1176
                                             'Unable to handle http code %d: %s'
1169
1177
                                             % (code, msg))
1170
1178
 
 
1179
 
1171
1180
class Opener(object):
1172
1181
    """A wrapper around urllib2.build_opener
1173
1182
 
1191
1200
            HTTPSHandler,
1192
1201
            HTTPDefaultErrorHandler,
1193
1202
            )
 
1203
 
1194
1204
        self.open = self._opener.open
1195
1205
        if DEBUG >= 2:
1196
1206
            # When dealing with handler order, it's easy to mess