Search in sources :

Example 1 with DatarouterHttpResponse

use of io.datarouter.httpclient.response.DatarouterHttpResponse in project datarouter by hotpads.

the class HttpTestHandler method httpTest.

@Handler(defaultHandler = true)
public Mav httpTest(OptionalString url, OptionalString method, OptionalString requestBody, OptionalString headers, OptionalString contentType, OptionalString useProxy, OptionalString followRedirects) {
    Mav mav = new Mav(files.jsp.http.httpTesterJsp);
    mav.put("path", paths.datarouter.http.tester.toSlashedString());
    if (url.isEmpty() || method.isEmpty()) {
        return mav;
    }
    mav.put("url", url.get());
    HttpRequestMethod requestMethod = "POST".equals(method.get()) ? HttpRequestMethod.POST : HttpRequestMethod.GET;
    mav.put("method", requestMethod.name());
    DatarouterHttpRequest request = new DatarouterHttpRequest(requestMethod, url.get()).setRetrySafe(true);
    if (headers.isPresent()) {
        Map<String, String> headersMap = GsonTool.GSON.fromJson(headers.get(), new TypeToken<Map<String, String>>() {
        }.getType());
        request.addHeaders(headersMap);
        mav.put("headersMap", GsonTool.GSON.toJson(headersMap));
    }
    if (requestBody.isPresent()) {
        ContentType cont = contentType.isPresent() ? ContentType.getByMimeType(contentType.get()) : ContentType.APPLICATION_JSON;
        request.setEntity(requestBody.get(), cont);
        mav.put("requestBody", requestBody.get());
        mav.put("contentType", cont.getMimeType());
    }
    if (useProxy.isPresent()) {
        mav.put("useProxy", true);
        proxySetter.setProxyOnRequest(request);
    }
    Long start = System.currentTimeMillis();
    Conditional<DatarouterHttpResponse> response;
    if (followRedirects.isPresent()) {
        mav.put("followRedirects", true);
        response = httpTesterClient.tryExecute(request);
    } else {
        response = httpTesterWithoutRedirectClient.tryExecute(request);
    }
    Long elapsedMs = System.currentTimeMillis() - start;
    if (response.isFailure() && response.getException() instanceof DatarouterHttpResponseException) {
        DatarouterHttpResponseException responseException = (DatarouterHttpResponseException) response.getException();
        addResponseToMavModel(mav, url.get(), elapsedMs, Optional.of(responseException.getResponse()));
    } else if (response.isFailure()) {
        mav.put("stackTrace", ExceptionTool.getStackTraceAsString(response.getException()));
        addResponseToMavModel(mav, url.get(), elapsedMs, Optional.empty());
    }
    response.ifSuccess(httpResponse -> addResponseToMavModel(mav, url.get(), elapsedMs, Optional.of(httpResponse)));
    return mav;
}
Also used : HttpRequestMethod(io.datarouter.httpclient.request.HttpRequestMethod) DatarouterHttpResponse(io.datarouter.httpclient.response.DatarouterHttpResponse) DatarouterHttpResponseException(io.datarouter.httpclient.response.exception.DatarouterHttpResponseException) Mav(io.datarouter.web.handler.mav.Mav) ContentType(org.apache.http.entity.ContentType) TypeToken(com.google.gson.reflect.TypeToken) DatarouterHttpRequest(io.datarouter.httpclient.request.DatarouterHttpRequest) OptionalString(io.datarouter.web.handler.types.optional.OptionalString) BaseHandler(io.datarouter.web.handler.BaseHandler)

Example 2 with DatarouterHttpResponse

use of io.datarouter.httpclient.response.DatarouterHttpResponse in project datarouter by hotpads.

the class DatarouterHttpClientIntegrationTests method testServiceUnavailableFailure.

@Test(expectedExceptions = DatarouterHttpResponseException.class)
public void testServiceUnavailableFailure() throws DatarouterHttpException {
    try {
        int status = HttpStatus.SC_SERVICE_UNAVAILABLE;
        String expectedResponse = UUID.randomUUID().toString();
        server.setResponse(status, expectedResponse);
        DatarouterHttpClient client = new DatarouterHttpClientBuilder().build();
        DatarouterHttpRequest request = new DatarouterHttpRequest(HttpRequestMethod.GET, URL).setRetrySafe(false);
        client.executeChecked(request);
    } catch (DatarouterHttpResponseException e) {
        Assert.assertTrue(e.isServerError());
        DatarouterHttpResponse response = e.getResponse();
        Assert.assertNotNull(response);
        Assert.assertEquals(response.getStatusCode(), HttpStatus.SC_SERVICE_UNAVAILABLE);
        throw e;
    }
}
Also used : DatarouterHttpResponse(io.datarouter.httpclient.response.DatarouterHttpResponse) DatarouterHttpResponseException(io.datarouter.httpclient.response.exception.DatarouterHttpResponseException) DatarouterHttpRequest(io.datarouter.httpclient.request.DatarouterHttpRequest) Test(org.testng.annotations.Test)

