org.zalando.riptide.logbook.LocalRequest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of riptide-logbook Show documentation
Show all versions of riptide-logbook Show documentation
Client side response routing
package org.zalando.riptide.logbook;
import com.google.common.collect.Iterables;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.zalando.logbook.HttpHeaders;
import org.zalando.logbook.HttpRequest;
import org.zalando.logbook.Origin;
import org.zalando.riptide.CharsetExtractor;
import org.zalando.riptide.RequestArguments;
import org.zalando.riptide.RequestArguments.Entity;
import javax.annotation.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.Collections.emptyList;
import static org.zalando.fauxpas.FauxPas.throwingUnaryOperator;
// TODO remove Entity interface here
@AllArgsConstructor
final class LocalRequest implements HttpRequest {
private static final CharsetExtractor EXTRACTOR = new CharsetExtractor();
private final AtomicReference state = new AtomicReference<>(new Unbuffered());
private final RequestArguments arguments;
private interface State {
default State with() {
return this;
}
default State without() {
return this;
}
default State buffer(final Entity entity, final HttpOutputMessage message) throws IOException {
throw new UnsupportedOperationException();
}
default byte[] getBody() {
return new byte[0];
}
}
private static final class Unbuffered implements State {
@Override
public State with() {
return new Offering();
}
@Override
public State buffer(final Entity entity, final HttpOutputMessage message) throws IOException {
entity.writeTo(message);
return new Passing();
}
}
private static final class Offering implements State {
@Override
public State without() {
return new Unbuffered();
}
@Override
public State buffer(
final Entity entity,
final HttpOutputMessage message) throws IOException {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
entity.writeTo(new SimpleHttpOutputMessage(
message.getHeaders(),
new TeeOutputStream(message.getBody(), buffer)));
return new Buffering(buffer.toByteArray());
}
}
@AllArgsConstructor
private static final class Buffering implements State {
private final byte[] body;
@Override
public State without() {
return new Ignoring(body);
}
@Override
public byte[] getBody() {
return body;
}
}
@AllArgsConstructor
private static final class Ignoring implements State {
private final byte[] body;
@Override
public State with() {
return new Buffering(body);
}
}
private static final class Passing implements State {
}
@Override
public HttpRequest withBody() {
state.updateAndGet(State::with);
return this;
}
@Override
public HttpRequest withoutBody() {
state.updateAndGet(State::without);
return this;
}
@Override
public Origin getOrigin() {
return Origin.LOCAL;
}
@Override
public String getProtocolVersion() {
return "HTTP/1.1";
}
@Override
public String getRemote() {
return "localhost";
}
@Override
public String getMethod() {
return arguments.getMethod().name();
}
@Override
public String getScheme() {
return arguments.getRequestUri().getScheme();
}
@Override
public String getHost() {
return arguments.getRequestUri().getHost();
}
@Override
public Optional getPort() {
return Optional.of(arguments.getRequestUri().getPort()).filter(p -> p != -1);
}
@Override
public String getPath() {
return arguments.getRequestUri().getPath();
}
@Override
public String getQuery() {
return Optional.ofNullable(arguments.getRequestUri().getQuery()).orElse("");
}
@Override
public HttpHeaders getHeaders() {
return HttpHeaders.of(arguments.getHeaders());
}
@Nullable
@Override
public String getContentType() {
return Iterables.getFirst(
arguments.getHeaders().getOrDefault("Content-Type", emptyList()), null);
}
@Override
public Charset getCharset() {
return Optional.ofNullable(getContentType())
.map(MediaType::parseMediaType)
.flatMap(EXTRACTOR::getCharset)
.orElse(StandardCharsets.UTF_8);
}
void writeTo(final Entity entity, final HttpOutputMessage message) {
state.updateAndGet(throwingUnaryOperator(state ->
state.buffer(entity, message)));
}
@Override
public byte[] getBody() {
return state.get().getBody();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy