diff --git a/lib/src/http.dart b/lib/src/http.dart index 3441892fa..9f1101270 100644 --- a/lib/src/http.dart +++ b/lib/src/http.dart @@ -92,39 +92,7 @@ class _PubHttpClient extends http.BaseClient { _logResponse(streamedResponse); - var status = streamedResponse.statusCode; - // 401 responses should be handled by the OAuth2 client. It's very - // unlikely that they'll be returned by non-OAuth2 requests. We also want - // to pass along 400 responses from the token endpoint. - var tokenRequest = streamedResponse.request.url == oauth2.tokenEndpoint; - if (status < 400 || status == 401 || (status == 400 && tokenRequest)) { - return streamedResponse; - } - - if (status == 406 && - request.headers['Accept'] == PUB_API_HEADERS['Accept']) { - fail("Pub ${sdk.version} is incompatible with the current version of " - "${request.url.host}.\n" - "Upgrade pub to the latest version and try again."); - } - - if (status == 500 && - (request.url.host == "pub.dartlang.org" || - request.url.host == "storage.googleapis.com")) { - var message = "HTTP error 500: Internal Server Error at " - "${request.url}."; - - if (request.url.host == "pub.dartlang.org" || - request.url.host == "storage.googleapis.com") { - message += "\nThis is likely a transient error. Please try again " - "later."; - } - - fail(message); - } - - throw new PubHttpException( - await http.Response.fromStream(streamedResponse)); + return streamedResponse; } /// Whether extra metadata headers should be added to [request]. @@ -216,10 +184,48 @@ final _pubClient = new _PubHttpClient(); /// we're waiting for them to come back up. final _retriedHosts = new Set(); +/// Intercepts all requests and throws exceptions if the response was not +/// considered successful. +class _ThrowingClient extends http.BaseClient { + final http.Client _inner; + + _ThrowingClient(this._inner); + + Future send(http.BaseRequest request) async { + final streamedResponse = await _inner.send(request); + + var status = streamedResponse.statusCode; + // 401 responses should be handled by the OAuth2 client. It's very + // unlikely that they'll be returned by non-OAuth2 requests. We also want + // to pass along 400 responses from the token endpoint. + var tokenRequest = streamedResponse.request.url == oauth2.tokenEndpoint; + if (status < 400 || status == 401 || (status == 400 && tokenRequest)) { + return streamedResponse; + } + + if (status == 406 && + request.headers['Accept'] == PUB_API_HEADERS['Accept']) { + fail("Pub ${sdk.version} is incompatible with the current version of " + "${request.url.host}.\n" + "Upgrade pub to the latest version and try again."); + } + + if (status == 500 && + (request.url.host == "pub.dartlang.org" || + request.url.host == "storage.googleapis.com")) { + fail("HTTP error 500: Internal Server Error at ${request.url}.\n" + "This is likely a transient error. Please try again later."); + } + + throw new PubHttpException( + await http.Response.fromStream(streamedResponse)); + } +} + /// The HTTP client to use for all HTTP requests. final httpClient = new ThrottleClient( 16, - new RetryClient(_pubClient, + new _ThrowingClient(new RetryClient(_pubClient, retries: 5, when: (response) => const [502, 503, 504].contains(response.statusCode), delay: (retryCount) { @@ -245,7 +251,7 @@ final httpClient = new ThrottleClient( log.message( "It looks like ${request.url.host} is having some trouble.\n" "Pub will wait for a while before trying to connect again."); - })); + }))); /// The underlying HTTP client wrapped by [httpClient]. http.Client get innerHttpClient => _pubClient._inner;