content: package org.aion.api.server.http.undertow;
  
  import io.undertow.server.HttpHandler;
  import io.undertow.server.HttpServerExchange;
  import io.undertow.util.Headers;
  import io.undertow.util.HttpString;
  import io.undertow.util.Methods;
  import io.undertow.util.StatusCodes;
  import java.util.Map;
  import org.aion.api.server.rpc.RpcProcessor;
  
  class AionUndertowRpcHandler implements HttpHandler {
      private final boolean corsEnabled;
      private final Map<HttpString, String> corsHeaders;
      private final RpcProcessor rpcProcessor;
  
      public AionUndertowRpcHandler(
              boolean corsEnabled, Map<HttpString, String> corsHeaders, RpcProcessor rpcProcessor) {
          this.corsEnabled = corsEnabled;
          this.corsHeaders = corsHeaders;
          this.rpcProcessor = rpcProcessor;
      }
  
      private void addCorsHeaders(HttpServerExchange exchange) {
          for (Map.Entry<HttpString, String> header : corsHeaders.entrySet()) {
              exchange.getResponseHeaders().put(header.getKey(), header.getValue());
          }
      }
  
      @Override
      public void handleRequest(HttpServerExchange exchange) {
          boolean isPost = Methods.POST.equals(exchange.getRequestMethod());
          boolean isOptions = Methods.OPTIONS.equals(exchange.getRequestMethod());
  
          // only support POST & OPTIONS requests
          if (!isPost && !isOptions) {
              exchange.setStatusCode(StatusCodes.METHOD_NOT_ALLOWED);
              exchange.setPersistent(false); // don't need to keep-alive connection in case of error.
              exchange.endExchange();
              return;
          }
  
          // respond to cors-preflight request
          if (corsEnabled && isOptions) {
              addCorsHeaders(exchange);
              exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
              exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, "0");
              exchange.getResponseSender().send("");
              return;
          }
  
          /** respond to rpc call; {@link io.Undertow.BlockingReceiverImpl#receiveFullString} */
          exchange.getRequestReceiver()
                  .receiveFullString(
                          (_exchange, body) -> {
                              if (corsEnabled) addCorsHeaders(_exchange);
                              _exchange
                                      .getResponseHeaders()
                                      .put(Headers.CONTENT_TYPE, "application/json");
                              _exchange.getResponseSender().send(rpcProcessor.process(body));
                          });
      }
  }
  