@SmallTest @Feature({"Cronet"}) @CompareDefaultWithCronet public void testRewind() throws Exception { // Post preserving redirect should fail. URL url = new URL(NativeTestServer.getRedirectToEchoBody()); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.setFixedLengthStreamingMode(TestUtil.UPLOAD_DATA.length); try { OutputStream out = connection.getOutputStream(); out.write(TestUtil.UPLOAD_DATA); } catch (HttpRetryException e) { assertEquals("Cannot retry streamed Http body", e.getMessage()); } connection.disconnect(); }
@Override void sendResponseMessage(HttpURLConnection connection) { InputStream response = null; byte[] responseBody = null; try { int statusCode = connection.getResponseCode(); if(statusCode >= 300) { response = connection.getErrorStream(); if(response != null) responseBody = Util.inputStreamToByteArray(response); sendFailMessage(new HttpRetryException(connection.getResponseMessage(), statusCode), responseBody); } else { response = connection.getInputStream(); if(response != null) responseBody = Util.inputStreamToByteArray(response); sendSuccessMessage(statusCode, responseBody); } } catch(IOException e) { sendFailMessage(e, (byte[])null); } finally { if(response != null) Util.closeQuietly(response); } }
/** * Perform the connection with the given client * and return the response to the relative callback * @param connection the connection to execute and collect the informations */ void sendResponseMessage(HttpURLConnection connection) { String responseBody = null; InputStream response = null; try { int responseCode = connection.getResponseCode(); if(responseCode >= 300) { response = connection.getErrorStream(); if(response != null) responseBody = Util.inputStreamToString(response); sendFailMessage(new HttpRetryException(connection.getResponseMessage(), responseCode), responseBody); } else { response = connection.getInputStream(); if(response != null) responseBody = Util.inputStreamToString(response); sendSuccessMessage(responseCode, responseBody); } } catch(IOException e) { sendFailMessage(e, (String)null); } finally { if(response != null) Util.closeQuietly(response); } }
private void testAuthenticateWithStreamingPost(StreamingMode streamingMode) throws Exception { MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") .setBody("Please authenticate."); server.enqueue(pleaseAuthenticate); Authenticator.setDefault(new RecordingAuthenticator()); urlFactory.setClient(urlFactory.client().newBuilder() .authenticator(new JavaNetAuthenticator()) .build()); connection = urlFactory.open(server.url("/").url()); connection.setDoOutput(true); byte[] requestBody = {'A', 'B', 'C', 'D'}; if (streamingMode == StreamingMode.FIXED_LENGTH) { connection.setFixedLengthStreamingMode(requestBody.length); } else if (streamingMode == StreamingMode.CHUNKED) { connection.setChunkedStreamingMode(0); } OutputStream outputStream = connection.getOutputStream(); outputStream.write(requestBody); outputStream.close(); try { connection.getInputStream(); fail(); } catch (HttpRetryException expected) { } // no authorization header for the request... RecordedRequest request = server.takeRequest(); assertNull(request.getHeader("Authorization")); assertEquals("ABCD", request.getBody().readUtf8()); }
private HttpEngine getResponse() throws IOException { initHttpEngine(); if (this.httpEngine.hasResponse()) { return this.httpEngine; } while (true) { if (execute(true)) { Response response = this.httpEngine.getResponse(); Request followUp = this.httpEngine.followUpRequest(); if (followUp == null) { this.httpEngine.releaseStreamAllocation(); return this.httpEngine; } int i = this.followUpCount + 1; this.followUpCount = i; if (i > 20) { throw new ProtocolException("Too many follow-up requests: " + this .followUpCount); } this.url = followUp.url(); this.requestHeaders = followUp.headers().newBuilder(); Sink requestBody = this.httpEngine.getRequestBody(); if (!followUp.method().equals(this.method)) { requestBody = null; } if (requestBody == null || (requestBody instanceof RetryableSink)) { StreamAllocation streamAllocation = this.httpEngine.close(); if (!this.httpEngine.sameConnection(followUp.httpUrl())) { streamAllocation.release(); streamAllocation = null; } this.httpEngine = newHttpEngine(followUp.method(), streamAllocation, (RetryableSink) requestBody, response); } else { throw new HttpRetryException("Cannot retry streamed HTTP body", this .responseCode); } } } }
public void assertDeserialized(Serializable reference, Serializable test) { HttpRetryException ref = (HttpRetryException) reference; HttpRetryException tst = (HttpRetryException) test; assertEquals("getLocation", ref.getLocation(), tst.getLocation()); assertEquals("responseCode", ref.responseCode(), tst.responseCode()); assertEquals("getReason", ref.getReason(), tst.getReason()); assertEquals("getMessage", ref.getMessage(), tst.getMessage()); }
private void testAuthenticateWithStreamingPost(StreamingMode streamingMode) throws Exception { MockResponse pleaseAuthenticate = new MockResponse() .setResponseCode(401) .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") .setBody("Please authenticate."); server.enqueue(pleaseAuthenticate); server.play(); Authenticator.setDefault(SIMPLE_AUTHENTICATOR); HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); connection.setDoOutput(true); byte[] requestBody = { 'A', 'B', 'C', 'D' }; if (streamingMode == StreamingMode.FIXED_LENGTH) { connection.setFixedLengthStreamingMode(requestBody.length); } else if (streamingMode == StreamingMode.CHUNKED) { connection.setChunkedStreamingMode(0); } OutputStream outputStream = connection.getOutputStream(); outputStream.write(requestBody); outputStream.close(); try { connection.getInputStream(); fail(); } catch (HttpRetryException expected) { } // no authorization header for the request... RecordedRequest request = server.takeRequest(); assertContainsNoneMatching(request.getHeaders(), "Authorization: Basic .*"); assertEquals(Arrays.toString(requestBody), Arrays.toString(request.getBody())); }
private void testAuthenticateWithStreamingPost(StreamingMode streamingMode) throws Exception { MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") .setBody("Please authenticate."); server.enqueue(pleaseAuthenticate); server.play(); Authenticator.setDefault(new RecordingAuthenticator()); connection = client.open(server.getUrl("/")); connection.setDoOutput(true); byte[] requestBody = { 'A', 'B', 'C', 'D' }; if (streamingMode == StreamingMode.FIXED_LENGTH) { connection.setFixedLengthStreamingMode(requestBody.length); } else if (streamingMode == StreamingMode.CHUNKED) { connection.setChunkedStreamingMode(0); } OutputStream outputStream = connection.getOutputStream(); outputStream.write(requestBody); outputStream.close(); try { connection.getInputStream(); fail(); } catch (HttpRetryException expected) { } // no authorization header for the request... RecordedRequest request = server.takeRequest(); assertContainsNoneMatching(request.getHeaders(), "Authorization: Basic .*"); assertEquals(Arrays.toString(requestBody), Arrays.toString(request.getBody())); }
private void testAuthenticateWithStreamingPost(StreamingMode streamingMode) throws Exception { MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") .setBody("Please authenticate."); server.enqueue(pleaseAuthenticate); server.play(); Authenticator.setDefault(new RecordingAuthenticator()); HttpURLConnection connection = client.open(server.getUrl("/")); connection.setDoOutput(true); byte[] requestBody = { 'A', 'B', 'C', 'D' }; if (streamingMode == StreamingMode.FIXED_LENGTH) { connection.setFixedLengthStreamingMode(requestBody.length); } else if (streamingMode == StreamingMode.CHUNKED) { connection.setChunkedStreamingMode(0); } OutputStream outputStream = connection.getOutputStream(); outputStream.write(requestBody); outputStream.close(); try { connection.getInputStream(); fail(); } catch (HttpRetryException expected) { } // no authorization header for the request... RecordedRequest request = server.takeRequest(); assertContainsNoneMatching(request.getHeaders(), "Authorization: Basic .*"); assertEquals(Arrays.toString(requestBody), Arrays.toString(request.getBody())); }
@Override public void rewind(UploadDataSink uploadDataSink) { uploadDataSink.onRewindError( new HttpRetryException("Cannot retry streamed Http body", -1)); }
/** * Aggressively tries to get the final HTTP response, potentially making * many HTTP requests in the process in order to cope with redirects and * authentication. */ private HttpEngine getResponse() throws IOException { initHttpEngine(); if (httpEngine.hasResponse()) { return httpEngine; } while (true) { if (!execute(true)) { continue; } Retry retry = processResponseHeaders(); if (retry == Retry.NONE) { httpEngine.automaticallyReleaseConnectionToPool(); return httpEngine; } // The first request was insufficient. Prepare for another... String retryMethod = method; OutputStream requestBody = httpEngine.getRequestBody(); // Although RFC 2616 10.3.2 specifies that a HTTP_MOVED_PERM // redirect should keep the same method, Chrome, Firefox and the // RI all issue GETs when following any redirect. int responseCode = httpEngine.getResponseCode(); if (responseCode == HTTP_MULT_CHOICE || responseCode == HTTP_MOVED_PERM || responseCode == HTTP_MOVED_TEMP || responseCode == HTTP_SEE_OTHER) { retryMethod = "GET"; requestBody = null; } if (requestBody != null && !(requestBody instanceof RetryableOutputStream)) { throw new HttpRetryException("Cannot retry streamed HTTP body", responseCode); } if (retry == Retry.DIFFERENT_CONNECTION) { httpEngine.automaticallyReleaseConnectionToPool(); } httpEngine.release(false); httpEngine = newHttpEngine(retryMethod, rawRequestHeaders, httpEngine.getConnection(), (RetryableOutputStream) requestBody); if (requestBody == null) { // Drop the Content-Length header when redirected from POST to GET. httpEngine.getRequestHeaders().removeContentLength(); } } }
/** * Aggressively tries to get the final HTTP response, potentially making many HTTP requests in the * process in order to cope with redirects and authentication. */ private HttpEngine getResponse() throws IOException { initHttpEngine(); if (httpEngine.hasResponse()) { return httpEngine; } while (true) { if (!execute(true)) { continue; } Response response = httpEngine.getResponse(); Request followUp = httpEngine.followUpRequest(); if (followUp == null) { httpEngine.releaseStreamAllocation(); return httpEngine; } if (++followUpCount > HttpEngine.MAX_FOLLOW_UPS) { throw new ProtocolException("Too many follow-up requests: " + followUpCount); } // The first request was insufficient. Prepare for another... url = followUp.url().url(); requestHeaders = followUp.headers().newBuilder(); // Although RFC 2616 10.3.2 specifies that a HTTP_MOVED_PERM redirect // should keep the same method, Chrome, Firefox and the RI all issue GETs // when following any redirect. Sink requestBody = httpEngine.getRequestBody(); if (!followUp.method().equals(method)) { requestBody = null; } if (requestBody != null && !(requestBody instanceof RetryableSink)) { throw new HttpRetryException("Cannot retry streamed HTTP body", responseCode); } StreamAllocation streamAllocation = httpEngine.close(); if (!httpEngine.sameConnection(followUp.url())) { streamAllocation.release(); streamAllocation = null; } httpEngine = newHttpEngine(followUp.method(), streamAllocation, (RetryableSink) requestBody, response); } }
/** * Checks for errors from standard read/write requests and performs * occasional status checks. * * @param line the response from the server to analyze * @param caller what we tried to do * @throws CredentialNotFoundException if permission denied * @throws AccountLockedException if the user is blocked * @throws HttpRetryException if the database is locked or action was * throttled and a retry failed * @throws AssertionError if assertions fail * @throws UnknownError in the case of a MediaWiki bug * @since 0.18 */ protected void checkErrorsAndUpdateStatus(String line, String caller) throws IOException, LoginException { // perform various status checks every 100 or so edits if (statuscounter > statusinterval) { // purge user rights in case of desysop or loss of other priviliges user.getUserInfo(); if ((assertion & ASSERT_SYSOP) == ASSERT_SYSOP && !user.isA("sysop")) // assert user.isA("sysop") : "Sysop privileges missing or revoked, or session expired"; throw new AssertionError("Sysop privileges missing or revoked, or session expired"); // check for new messages if ((assertion & ASSERT_NO_MESSAGES) == ASSERT_NO_MESSAGES && hasNewMessages()) // assert !hasNewMessages() : "User has new messages"; throw new AssertionError("User has new messages"); statuscounter = 0; } else statuscounter++; // successful if (line.contains("result=\"Success\"")) return; // empty response from server if (line.isEmpty()) throw new UnknownError("Received empty response from server!"); // assertions if ((assertion & ASSERT_BOT) == ASSERT_BOT && line.contains("error code=\"assertbotfailed\"")) // assert !line.contains("error code=\"assertbotfailed\"") : "Bot privileges missing or revoked, or session expired."; throw new AssertionError("Bot privileges missing or revoked, or session expired."); if ((assertion & ASSERT_USER) == ASSERT_USER && line.contains("error code=\"assertuserfailed\"")) // assert !line.contains("error code=\"assertuserfailed\"") : "Session expired."; throw new AssertionError("Session expired."); if (line.contains("error code=\"permissiondenied\"")) throw new CredentialNotFoundException("Permission denied."); // session expired or stupidity // rate limit (automatic retry), though might be a long one (e.g. email) if (line.contains("error code=\"ratelimited\"")) { log(Level.WARNING, caller, "Server-side throttle hit."); throw new HttpRetryException("Action throttled.", 503); } // blocked! (note here the \" in blocked is deliberately missing for emailUser() if (line.contains("error code=\"blocked") || line.contains("error code=\"autoblocked\"")) { log(Level.SEVERE, caller, "Cannot " + caller + " - user is blocked!."); throw new AccountLockedException("Current user is blocked!"); } // database lock (automatic retry) if (line.contains("error code=\"readonly\"")) { log(Level.WARNING, caller, "Database locked!"); throw new HttpRetryException("Database locked!", 503); } // unknown error if (line.contains("error code=\"unknownerror\"")) throw new UnknownError("Unknown MediaWiki API error, response was " + line); // generic (automatic retry) throw new IOException("MediaWiki error, response was " + line); }
/** * Send PdxInstance list to a GemFire RESTful endpoint * @param payload * @param keys * @return * @throws IOException */ public boolean send(final String keys, final String payload) throws IOException { boolean isPutSuccessful = false; final HttpPut httpPut = new HttpPut(getEndpoint() + keys); // create method url with keys int statusCode = 0; try { HttpEntity entity = EntityBuilder.create() .setText(payload) .setContentType(ContentType.APPLICATION_JSON) .setContentEncoding("gzip") .gzipCompress() .build(); httpPut.setEntity(entity); int retryCount = 0; /** * try sending request <code>MAX_RETRY</code> times with <code>RETRY_INTERVAL</code> interval */ do { try (CloseableHttpResponse putResponse = httpClient.execute(httpPut)) { statusCode = putResponse.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_OK) { isPutSuccessful = true; } else { retryCount++; LOGGER.warning(String.format("HTTP request failed (status %s)- Retry in %d ms %d/%d", statusCode, RETRY_INTERVAL, retryCount, MAX_RETRY)); if (retryCount < MAX_RETRY) { waitBeforeRetry(RETRY_INTERVAL); } } } } while ((!isPutSuccessful) && (retryCount < MAX_RETRY)); if (retryCount >= MAX_RETRY) { throw new HttpRetryException("HTTP request failed after all attempts", statusCode, httpPut.getURI().toString()); } } catch (IOException ex) { LOGGER.log(Level.SEVERE, String.format("Error code: %d %n URI: %s %n Method: %s" , statusCode, httpPut.getRequestLine().getUri(), httpPut.getRequestLine().getMethod()), ex); // rethrow exception throw ex; } finally { // always release connection httpPut.releaseConnection(); } return isPutSuccessful; }