
io.inverno.mod.grpc.server.internal.GenericGrpcExchange Maven / Gradle / Ivy
/*
* Copyright 2024 Jeremy Kuhn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.inverno.mod.grpc.server.internal;
import com.google.protobuf.Message;
import io.inverno.mod.base.resource.MediaTypes;
import io.inverno.mod.grpc.base.GrpcException;
import io.inverno.mod.grpc.base.GrpcHeaders;
import io.inverno.mod.grpc.base.GrpcStatus;
import io.inverno.mod.grpc.server.GrpcExchange;
import io.inverno.mod.grpc.server.GrpcRequest;
import io.inverno.mod.grpc.server.GrpcResponse;
import io.inverno.mod.http.base.ExchangeContext;
import io.inverno.mod.http.base.Status;
import io.inverno.mod.http.server.Exchange;
import io.inverno.mod.http.server.ResetStreamException;
import io.netty.handler.codec.http2.Http2Error;
import java.util.Optional;
import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
*
* Generic {@link GrpcExchange} implementation.
*
*
* @author Jeremy Kuhn
* @since 1.9
*
* @param The exchange context type
* @param The request message type
* @param The response message type
* @param the request type
* @param the response type
*/
public class GenericGrpcExchange, E extends GrpcResponse> implements GrpcExchange {
public static final Logger LOGGER = LogManager.getLogger(GrpcExchange.class);
/**
* The underlying HTTP server exchange.
*/
private final Exchange exchange;
/**
* The gRPC request supplier.
*/
private final Supplier requestSupplier;
/**
* The gRPC response supplier.
*/
private final Supplier responseSupplier;
/**
* The gRPC request.
*/
private D request;
/**
* The gRPC response.
*/
private E response;
/**
* The cancel cause.
*/
private Optional cancelCause;
/**
*
* Creates a generic gRPC exchange.
*
*
* @param exchange the HTTP server exchange
* @param requestSupplier the gRPC request supplier
* @param responseSupplier the gRPC response supplier
*/
public GenericGrpcExchange(Exchange exchange, Supplier requestSupplier, Supplier responseSupplier) {
this.exchange = exchange;
this.requestSupplier = requestSupplier;
this.responseSupplier = responseSupplier;
this.exchange.response().headers(headers -> headers.status(Status.OK).contentType(MediaTypes.APPLICATION_GRPC_PROTO));
this.exchange.response().trailers(trailers -> trailers.set(GrpcHeaders.NAME_GRPC_STATUS, Integer.toString(GrpcStatus.OK.getCode())));
}
@Override
public A context() {
return this.exchange.context();
}
@Override
public D request() {
if(this.request == null) {
this.request = this.requestSupplier.get();
}
return this.request;
}
@Override
public E response() {
if(this.response == null) {
this.response = this.responseSupplier.get();
}
return this.response;
}
@Override
public void cancel() {
this.exchange.reset(Http2Error.CANCEL.code());
}
@Override
public Optional getCancelCause() {
if(this.cancelCause == null || this.cancelCause.isEmpty()) {
this.cancelCause = this.exchange.getCancelCause().map(e -> {
if(e instanceof GrpcException) {
return (GrpcException)e;
}
else if(e instanceof ResetStreamException && ((ResetStreamException)e).getErrorCode() == Http2Error.CANCEL.code()) {
return new GrpcException(GrpcStatus.CANCELLED, e);
}
return new GrpcException(GrpcStatus.UNKNOWN, e);
});
}
return this.cancelCause;
}
/**
*
* Generic {@link GrpcExchange.Unary} implementation.
*
*
* @author Jeremy Kuhn
* @since 1.9
*
* @param the exchange context type
* @param the request message type
* @param the response message type
*/
public static class GenericUnary extends GenericGrpcExchange, GrpcResponse.Unary> implements GrpcExchange.Unary {
/**
*
* Creates a generic unary gRPC exchange.
*
*
* @param exchange the HTTP server exchange
* @param requestSupplier the gRPC request supplier
* @param responseSupplier the gRPC response supplier
*/
public GenericUnary(Exchange exchange, Supplier> requestSupplier, Supplier> responseSupplier) {
super(exchange, requestSupplier, responseSupplier);
}
}
/**
*
* Generic {@link GrpcExchange.ClientStreaming} implementation.
*
*
* @author Jeremy Kuhn
* @since 1.9
*
* @param the exchange context type
* @param the request message type
* @param the response message type
*/
public static class GenericClientStreaming extends GenericGrpcExchange, GrpcResponse.Unary> implements GrpcExchange.ClientStreaming {
/**
*
* Creates a generic client streaming gRPC exchange.
*
*
* @param exchange the HTTP server exchange
* @param requestSupplier the gRPC request supplier
* @param responseSupplier the gRPC response supplier
*/
public GenericClientStreaming(Exchange exchange, Supplier> requestSupplier, Supplier> responseSupplier) {
super(exchange, requestSupplier, responseSupplier);
}
}
/**
*
* Generic {@link GrpcExchange.ServerStreaming} implementation.
*
*
* @author Jeremy Kuhn
* @since 1.9
*
* @param the exchange context type
* @param the request message type
* @param the response message type
*/
public static class GenericServerStreaming extends GenericGrpcExchange, GrpcResponse.Streaming> implements GrpcExchange.ServerStreaming {
/**
*
* Creates a generic server streaming gRPC exchange.
*
*
* @param exchange the HTTP server exchange
* @param requestSupplier the gRPC request supplier
* @param responseSupplier the gRPC response supplier
*/
public GenericServerStreaming(Exchange exchange, Supplier> requestSupplier, Supplier> responseSupplier) {
super(exchange, requestSupplier, responseSupplier);
}
}
/**
*
* Generic {@link GrpcExchange.BidirectionalStreaming} implementation.
*
*
* @author Jeremy Kuhn
* @since 1.9
*
* @param the exchange context type
* @param the request message type
* @param the response message type
*/
public static class GenericBidirectionalStreaming extends GenericGrpcExchange, GrpcResponse.Streaming> implements GrpcExchange.BidirectionalStreaming {
/**
*
* Creates a generic bidirectional streaming gRPC exchange.
*
*
* @param exchange the HTTP server exchange
* @param requestSupplier the gRPC request supplier
* @param responseSupplier the gRPC response supplier
*/
public GenericBidirectionalStreaming(Exchange exchange, Supplier> requestSupplier, Supplier> responseSupplier) {
super(exchange, requestSupplier, responseSupplier);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy