@Test public void rejectOnForbidden() throws Exception { mockCall(403); InterledgerResponsePacket responsePacket = link.sendPacket(packetMock); assertThat(responsePacket).extracting("code", "message") .containsExactly(InterledgerErrorCode.F00_BAD_REQUEST, "Unable to connect to remote ILP-over-HTTP Link: Invalid Bearer Token. response=Response{protocol=h2, " + "code=403, message=stop asking me to set stuff, url=https: ); }
@Override public InterledgerResponsePacket sendPacket(final InterledgerPreparePacket preparePacket) { Objects.requireNonNull(preparePacket); if (preparePacket.getExpiresAt() != null && okHttpClient.readTimeoutMillis() <= Duration.between(Instant.now(), preparePacket.getExpiresAt()).toMillis()) { logger.warn("OkHttpClient read timeout is shorter than the Prepare Packet's timeout. " + "This may result in an HTTP timeout while unexpired ILP packets are in flight."); } final Request okHttpRequest; try { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ilpCodecContext.write(preparePacket, byteArrayOutputStream); okHttpRequest = this.constructSendPacketRequest(preparePacket); } catch (IOException e) { throw new LinkException(e.getMessage(), e, getLinkId()); } try (Response response = okHttpClient.newCall(okHttpRequest).execute()) { if (response.isSuccessful()) { return ilpCodecContext.read(InterledgerResponsePacket.class, response.body().byteStream()); } else { final String errorResponseBody = CharStreams.toString(response.body().charStream()); Optional<ThrowableProblem> problem = parseThrowableProblem(preparePacket, errorResponseBody); final InterledgerRejectPacket rejectPacket; if (response.code() >= 400 && response.code() < 500) { String customErrorMessage = null; if (response.code() == 401 || response.code() == 403) { customErrorMessage = String.format("Unable to connect to remote ILP-over-HTTP Link: Invalid Bearer " + "Token. response=%s", response); logger.error(customErrorMessage); } String message = Stream.of( customErrorMessage, problem.map(Problem::getTitle).orElse(null), errorResponseBody ) .filter(Objects::nonNull) .findFirst() .get(); rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.F00_BAD_REQUEST) .message(message) .build(); } else { rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.T00_INTERNAL_ERROR) .message(problem.map(Problem::getTitle).orElse(errorResponseBody)) .build(); } logger.error( "Unable to send ILP-over-HTTP packet. preparePacket={} httpResponseCode={} errorResponse={} " + "rejectPacket={}", preparePacket, response.code(), CharStreams.toString(response.body().charStream()), rejectPacket ); return rejectPacket; } } catch (IOException e) { throw new LinkException( String.format("Unable to sendPacket. preparePacket=%s error=%s", preparePacket, e.getMessage()), e, getLinkId() ); } }
IlpOverHttpLink extends AbstractLink<IlpOverHttpLinkSettings> implements Link<IlpOverHttpLinkSettings> { @Override public InterledgerResponsePacket sendPacket(final InterledgerPreparePacket preparePacket) { Objects.requireNonNull(preparePacket); if (preparePacket.getExpiresAt() != null && okHttpClient.readTimeoutMillis() <= Duration.between(Instant.now(), preparePacket.getExpiresAt()).toMillis()) { logger.warn("OkHttpClient read timeout is shorter than the Prepare Packet's timeout. " + "This may result in an HTTP timeout while unexpired ILP packets are in flight."); } final Request okHttpRequest; try { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ilpCodecContext.write(preparePacket, byteArrayOutputStream); okHttpRequest = this.constructSendPacketRequest(preparePacket); } catch (IOException e) { throw new LinkException(e.getMessage(), e, getLinkId()); } try (Response response = okHttpClient.newCall(okHttpRequest).execute()) { if (response.isSuccessful()) { return ilpCodecContext.read(InterledgerResponsePacket.class, response.body().byteStream()); } else { final String errorResponseBody = CharStreams.toString(response.body().charStream()); Optional<ThrowableProblem> problem = parseThrowableProblem(preparePacket, errorResponseBody); final InterledgerRejectPacket rejectPacket; if (response.code() >= 400 && response.code() < 500) { String customErrorMessage = null; if (response.code() == 401 || response.code() == 403) { customErrorMessage = String.format("Unable to connect to remote ILP-over-HTTP Link: Invalid Bearer " + "Token. response=%s", response); logger.error(customErrorMessage); } String message = Stream.of( customErrorMessage, problem.map(Problem::getTitle).orElse(null), errorResponseBody ) .filter(Objects::nonNull) .findFirst() .get(); rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.F00_BAD_REQUEST) .message(message) .build(); } else { rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.T00_INTERNAL_ERROR) .message(problem.map(Problem::getTitle).orElse(errorResponseBody)) .build(); } logger.error( "Unable to send ILP-over-HTTP packet. preparePacket={} httpResponseCode={} errorResponse={} " + "rejectPacket={}", preparePacket, response.code(), CharStreams.toString(response.body().charStream()), rejectPacket ); return rejectPacket; } } catch (IOException e) { throw new LinkException( String.format("Unable to sendPacket. preparePacket=%s error=%s", preparePacket, e.getMessage()), e, getLinkId() ); } } }
IlpOverHttpLink extends AbstractLink<IlpOverHttpLinkSettings> implements Link<IlpOverHttpLinkSettings> { @Override public InterledgerResponsePacket sendPacket(final InterledgerPreparePacket preparePacket) { Objects.requireNonNull(preparePacket); if (preparePacket.getExpiresAt() != null && okHttpClient.readTimeoutMillis() <= Duration.between(Instant.now(), preparePacket.getExpiresAt()).toMillis()) { logger.warn("OkHttpClient read timeout is shorter than the Prepare Packet's timeout. " + "This may result in an HTTP timeout while unexpired ILP packets are in flight."); } final Request okHttpRequest; try { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ilpCodecContext.write(preparePacket, byteArrayOutputStream); okHttpRequest = this.constructSendPacketRequest(preparePacket); } catch (IOException e) { throw new LinkException(e.getMessage(), e, getLinkId()); } try (Response response = okHttpClient.newCall(okHttpRequest).execute()) { if (response.isSuccessful()) { return ilpCodecContext.read(InterledgerResponsePacket.class, response.body().byteStream()); } else { final String errorResponseBody = CharStreams.toString(response.body().charStream()); Optional<ThrowableProblem> problem = parseThrowableProblem(preparePacket, errorResponseBody); final InterledgerRejectPacket rejectPacket; if (response.code() >= 400 && response.code() < 500) { String customErrorMessage = null; if (response.code() == 401 || response.code() == 403) { customErrorMessage = String.format("Unable to connect to remote ILP-over-HTTP Link: Invalid Bearer " + "Token. response=%s", response); logger.error(customErrorMessage); } String message = Stream.of( customErrorMessage, problem.map(Problem::getTitle).orElse(null), errorResponseBody ) .filter(Objects::nonNull) .findFirst() .get(); rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.F00_BAD_REQUEST) .message(message) .build(); } else { rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.T00_INTERNAL_ERROR) .message(problem.map(Problem::getTitle).orElse(errorResponseBody)) .build(); } logger.error( "Unable to send ILP-over-HTTP packet. preparePacket={} httpResponseCode={} errorResponse={} " + "rejectPacket={}", preparePacket, response.code(), CharStreams.toString(response.body().charStream()), rejectPacket ); return rejectPacket; } } catch (IOException e) { throw new LinkException( String.format("Unable to sendPacket. preparePacket=%s error=%s", preparePacket, e.getMessage()), e, getLinkId() ); } } IlpOverHttpLink(
      final Supplier<InterledgerAddress> operatorAddressSupplier,
      final HttpUrl outgoingUrl,
      final OkHttpClient okHttpClient,
      final ObjectMapper objectMapper,
      final CodecContext ilpCodecContext,
      final BearerTokenSupplier bearerTokenSupplier
  ); }
