package io.muoncore.protocol.requestresponse.server; import io.muoncore.Discovery; import io.muoncore.ServiceDescriptor; import io.muoncore.channel.Channel; import io.muoncore.channel.ChannelConnection; import io.muoncore.channel.Channels; import io.muoncore.codec.Codecs; import io.muoncore.config.AutoConfiguration; import io.muoncore.descriptors.OperationDescriptor; import io.muoncore.descriptors.ProtocolDescriptor; import io.muoncore.descriptors.SchemaDescriptor; import io.muoncore.descriptors.SchemasDescriptor; import io.muoncore.message.MuonInboundMessage; import io.muoncore.message.MuonMessage; import io.muoncore.message.MuonOutboundMessage; import io.muoncore.protocol.ServerProtocolStack; import io.muoncore.protocol.requestresponse.RRPTransformers; import lombok.AllArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; import java.util.stream.Collectors; /** * Server side of the Requestr Response protocol. * <p> * Transports open channels on this protocol when a remote request response client opens a channel through them * and sends a first message. */ @AllArgsConstructor public class RequestResponseServerProtocolStack implements ServerProtocolStack { private static final Logger LOG = LoggerFactory.getLogger(RequestResponseServerProtocolStack.class.getCanonicalName()); private final RequestResponseHandlers handlers; private Codecs codecs; private Discovery discovery; private AutoConfiguration config; @Override @SuppressWarnings("unchecked") public ChannelConnection<MuonInboundMessage, MuonOutboundMessage> createChannel() { Channel<MuonOutboundMessage, MuonInboundMessage> api2 = Channels.workerChannel("rrpserver", "transport"); api2.left().receive(message -> { if (message == null || message.getChannelOperation() == MuonMessage.ChannelOperation.closed) { //shutdown signal. return; } final ServerRequest request = RRPTransformers.toRequest(message, codecs); final RequestResponseServerHandler handler = handlers.findHandler(request); handler.handle(new RequestWrapper() { @Override public ServerRequest getRequest() { return request; } @Override public void answer(ServerResponse response) { Optional<ServiceDescriptor> target = discovery.findService(svc -> svc.getIdentifier().equals( config.getServiceName())); String[] codecList; if (target.isPresent()) { codecList = target.get().getCodecs(); } else { LOG.warn("Could not locate service " + request.getUrl().getHost() + ", setting response codec to application/json"); codecList = new String[]{"application/json"}; } MuonOutboundMessage msg = RRPTransformers.toOutbound(config.getServiceName(), request.getUrl().getHost(), response, codecs, codecList); api2.left().send(msg); } }); }); return api2.right(); } @Override public ProtocolDescriptor getProtocolDescriptor() { List<OperationDescriptor> ops = handlers.getHandlers().stream() .map( handler -> new OperationDescriptor(handler.getPredicate().resourceString())) .collect(Collectors.toList()); return new ProtocolDescriptor( RRPTransformers.REQUEST_RESPONSE_PROTOCOL, "Request/ Response Protocol", "Make a single request, get a single response", ops); } @Override public Map<String, SchemaDescriptor> getSchemasFor(String endpoint) { Optional<RequestResponseServerHandler> first = handlers.getHandlers().stream().filter(requestResponseServerHandler -> requestResponseServerHandler.getPredicate().resourceString().equals(endpoint)).findFirst(); return first.map(RequestResponseServerHandler::getDescriptors).orElseGet(Collections::emptyMap); } }