Example 3 with DatarouterHttpResponse

use of io.datarouter.httpclient.response.DatarouterHttpResponse in project datarouter by hotpads.

the class DatarouterHttpClientIntegrationTests method testSecurityComponentsWithRefreshableSuppliers.

@Test
public void testSecurityComponentsWithRefreshableSuppliers() {
    DatarouterHttpClient client;
    DatarouterHttpRequest request;
    DatarouterHttpResponse response;
    Map<String, String> postParams;
    String salt = "some super secure salty salt " + UUID.randomUUID().toString();
    String cipherKey = "kirg king kind " + UUID.randomUUID().toString();
    String apiKey = "apiKey advanced placement incremental key " + UUID.randomUUID().toString();
    DefaultSignatureGenerator signatureGenerator = new RefreshableDefaultSignatureGenerator(() -> salt);
    DefaultCsrfGenerator csrfGenerator = new RefreshableDefaultCsrfGenerator(() -> cipherKey);
    Supplier<String> apiKeySupplier = new RefreshableStringSupplier(() -> apiKey);
    client = new DatarouterHttpClientBuilder().setSignatureGenerator(signatureGenerator).setCsrfGenerator(csrfGenerator).setApiKeySupplier(apiKeySupplier).build();
    Map<String, String> params = new HashMap<>();
    params.put("1", UUID.randomUUID().toString());
    params.put("2", Integer.toString(RANDOM.nextInt()));
    params.put("3", "Everything is awesome! Everything is cool when you're part of a team!");
    String expectedResponse = Arrays.toString(params.entrySet().toArray());
    server.setResponse(HttpStatus.SC_ACCEPTED, expectedResponse);
    // GET request cannot be signed
    request = new DatarouterHttpRequest(HttpRequestMethod.GET, URL).setRetrySafe(false).addPostParams(params);
    response = client.execute(request);
    postParams = request.getFirstPostParams();
    Assert.assertEquals(response.getEntity(), expectedResponse);
    Assert.assertEquals(postParams.size(), params.size());
    Assert.assertNull(postParams.get(SecurityParameters.CSRF_IV));
    Assert.assertNull(postParams.get(SecurityParameters.CSRF_TOKEN));
    Assert.assertNull(postParams.get(SecurityParameters.API_KEY));
    Assert.assertNull(postParams.get(SecurityParameters.SIGNATURE));
    client = new DatarouterHttpClientBuilder().setSignatureGenerator(signatureGenerator).setCsrfGenerator(csrfGenerator).setApiKeySupplier(apiKeySupplier).build();
    // entity enclosing request with no entity or params cannot be signed
    request = new DatarouterHttpRequest(HttpRequestMethod.POST, URL);
    response = client.execute(request);
    postParams = request.getFirstPostParams();
    Assert.assertEquals(response.getEntity(), expectedResponse);
    Assert.assertEquals(request.getPostParams().size(), 4);
    Assert.assertNotNull(postParams.get(SecurityParameters.CSRF_IV));
    Assert.assertNotNull(postParams.get(SecurityParameters.CSRF_TOKEN));
    Assert.assertNotNull(postParams.get(SecurityParameters.API_KEY));
    Assert.assertNotNull(postParams.get(SecurityParameters.SIGNATURE));
    client = new DatarouterHttpClientBuilder().setSignatureGenerator(signatureGenerator).setCsrfGenerator(csrfGenerator).setApiKeySupplier(apiKeySupplier).build();
    // entity enclosing request already with an entity cannot be signed, even with params
    request = new DatarouterHttpRequest(HttpRequestMethod.PATCH, URL).setRetrySafe(false).setEntity(params).addPostParams(params);
    response = client.execute(request);
    postParams = request.getFirstPostParams();
    Assert.assertEquals(response.getEntity(), expectedResponse);
    Assert.assertEquals(postParams.size(), 3);
    Assert.assertNull(postParams.get(SecurityParameters.CSRF_IV));
    Assert.assertNull(postParams.get(SecurityParameters.CSRF_TOKEN));
    Assert.assertNull(postParams.get(SecurityParameters.API_KEY));
    Assert.assertNull(postParams.get(SecurityParameters.SIGNATURE));
    client = new DatarouterHttpClientBuilder().setSignatureGenerator(signatureGenerator).setCsrfGenerator(csrfGenerator).setApiKeySupplier(apiKeySupplier).build();
    // entity enclosing request is signed with entity from post params
    request = new DatarouterHttpRequest(HttpRequestMethod.POST, URL).addPostParams(params);
    response = client.execute(request);
    postParams = request.getFirstPostParams();
    Assert.assertEquals(response.getEntity(), expectedResponse);
    Assert.assertEquals(postParams.size(), params.size() + 4);
    Assert.assertNotNull(postParams.get(SecurityParameters.CSRF_IV));
    Assert.assertNotNull(postParams.get(SecurityParameters.CSRF_TOKEN));
    Assert.assertNotNull(postParams.get(SecurityParameters.API_KEY));
    Assert.assertNotNull(postParams.get(SecurityParameters.SIGNATURE));
    // test equivalence classes
    client = new DatarouterHttpClientBuilder().setCsrfGenerator(csrfGenerator).build();
    request = new DatarouterHttpRequest(HttpRequestMethod.PUT, URL).setRetrySafe(false).addPostParams(params);
    response = client.execute(request);
    postParams = request.getFirstPostParams();
    Assert.assertEquals(response.getEntity(), expectedResponse);
    Assert.assertEquals(postParams.size(), params.size() + 2);
    Assert.assertNotNull(postParams.get(SecurityParameters.CSRF_IV));
    Assert.assertNotNull(postParams.get(SecurityParameters.CSRF_TOKEN));
    Assert.assertNull(postParams.get(SecurityParameters.API_KEY));
    Assert.assertNull(postParams.get(SecurityParameters.SIGNATURE));
    client = new DatarouterHttpClientBuilder().setApiKeySupplier(apiKeySupplier).build();
    request = new DatarouterHttpRequest(HttpRequestMethod.PATCH, URL).setRetrySafe(false).addPostParams(params);
    response = client.execute(request);
    postParams = request.getFirstPostParams();
    Assert.assertEquals(response.getEntity(), expectedResponse);
    Assert.assertEquals(postParams.size(), params.size() + 1);
    Assert.assertNull(postParams.get(SecurityParameters.CSRF_IV));
    Assert.assertNull(postParams.get(SecurityParameters.CSRF_TOKEN));
    Assert.assertNotNull(postParams.get(SecurityParameters.API_KEY));
    Assert.assertNull(postParams.get(SecurityParameters.SIGNATURE));
}
Also used : RefreshableDefaultCsrfGenerator(io.datarouter.httpclient.security.DefaultCsrfGenerator.RefreshableDefaultCsrfGenerator) DefaultCsrfGenerator(io.datarouter.httpclient.security.DefaultCsrfGenerator) RefreshableStringSupplier(io.datarouter.instrumentation.refreshable.RefreshableStringSupplier) RefreshableDefaultSignatureGenerator(io.datarouter.httpclient.security.DefaultSignatureGenerator.RefreshableDefaultSignatureGenerator) HashMap(java.util.HashMap) DatarouterHttpResponse(io.datarouter.httpclient.response.DatarouterHttpResponse) RefreshableDefaultSignatureGenerator(io.datarouter.httpclient.security.DefaultSignatureGenerator.RefreshableDefaultSignatureGenerator) DefaultSignatureGenerator(io.datarouter.httpclient.security.DefaultSignatureGenerator) DatarouterHttpRequest(io.datarouter.httpclient.request.DatarouterHttpRequest) RefreshableDefaultCsrfGenerator(io.datarouter.httpclient.security.DefaultCsrfGenerator.RefreshableDefaultCsrfGenerator) Test(org.testng.annotations.Test)

