@Override public ExecutableHttpRequest prepareRequest(HttpExecuteRequest request) { capturedRequests.add(request.httpRequest()); return new ExecutableHttpRequest() { @Override public HttpExecuteResponse call() { return nextResponse; } @Override public void abort() { } }; }
@Override public HttpExecuteRequest build() { return new HttpExecuteRequest(this); } }
private HttpURLConnection createAndConfigureConnection(HttpExecuteRequest request) { HttpURLConnection connection = connectionFactory.createConnection(request.httpRequest().getUri()); request.httpRequest() .headers() .forEach((key, values) -> values.forEach(value -> connection.setRequestProperty(key, value))); invokeSafely(() -> connection.setRequestMethod(request.httpRequest().method().name())); if (request.contentStreamProvider().isPresent()) { connection.setDoOutput(true); } // Disable following redirects since it breaks SDK error handling and matches Apache. // See: https://github.com/aws/aws-sdk-java-v2/issues/975 connection.setInstanceFollowRedirects(false); return connection; }
@Test public void validatesHttpsCertificateIssuer() throws Exception { SdkHttpClient client = createSdkHttpClient(); SdkHttpFullRequest request = mockSdkRequest("https://localhost:" + mockServer.httpsPort(), SdkHttpMethod.POST); assertThatThrownBy(client.prepareRequest(HttpExecuteRequest.builder().request(request).build())::call) .isInstanceOf(SSLHandshakeException.class); }
@Override public HttpExecuteResponse call() throws IOException { connection.connect(); request.contentStreamProvider().ifPresent(provider -> invokeSafely(() -> IoUtils.copy(provider.newStream(), connection.getOutputStream()))); int responseCode = connection.getResponseCode(); boolean isErrorResponse = HttpStatusFamily.of(responseCode).isOneOf(CLIENT_ERROR, SERVER_ERROR); InputStream content = !isErrorResponse ? connection.getInputStream() : connection.getErrorStream(); AbortableInputStream responseBody = content != null ? AbortableInputStream.create(content) : null; return HttpExecuteResponse.builder() .response(SdkHttpResponse.builder() .statusCode(responseCode) .statusText(connection.getResponseMessage()) // TODO: Don't ignore abort? .headers(extractHeaders(connection)) .build()) .responseBody(responseBody) .build(); }
private HttpRequestBase wrapEntity(HttpExecuteRequest request, HttpEntityEnclosingRequestBase entityEnclosingRequest) { /* * We should never reuse the entity of the previous request, since * reading from the buffered entity will bypass reading from the * original request content. And if the content contains InputStream * wrappers that were added for validation-purpose (e.g. * Md5DigestCalculationInputStream), these wrappers would never be * read and updated again after AmazonHttpClient resets it in * preparation for the retry. Eventually, these wrappers would * return incorrect validation result. */ if (request.contentStreamProvider().isPresent()) { HttpEntity entity = new RepeatableInputStreamRequestEntity(request); if (request.httpRequest().headers().get(HttpHeaders.CONTENT_LENGTH) == null) { entity = ApacheUtils.newBufferedHttpEntity(entity); } entityEnclosingRequest.setEntity(entity); } return entityEnclosingRequest; }
protected void testForResponseCodeUsingHttps(SdkHttpClient client, int returnCode) throws Exception { SdkHttpMethod sdkHttpMethod = SdkHttpMethod.POST; stubForMockRequest(returnCode); SdkHttpFullRequest req = mockSdkRequest("https://localhost:" + mockServer.httpsPort(), sdkHttpMethod); HttpExecuteResponse rsp = client.prepareRequest(HttpExecuteRequest.builder() .request(req) .contentStreamProvider(req.contentStreamProvider() .orElse(null)) .build()) .call(); validateResponse(rsp, returnCode, sdkHttpMethod); }
/** * Creates a new RepeatableInputStreamRequestEntity using the information * from the specified request. If the input stream containing the request's * contents is repeatable, then this RequestEntity will report as being * repeatable. * * @param request The details of the request being written out (content type, * content length, and content). */ public RepeatableInputStreamRequestEntity(final HttpExecuteRequest request) { setChunked(false); /* * If we don't specify a content length when we instantiate our * InputStreamRequestEntity, then HttpClient will attempt to * buffer the entire stream contents into memory to determine * the content length. */ long contentLength = request.httpRequest().firstMatchingHeader("Content-Length") .map(this::parseContentLength) .orElse(-1L); content = getContent(request.contentStreamProvider()); // TODO v2 MetricInputStreamEntity inputStreamRequestEntity = new InputStreamEntity(content, contentLength); setContent(content); setContentLength(contentLength); request.httpRequest().firstMatchingHeader("Content-Type").ifPresent(contentType -> { inputStreamRequestEntity.setContentType(contentType); setContentType(contentType); }); }
@Override public ExecutableHttpRequest prepareRequest(HttpExecuteRequest request) { capturedRequests.add(request.httpRequest()); return new ExecutableHttpRequest() { @Override public HttpExecuteResponse call() { return nextResponse; } @Override public void abort() { } }; }
private HttpExecuteResponse executeHttpRequest(SdkHttpFullRequest request, RequestExecutionContext context) throws Exception { ExecutableHttpRequest requestCallable = sdkHttpClient .prepareRequest(HttpExecuteRequest.builder() .request(request) .contentStreamProvider(request.contentStreamProvider().orElse(null)) .build()); context.apiCallTimeoutTracker().abortable(requestCallable); context.apiCallAttemptTimeoutTracker().abortable(requestCallable); return requestCallable.call(); } }
@Override public HttpExecuteRequest build() { return new HttpExecuteRequest(this); } }
@Override public ExecutableHttpRequest prepareRequest(HttpExecuteRequest request) { capturedRequests.add(request.httpRequest()); return new ExecutableHttpRequest() { @Override public HttpExecuteResponse call() { return nextResponse; } @Override public void abort() { } }; }
private void testForResponseCode(int returnCode, SdkHttpMethod method) throws Exception { SdkHttpClient client = createSdkHttpClient(); stubForMockRequest(returnCode); SdkHttpFullRequest req = mockSdkRequest("http://localhost:" + mockServer.port(), method); HttpExecuteResponse rsp = client.prepareRequest(HttpExecuteRequest.builder() .request(req) .contentStreamProvider(req.contentStreamProvider() .orElse(null)) .build()) .call(); validateResponse(rsp, returnCode, method); }
public HttpRequestBase create(final HttpExecuteRequest request, final ApacheHttpRequestConfig requestConfig) { URI uri = request.httpRequest().getUri(); HttpRequestBase base = createApacheRequest(request, uri.toString()); addHeadersToRequest(base, request.httpRequest()); addRequestConfig(base, request.httpRequest(), requestConfig); return base; }
private HttpRequestBase createApacheRequest(HttpExecuteRequest request, String uri) { switch (request.httpRequest().method()) { case HEAD: return new HttpHead(uri); case GET: return new HttpGet(uri); case DELETE: return new HttpDelete(uri); case OPTIONS: return new HttpOptions(uri); case PATCH: return wrapEntity(request, new HttpPatch(uri)); case POST: return wrapEntity(request, new HttpPost(uri)); case PUT: return wrapEntity(request, new HttpPut(uri)); default: throw new RuntimeException("Unknown HTTP method name: " + request.httpRequest().method()); } }