IlpOverHttpLink extends AbstractLink<IlpOverHttpLinkSettings> implements Link<IlpOverHttpLinkSettings> { @Override public InterledgerResponsePacket sendPacket(final InterledgerPreparePacket preparePacket) { Objects.requireNonNull(preparePacket); if (preparePacket.getExpiresAt() != null && okHttpClient.readTimeoutMillis() <= Duration.between(Instant.now(), preparePacket.getExpiresAt()).toMillis()) { logger.warn("OkHttpClient read timeout is shorter than the Prepare Packet's timeout. " + "This may result in an HTTP timeout while unexpired ILP packets are in flight."); } final Request okHttpRequest; try { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ilpCodecContext.write(preparePacket, byteArrayOutputStream); okHttpRequest = this.constructSendPacketRequest(preparePacket); } catch (IOException e) { throw new LinkException(e.getMessage(), e, getLinkId()); } try (Response response = okHttpClient.newCall(okHttpRequest).execute()) { if (response.isSuccessful()) { return ilpCodecContext.read(InterledgerResponsePacket.class, response.body().byteStream()); } else { final String errorResponseBody = CharStreams.toString(response.body().charStream()); Optional<ThrowableProblem> problem = parseThrowableProblem(preparePacket, errorResponseBody); final InterledgerRejectPacket rejectPacket; if (response.code() >= 400 && response.code() < 500) { String customErrorMessage = null; if (response.code() == 401 || response.code() == 403) { customErrorMessage = String.format("Unable to connect to remote ILP-over-HTTP Link: Invalid Bearer " + "Token. response=%s", response); logger.error(customErrorMessage); } String message = Stream.of( customErrorMessage, problem.map(Problem::getTitle).orElse(null), errorResponseBody ) .filter(Objects::nonNull) .findFirst() .get(); rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.F00_BAD_REQUEST) .message(message) .build(); } else { rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.T00_INTERNAL_ERROR) .message(problem.map(Problem::getTitle).orElse(errorResponseBody)) .build(); } logger.error( "Unable to send ILP-over-HTTP packet. preparePacket={} httpResponseCode={} errorResponse={} " + "rejectPacket={}", preparePacket, response.code(), CharStreams.toString(response.body().charStream()), rejectPacket ); return rejectPacket; } } catch (IOException e) { throw new LinkException( String.format("Unable to sendPacket. preparePacket=%s error=%s", preparePacket, e.getMessage()), e, getLinkId() ); } } IlpOverHttpLink(
      final Supplier<InterledgerAddress> operatorAddressSupplier,
      final HttpUrl outgoingUrl,
      final OkHttpClient okHttpClient,
      final ObjectMapper objectMapper,
      final CodecContext ilpCodecContext,
      final BearerTokenSupplier bearerTokenSupplier
  ); @Override InterledgerResponsePacket sendPacket(final InterledgerPreparePacket preparePacket); void testConnection(); @Override String toString(); HttpUrl getOutgoingUrl(); }