Example 4 with DatarouterHttpResponse

use of io.datarouter.httpclient.response.DatarouterHttpResponse in project datarouter by hotpads.

the class DatarouterHttpClientIoExceptionCircuitBreaker method call.

public DatarouterHttpResponse call(CloseableHttpClient httpClient, DatarouterHttpRequest request, Consumer<HttpEntity> httpEntityConsumer, HttpClientContext context, Supplier<Boolean> enableBreakers, Supplier<Boolean> traceInQueryString, Supplier<Boolean> debugLog) throws DatarouterHttpException {
    CircuitBreakerState state = getState();
    if (state == CircuitBreakerState.OPEN && enableBreakers.get()) {
        incrementCounterOnStateChange("open");
        throw new DatarouterHttpCircuitBreakerException(name, callResultQueue.getOriginalException());
    }
    DatarouterHttpException ex;
    TracerTool.startSpan("http call " + request.getPath(), TraceSpanGroupType.HTTP);
    Tracer tracer = TracerThreadLocal.get();
    W3TraceContext traceContext;
    if (tracer != null && tracer.getTraceContext().isPresent()) {
        traceContext = tracer.getTraceContext().get().copy();
        traceContext.updateParentIdAndAddTracestateMember();
    } else {
        count("traceContext null");
        traceContext = new W3TraceContext(Trace2Dto.getCurrentTimeInNs());
    }
    String traceparent = traceContext.getTraceparent().toString();
    if (traceInQueryString.get()) {
        request.addGetParam(TRACEPARENT, traceparent);
    }
    HttpRequestBase internalHttpRequest = request.getRequest();
    count("request");
    logger.debug("traceparent={} passing to request={}", traceparent, request.getPath());
    internalHttpRequest.addHeader(TRACEPARENT, traceparent);
    internalHttpRequest.addHeader(TRACESTATE, traceContext.getTracestate().toString());
    context.setAttribute(TRACEPARENT, traceContext.getTraceparent().toString());
    if (debugLog.get()) {
        logger.warn("sending http request method={} url={}", internalHttpRequest.getMethod(), internalHttpRequest.getURI());
    }
    long requestStartTimeNs = Trace2Dto.getCurrentTimeInNs();
    try {
        HttpResponse httpResponse = httpClient.execute(internalHttpRequest, context);
        Duration duration = Duration.ofNanos(Trace2Dto.getCurrentTimeInNs() - requestStartTimeNs);
        String entity = null;
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        count("response " + statusCode);
        boolean isBadStatusCode = statusCode >= HttpStatus.SC_BAD_REQUEST;
        HttpEntity httpEntity = httpResponse.getEntity();
        if (httpEntity != null) {
            // skip the httpEntityConsumer in case of error because we are going to close the input stream
            if (httpEntityConsumer != null && !isBadStatusCode) {
                httpEntityConsumer.accept(httpEntity);
            } else {
                entity = EntityUtils.toString(httpEntity);
            }
        }
        Optional<Traceparent> remoteTraceparent = Optional.ofNullable(httpResponse.getFirstHeader(TRACEPARENT)).map(Header::getValue).map(Traceparent::parse).filter(Optional::isPresent).map(Optional::get);
        remoteTraceparent.ifPresent(tp -> TracerTool.appendToSpanInfo("remote parentId", tp.parentId));
        if (remoteTraceparent.isPresent() && remoteTraceparent.get().shouldSample()) {
            // if remote server has forced sample for trace, we also force sample the client's trace
            TracerTool.setForceSample();
        }
        if (duration.compareTo(LOG_SLOW_REQUEST_THRESHOLD) > 0) {
            logger.warn("Slow request target={} durationS={} remoteTraceparent={}", request.getPath(), duration.getSeconds(), remoteTraceparent.orElse(null));
        }
        DatarouterHttpResponse response = new DatarouterHttpResponse(httpResponse, context, statusCode, entity);
        if (isBadStatusCode) {
            TracerTool.appendToSpanInfo("bad status code", statusCode);
            ex = new DatarouterHttpResponseException(response, duration, traceparent, request.getPath());
            callResultQueue.insertFalseResultWithException(ex);
            // no need to abort the connection, we received a response line, the connection is probably still good
            response.tryClose();
            throw ex;
        }
        if (state == CircuitBreakerState.HALF_OPEN) {
            callResultQueue.reset();
            incrementCounterOnStateChange("closing");
            logger.error("Half opened circuit now closing. CircuitName={}", name);
        }
        callResultQueue.insertTrueResult();
        return response;
    } catch (IOException e) {
        count("IOException");
        TracerTool.appendToSpanInfo("exception", e.getMessage());
        ex = new DatarouterHttpConnectionAbortedException(e, TimeUnit.NANOSECONDS.toMillis(requestStartTimeNs), traceparent, request.getPath());
        callResultQueue.insertFalseResultWithException(ex);
    } catch (CancellationException e) {
        count("CancellationException");
        TracerTool.appendToSpanInfo("exception", e.getMessage());
        ex = new DatarouterHttpRequestInterruptedException(e, TimeUnit.NANOSECONDS.toMillis(requestStartTimeNs), traceparent, request.getPath());
        callResultQueue.insertFalseResultWithException(ex);
    } finally {
        TracerTool.finishSpan();
    }
    // connection might have gone bad, destroying it
    if (internalHttpRequest != null) {
        forceAbortRequestUnchecked(internalHttpRequest);
    }
    throw ex;
}
Also used : HttpRequestBase(org.apache.http.client.methods.HttpRequestBase) DatarouterHttpResponseException(io.datarouter.httpclient.response.exception.DatarouterHttpResponseException) DatarouterHttpRequestInterruptedException(io.datarouter.httpclient.response.exception.DatarouterHttpRequestInterruptedException) HttpEntity(org.apache.http.HttpEntity) Optional(java.util.Optional) Tracer(io.datarouter.instrumentation.trace.Tracer) DatarouterHttpCircuitBreakerException(io.datarouter.httpclient.response.exception.DatarouterHttpCircuitBreakerException) DatarouterHttpResponse(io.datarouter.httpclient.response.DatarouterHttpResponse) HttpResponse(org.apache.http.HttpResponse) W3TraceContext(io.datarouter.instrumentation.trace.W3TraceContext) Duration(java.time.Duration) IOException(java.io.IOException) Traceparent(io.datarouter.instrumentation.trace.Traceparent) DatarouterHttpResponse(io.datarouter.httpclient.response.DatarouterHttpResponse) DatarouterHttpConnectionAbortedException(io.datarouter.httpclient.response.exception.DatarouterHttpConnectionAbortedException) DatarouterHttpException(io.datarouter.httpclient.response.exception.DatarouterHttpException) CancellationException(java.util.concurrent.CancellationException)

