All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.artipie.http.rs.CachedResponse Maven / Gradle / Ivy

There is a newer version: v1.17.16
Show newest version
/*
 * The MIT License (MIT) Copyright (c) 2020-2023 artipie.com
 * https://github.com/artipie/artipie/blob/master/LICENSE.txt
 */
package com.artipie.http.rs;

import com.artipie.asto.Content;
import com.artipie.asto.ext.PublisherAs;
import com.artipie.http.Connection;
import com.artipie.http.Headers;
import com.artipie.http.Response;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.reactivestreams.Publisher;

/**
 * Response that caches origin response once it first sent and can replay it many times.
 * 

It can be useful when testing one response against multiple matchers, and response * from slice should be called only once.

* @since 0.17 */ public final class CachedResponse implements Response { /** * Origin response. */ private final Response origin; /** * Stateful connection. */ private final StatefulConnection con; /** * Wraps response with stateful connection. * @param origin Origin response */ public CachedResponse(final Response origin) { this.origin = origin; this.con = new StatefulConnection(); } @Override public CompletionStage send(final Connection connection) { return this.con.load(this.origin).thenCompose(self -> self.replay(connection)); } @Override public String toString() { return String.format( "(%s: state=%s)", this.getClass().getSimpleName(), this.con.toString() ); } /** * Connection that keeps response state and can reply it to other connection. * @since 0.16 */ private static final class StatefulConnection implements Connection { /** * Response status. */ private volatile RsStatus status; /** * Response headers. */ private volatile Headers headers; /** * Response body. */ private volatile byte[] body; @Override public CompletionStage accept(final RsStatus stts, final Headers hdrs, final Publisher bdy) { this.status = stts; this.headers = hdrs; return new PublisherAs(bdy).bytes().thenAccept( bytes -> this.body = bytes ); } @Override public String toString() { return String.format( "(%s: status=%s, headers=[%s], body=%s)", this.getClass().getSimpleName(), this.status, StreamSupport.stream(this.headers.spliterator(), false) .map( header -> String.format( "\"%s\": \"%s\"", header.getKey(), header.getValue() ) ).collect(Collectors.joining(", ")), Arrays.toString(this.body) ); } /** * Load state from response if needed. * @param response Response to load the state * @return Self future */ CompletionStage load(final Response response) { final CompletionStage self; if (this.status == null && this.headers == null && this.body == null) { self = response.send(this).thenApply(none -> this); } else { self = CompletableFuture.completedFuture(this); } return self; } /** * Reply self state to connection. * @param connection Connection * @return Future */ CompletionStage replay(final Connection connection) { return connection.accept(this.status, this.headers, new Content.From(this.body)); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy