Example #1
0
 void cancel(final HttpServerExchange exchange) {
   final ProxyConnection connectionAttachment = exchange.getAttachment(CONNECTION);
   if (connectionAttachment != null) {
     ClientConnection clientConnection = connectionAttachment.getConnection();
     UndertowLogger.PROXY_REQUEST_LOGGER.timingOutRequest(
         clientConnection.getPeerAddress() + "" + exchange.getRequestURI());
     IoUtils.safeClose(clientConnection);
   } else {
     UndertowLogger.PROXY_REQUEST_LOGGER.timingOutRequest(exchange.getRequestURI());
   }
   if (exchange.isResponseStarted()) {
     IoUtils.safeClose(exchange.getConnection());
   } else {
     exchange.setStatusCode(StatusCodes.SERVICE_UNAVAILABLE);
     exchange.endExchange();
   }
 }
Example #2
0
    @Override
    public void run() {
      ProxyConnection connection = provider.getConnection();
      if (connection == null) {
        logger.error("No connection found to send CRLF keep alive" + " with " + provider);
        return;
      }

      ListeningPoint lp = provider.getListeningPoint(connection.getTransport());

      if (!(lp instanceof ListeningPointExt)) {
        logger.error("ListeningPoint is not ListeningPointExt" + "(or is null)");
        return;
      }

      InetSocketAddress address = connection.getAddress();
      try {
        ((ListeningPointExt) lp)
            .sendHeartbeat(address.getAddress().getHostAddress(), address.getPort());
      } catch (IOException e) {
        logger.error("Error while sending a heartbeat", e);
      }
    }