Example 5 with DatarouterHttpResponse

use of io.datarouter.httpclient.response.DatarouterHttpResponse in project datarouter by hotpads.

the class ExampleMakeRequest method example.

public void example() {
    // reuse this client
    DatarouterHttpClient client = new DatarouterHttpClientBuilder().build();
    DatarouterHttpRequest request = new DatarouterHttpRequest(HttpRequestMethod.GET, "https://example.com/api").addGetParam("id", // Passing a GET parameter
    "1");
    DatarouterHttpResponse response = client.execute(request);
    String stringResult = response.getEntity();
}
Also used : DatarouterHttpResponse(io.datarouter.httpclient.response.DatarouterHttpResponse) DatarouterHttpClientBuilder(io.datarouter.httpclient.client.DatarouterHttpClientBuilder) DatarouterHttpRequest(io.datarouter.httpclient.request.DatarouterHttpRequest) DatarouterHttpClient(io.datarouter.httpclient.client.DatarouterHttpClient)

Aggregations

DatarouterHttpResponse (io.datarouter.httpclient.response.DatarouterHttpResponse)11 DatarouterHttpRequest (io.datarouter.httpclient.request.DatarouterHttpRequest)9 DatarouterHttpResponseException (io.datarouter.httpclient.response.exception.DatarouterHttpResponseException)6 Test (org.testng.annotations.Test)5 HashMap (java.util.HashMap)4 HttpRequestMethod (io.datarouter.httpclient.request.HttpRequestMethod)3 DatarouterHttpException (io.datarouter.httpclient.response.exception.DatarouterHttpException)3 IOException (java.io.IOException)3 HttpEntity (org.apache.http.HttpEntity)3 HttpRequestBase (org.apache.http.client.methods.HttpRequestBase)3 ContentType (org.apache.http.entity.ContentType)3 DatarouterHttpClientIoExceptionCircuitBreaker (io.datarouter.httpclient.circuitbreaker.DatarouterHttpClientIoExceptionCircuitBreaker)2 JsonSerializer (io.datarouter.httpclient.json.JsonSerializer)2 Conditional (io.datarouter.httpclient.response.Conditional)2 CsrfGenerator (io.datarouter.httpclient.security.CsrfGenerator)2 RefreshableCsrfGenerator (io.datarouter.httpclient.security.CsrfGenerator.RefreshableCsrfGenerator)2 SecurityParameters (io.datarouter.httpclient.security.SecurityParameters)2 SignatureGenerator (io.datarouter.httpclient.security.SignatureGenerator)2 RefreshableSignatureGenerator (io.datarouter.httpclient.security.SignatureGenerator.RefreshableSignatureGenerator)2 RefreshableSupplier (io.datarouter.instrumentation.refreshable.RefreshableSupplier)2