IlpOverHttpLink extends AbstractLink<IlpOverHttpLinkSettings> implements Link<IlpOverHttpLinkSettings> { @Override public InterledgerResponsePacket sendPacket(final InterledgerPreparePacket preparePacket) { Objects.requireNonNull(preparePacket); if (preparePacket.getExpiresAt() != null && okHttpClient.readTimeoutMillis() <= Duration.between(Instant.now(), preparePacket.getExpiresAt()).toMillis()) { logger.warn("OkHttpClient read timeout is shorter than the Prepare Packet's timeout. " + "This may result in an HTTP timeout while unexpired ILP packets are in flight."); } final Request okHttpRequest; try { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ilpCodecContext.write(preparePacket, byteArrayOutputStream); okHttpRequest = this.constructSendPacketRequest(preparePacket); } catch (IOException e) { throw new LinkException(e.getMessage(), e, getLinkId()); } try (Response response = okHttpClient.newCall(okHttpRequest).execute()) { if (response.isSuccessful()) { return ilpCodecContext.read(InterledgerResponsePacket.class, response.body().byteStream()); } else { final String errorResponseBody = CharStreams.toString(response.body().charStream()); Optional<ThrowableProblem> problem = parseThrowableProblem(preparePacket, errorResponseBody); final InterledgerRejectPacket rejectPacket; if (response.code() >= 400 && response.code() < 500) { String customErrorMessage = null; if (response.code() == 401 || response.code() == 403) { customErrorMessage = String.format("Unable to connect to remote ILP-over-HTTP Link: Invalid Bearer " + "Token. response=%s", response); logger.error(customErrorMessage); } String message = Stream.of( customErrorMessage, problem.map(Problem::getTitle).orElse(null), errorResponseBody ) .filter(Objects::nonNull) .findFirst() .get(); rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.F00_BAD_REQUEST) .message(message) .build(); } else { rejectPacket = InterledgerRejectPacket.builder() .triggeredBy(getOperatorAddressSupplier().get()) .code(InterledgerErrorCode.T00_INTERNAL_ERROR) .message(problem.map(Problem::getTitle).orElse(errorResponseBody)) .build(); } logger.error( "Unable to send ILP-over-HTTP packet. preparePacket={} httpResponseCode={} errorResponse={} " + "rejectPacket={}", preparePacket, response.code(), CharStreams.toString(response.body().charStream()), rejectPacket ); return rejectPacket; } } catch (IOException e) { throw new LinkException( String.format("Unable to sendPacket. preparePacket=%s error=%s", preparePacket, e.getMessage()), e, getLinkId() ); } } IlpOverHttpLink(
      final Supplier<InterledgerAddress> operatorAddressSupplier,
      final HttpUrl outgoingUrl,
      final OkHttpClient okHttpClient,
      final ObjectMapper objectMapper,
      final CodecContext ilpCodecContext,
      final BearerTokenSupplier bearerTokenSupplier
  ); @Override InterledgerResponsePacket sendPacket(final InterledgerPreparePacket preparePacket); void testConnection(); @Override String toString(); HttpUrl getOutgoingUrl(); static final String LINK_TYPE_STRING; static final LinkType LINK_TYPE; }