Example #3
0
    @Override
    public void run() {
      final ClientRequest request = new ClientRequest();

      StringBuilder requestURI = new StringBuilder();
      if (!clientConnection.getTargetPath().isEmpty()
          && !clientConnection.getTargetPath().equals("/")) {
        requestURI.append(clientConnection.getTargetPath());
      }

      if (exchange.isHostIncludedInRequestURI()) {
        int uriPart = exchange.getRequestURI().indexOf("//");
        if (uriPart == -1) {
          requestURI.append(exchange.getRequestURI());
        } else {
          uriPart = exchange.getRequestURI().indexOf("/", uriPart);
          requestURI.append(exchange.getRequestURI().substring(uriPart));
        }
      } else {
        requestURI.append(exchange.getRequestURI());
      }
      String qs = exchange.getQueryString();
      if (qs != null && !qs.isEmpty()) {
        requestURI.append('?');
        requestURI.append(qs);
      }
      request.setPath(requestURI.toString()).setMethod(exchange.getRequestMethod());
      final HeaderMap inboundRequestHeaders = exchange.getRequestHeaders();
      final HeaderMap outboundRequestHeaders = request.getRequestHeaders();
      copyHeaders(outboundRequestHeaders, inboundRequestHeaders);

      if (!exchange.isPersistent()) {
        // just because the client side is non-persistent
        // we don't want to close the connection to the backend
        outboundRequestHeaders.put(Headers.CONNECTION, "keep-alive");
      }
      if ("h2c".equals(exchange.getRequestHeaders().getFirst(Headers.UPGRADE))) {
        // we don't allow h2c upgrade requests to be passed through to the backend
        exchange.getRequestHeaders().remove(Headers.UPGRADE);
        outboundRequestHeaders.put(Headers.CONNECTION, "keep-alive");
      }

      for (Map.Entry<HttpString, ExchangeAttribute> entry : requestHeaders.entrySet()) {
        String headerValue = entry.getValue().readAttribute(exchange);
        if (headerValue == null || headerValue.isEmpty()) {
          outboundRequestHeaders.remove(entry.getKey());
        } else {
          outboundRequestHeaders.put(entry.getKey(), headerValue.replace('\n', ' '));
        }
      }

      final SocketAddress address = exchange.getConnection().getPeerAddress();
      final String remoteHost =
          (address != null && address instanceof InetSocketAddress)
              ? ((InetSocketAddress) address).getHostString()
              : "localhost";
      request.putAttachment(ProxiedRequestAttachments.REMOTE_HOST, remoteHost);

      if (reuseXForwarded && request.getRequestHeaders().contains(Headers.X_FORWARDED_FOR)) {
        // We have an existing header so we shall simply append the host to the existing list
        final String current = request.getRequestHeaders().getFirst(Headers.X_FORWARDED_FOR);
        if (current == null || current.isEmpty()) {
          // It was empty so just add it
          request.getRequestHeaders().put(Headers.X_FORWARDED_FOR, remoteHost);
        } else {
          // Add the new entry and reset the existing header
          request.getRequestHeaders().put(Headers.X_FORWARDED_FOR, current + "," + remoteHost);
        }
      } else {
        // No existing header or not allowed to reuse the header so set it here
        request.getRequestHeaders().put(Headers.X_FORWARDED_FOR, remoteHost);
      }

      // if we don't support push set a header saying so
      // this is non standard, and a problem with the HTTP2 spec, but they did not want to listen
      if (!exchange.getConnection().isPushSupported()
          && clientConnection.getConnection().isPushSupported()) {
        request.getRequestHeaders().put(Headers.X_DISABLE_PUSH, "true");
      }

      // Set the protocol header and attachment
      if (reuseXForwarded && exchange.getRequestHeaders().contains(Headers.X_FORWARDED_PROTO)) {
        final String proto = exchange.getRequestHeaders().getFirst(Headers.X_FORWARDED_PROTO);
        request.putAttachment(ProxiedRequestAttachments.IS_SSL, proto.equals("https"));
      } else {
        final String proto = exchange.getRequestScheme().equals("https") ? "https" : "http";
        request.getRequestHeaders().put(Headers.X_FORWARDED_PROTO, proto);
        request.putAttachment(ProxiedRequestAttachments.IS_SSL, proto.equals("https"));
      }

      // Set the server name
      if (reuseXForwarded && exchange.getRequestHeaders().contains(Headers.X_FORWARDED_SERVER)) {
        final String hostName = exchange.getRequestHeaders().getFirst(Headers.X_FORWARDED_SERVER);
        request.putAttachment(ProxiedRequestAttachments.SERVER_NAME, hostName);
      } else {
        final String hostName = exchange.getHostName();
        request.getRequestHeaders().put(Headers.X_FORWARDED_SERVER, hostName);
        request.putAttachment(ProxiedRequestAttachments.SERVER_NAME, hostName);
      }
      if (!exchange.getRequestHeaders().contains(Headers.X_FORWARDED_HOST)) {
        final String hostName = exchange.getHostName();
        if (hostName != null) {
          request.getRequestHeaders().put(Headers.X_FORWARDED_HOST, hostName);
        }
      }

      // Set the port
      if (reuseXForwarded && exchange.getRequestHeaders().contains(Headers.X_FORWARDED_PORT)) {
        try {
          int port =
              Integer.parseInt(exchange.getRequestHeaders().getFirst(Headers.X_FORWARDED_PORT));
          request.putAttachment(ProxiedRequestAttachments.SERVER_PORT, port);
        } catch (NumberFormatException e) {
          int port = exchange.getConnection().getLocalAddress(InetSocketAddress.class).getPort();
          request.getRequestHeaders().put(Headers.X_FORWARDED_PORT, port);
          request.putAttachment(ProxiedRequestAttachments.SERVER_PORT, port);
        }
      } else {
        int port = exchange.getConnection().getLocalAddress(InetSocketAddress.class).getPort();
        request.getRequestHeaders().put(Headers.X_FORWARDED_PORT, port);
        request.putAttachment(ProxiedRequestAttachments.SERVER_PORT, port);
      }

      SSLSessionInfo sslSessionInfo = exchange.getConnection().getSslSessionInfo();
      if (sslSessionInfo != null) {
        X509Certificate[] peerCertificates;
        try {
          peerCertificates = sslSessionInfo.getPeerCertificateChain();
          if (peerCertificates.length > 0) {
            request.putAttachment(
                ProxiedRequestAttachments.SSL_CERT, Certificates.toPem(peerCertificates[0]));
          }
        } catch (SSLPeerUnverifiedException
            | CertificateEncodingException
            | RenegotiationRequiredException e) {
          // ignore
        }
        request.putAttachment(
            ProxiedRequestAttachments.SSL_CYPHER, sslSessionInfo.getCipherSuite());
        request.putAttachment(
            ProxiedRequestAttachments.SSL_SESSION_ID, sslSessionInfo.getSessionId());
      }

      if (rewriteHostHeader) {
        InetSocketAddress targetAddress =
            clientConnection.getConnection().getPeerAddress(InetSocketAddress.class);
        request
            .getRequestHeaders()
            .put(Headers.HOST, targetAddress.getHostString() + ":" + targetAddress.getPort());
        request
            .getRequestHeaders()
            .put(Headers.X_FORWARDED_HOST, exchange.getRequestHeaders().getFirst(Headers.HOST));
      }
      if (log.isDebugEnabled()) {
        log.debugf(
            "Sending request %s to target %s for exchange %s", request, remoteHost, exchange);
      }
      clientConnection
          .getConnection()
          .sendRequest(
              request,
              new ClientCallback<ClientExchange>() {
                @Override
                public void completed(final ClientExchange result) {

                  if (log.isDebugEnabled()) {
                    log.debugf(
                        "Sent request %s to target %s for exchange %s",
                        request, remoteHost, exchange);
                  }
                  result.putAttachment(EXCHANGE, exchange);

                  boolean requiresContinueResponse =
                      HttpContinue.requiresContinueResponse(exchange);
                  if (requiresContinueResponse) {
                    result.setContinueHandler(
                        new ContinueNotification() {
                          @Override
                          public void handleContinue(final ClientExchange clientExchange) {
                            if (log.isDebugEnabled()) {
                              log.debugf(
                                  "Relieved continue response to request %s to target %s for exchange %s",
                                  request, remoteHost, exchange);
                            }
                            HttpContinue.sendContinueResponse(
                                exchange,
                                new IoCallback() {
                                  @Override
                                  public void onComplete(
                                      final HttpServerExchange exchange, final Sender sender) {
                                    // don't care
                                  }

                                  @Override
                                  public void onException(
                                      final HttpServerExchange exchange,
                                      final Sender sender,
                                      final IOException exception) {
                                    IoUtils.safeClose(clientConnection.getConnection());
                                    exchange.endExchange();
                                    UndertowLogger.REQUEST_IO_LOGGER.ioException(exception);
                                  }
                                });
                          }
                        });
                  }

                  // handle server push
                  if (exchange.getConnection().isPushSupported()
                      && result.getConnection().isPushSupported()) {
                    result.setPushHandler(
                        new PushCallback() {
                          @Override
                          public boolean handlePush(
                              ClientExchange originalRequest, final ClientExchange pushedRequest) {

                            if (log.isDebugEnabled()) {
                              log.debugf(
                                  "Sending push request %s received from %s to target %s for exchange %s",
                                  pushedRequest.getRequest(), request, remoteHost, exchange);
                            }
                            final ClientRequest request = pushedRequest.getRequest();
                            exchange
                                .getConnection()
                                .pushResource(
                                    request.getPath(),
                                    request.getMethod(),
                                    request.getRequestHeaders(),
                                    new HttpHandler() {
                                      @Override
                                      public void handleRequest(final HttpServerExchange exchange)
                                          throws Exception {
                                        String path = request.getPath();
                                        int i = path.indexOf("?");
                                        if (i > 0) {
                                          path = path.substring(0, i);
                                        }

                                        exchange.dispatch(
                                            SameThreadExecutor.INSTANCE,
                                            new ProxyAction(
                                                new ProxyConnection(
                                                    pushedRequest.getConnection(), path),
                                                exchange,
                                                requestHeaders,
                                                rewriteHostHeader,
                                                reuseXForwarded));
                                      }
                                    });
                            return true;
                          }
                        });
                  }

                  result.setResponseListener(new ResponseCallback(exchange));
                  final IoExceptionHandler handler =
                      new IoExceptionHandler(exchange, clientConnection.getConnection());
                  if (requiresContinueResponse) {
                    try {
                      if (!result.getRequestChannel().flush()) {
                        result
                            .getRequestChannel()
                            .getWriteSetter()
                            .set(
                                ChannelListeners.flushingChannelListener(
                                    new ChannelListener<StreamSinkChannel>() {
                                      @Override
                                      public void handleEvent(StreamSinkChannel channel) {
                                        Transfer.initiateTransfer(
                                            exchange.getRequestChannel(),
                                            result.getRequestChannel(),
                                            ChannelListeners.closingChannelListener(),
                                            new HTTPTrailerChannelListener(exchange, result),
                                            handler,
                                            handler,
                                            exchange.getConnection().getByteBufferPool());
                                      }
                                    },
                                    handler));
                        result.getRequestChannel().resumeWrites();
                        return;
                      }
                    } catch (IOException e) {
                      handler.handleException(result.getRequestChannel(), e);
                    }
                  }
                  Transfer.initiateTransfer(
                      exchange.getRequestChannel(),
                      result.getRequestChannel(),
                      ChannelListeners.closingChannelListener(),
                      new HTTPTrailerChannelListener(exchange, result),
                      handler,
                      handler,
                      exchange.getConnection().getByteBufferPool());
                }

                @Override
                public void failed(IOException e) {
                  UndertowLogger.PROXY_REQUEST_LOGGER.proxyRequestFailed(
                      exchange.getRequestURI(), e);
                  if (!exchange.isResponseStarted()) {
                    exchange.setStatusCode(StatusCodes.SERVICE_UNAVAILABLE);
                    exchange.endExchange();
                  } else {
                    IoUtils.safeClose(exchange.getConnection());
                  }
                }
              });
    }
Example #4
0
  // TODO: factor out repetitive debugging code
  private synchronized void close(boolean known_invalid) throws SQLException {
    // System.err.println("Closing " + this);
    if (physicalConnection != null) {
      try {
        StringBuffer debugOnlyLog = null;
        if (Debug.DEBUG && known_invalid) {
          debugOnlyLog = new StringBuffer();
          debugOnlyLog.append("[ exceptions: ");
        }

        Exception exc = cleanupUncachedActiveStatements();
        if (Debug.DEBUG && exc != null) {
          if (known_invalid) debugOnlyLog.append(exc.toString() + ' ');
          else
            logger.log(
                MLevel.WARNING,
                "An exception occurred while cleaning up uncached active Statements.",
                exc);
          // exc.printStackTrace();
        }

        try {
          // we've got to use silentClose() rather than close() here,
          // 'cuz if there's still an exposedProxy (say a user forgot to
          // close his Connection) before we close, and we use regular (loud)
          // close, we will try to check this dead or dying PooledConnection
          // back into the pool. We only want to do this when close is called
          // on user proxies, and the underlying PooledConnection might still
          // be good. The PooledConnection itself should only be closed by the
          // pool.
          if (exposedProxy != null) exposedProxy.silentClose(known_invalid);
        } catch (Exception e) {
          if (Debug.DEBUG) {
            if (known_invalid) debugOnlyLog.append(e.toString() + ' ');
            else logger.log(MLevel.WARNING, "An exception occurred.", exc);
            // e.printStackTrace();
          }
          exc = e;
        }
        try {
          this.closeAll();
        } catch (Exception e) {
          if (Debug.DEBUG) {
            if (known_invalid) debugOnlyLog.append(e.toString() + ' ');
            else logger.log(MLevel.WARNING, "An exception occurred.", exc);
            // e.printStackTrace();
          }
          exc = e;
        }

        try {
          physicalConnection.close();
        } catch (Exception e) {
          if (Debug.DEBUG) {
            if (known_invalid) debugOnlyLog.append(e.toString() + ' ');
            else logger.log(MLevel.WARNING, "An exception occurred.", exc);
            e.printStackTrace();
          }
          exc = e;
        }

        if (exc != null) {
          if (known_invalid) {
            debugOnlyLog.append(" ]");
            if (Debug.DEBUG) {
              // 						System.err.print("[DEBUG]" + this + ": while closing a PooledConnection known
              // to be invalid, ");
              // 						System.err.println("  some exceptions occurred. This is probably not a
              // problem:");
              // 						System.err.println( debugOnlyLog.toString() );

              logger.fine(
                  this
                      + ": while closing a PooledConnection known to be invalid, "
                      + "  some exceptions occurred. This is probably not a problem: "
                      + debugOnlyLog.toString());
            }
          } else
            throw new SQLException(
                "At least one error occurred while attempting "
                    + "to close() the PooledConnection: "
                    + exc);
        }
        if (Debug.TRACE == Debug.TRACE_MAX)
          logger.fine("C3P0PooledConnection closed. [" + this + ']');
        // System.err.println("C3P0PooledConnection closed. [" + this + ']');
      } finally {
        physicalConnection = null;
      }
    }
  }