@Override
  public void customize(Connector connector, HttpConfiguration channelConfig, Request request) {
    EndPoint endp = request.getHttpChannel().getEndPoint();
    if (endp instanceof DecryptedEndPoint) {
      SslConnection.DecryptedEndPoint ssl_endp = (DecryptedEndPoint) endp;
      SslConnection sslConnection = ssl_endp.getSslConnection();
      SSLEngine sslEngine = sslConnection.getSSLEngine();
      customize(sslEngine, request);

      if (request.getHttpURI().getScheme() == null) request.setScheme(HttpScheme.HTTPS.asString());
    } else if (endp instanceof ProxyConnectionFactory.ProxyEndPoint) {
      ProxyConnectionFactory.ProxyEndPoint proxy = (ProxyConnectionFactory.ProxyEndPoint) endp;
      if (request.getHttpURI().getScheme() == null
          && proxy.getAttribute(ProxyConnectionFactory.TLS_VERSION) != null)
        request.setScheme(HttpScheme.HTTPS.asString());
    }

    if (HttpScheme.HTTPS.is(request.getScheme())) customizeSecure(request);
  }
예제 #2
0
 @Override
 public void succeeded(Connection connection) {
   HttpDestination destination =
       (HttpDestination) context.get(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY);
   if (HttpScheme.HTTPS.is(destination.getScheme())) {
     SslContextFactory sslContextFactory = destination.getHttpClient().getSslContextFactory();
     if (sslContextFactory != null) {
       tunnel(destination, connection);
     } else {
       String message =
           String.format(
               "Cannot perform requests over SSL, no %s in %s",
               SslContextFactory.class.getSimpleName(), HttpClient.class.getSimpleName());
       promise.failed(new IllegalStateException(message));
     }
   } else {
     promise.succeeded(connection);
   }
 }
예제 #3
0
  public HttpDestination(HttpClient client, Origin origin) {
    this.client = client;
    this.origin = origin;

    this.exchanges = newExchangeQueue(client);

    this.requestNotifier = new RequestNotifier(client);
    this.responseNotifier = new ResponseNotifier();

    ProxyConfiguration proxyConfig = client.getProxyConfiguration();
    proxy = proxyConfig.match(origin);
    ClientConnectionFactory connectionFactory = client.getTransport();
    if (proxy != null) {
      connectionFactory = proxy.newClientConnectionFactory(connectionFactory);
    } else {
      if (HttpScheme.HTTPS.is(getScheme()))
        connectionFactory = newSslClientConnectionFactory(connectionFactory);
    }
    this.connectionFactory = connectionFactory;

    String host = getHost();
    if (!client.isDefaultPort(getScheme(), getPort())) host += ":" + getPort();
    hostField = new HttpField(HttpHeader.HOST, host);
  }
/**
 * HTTP Configuration.
 *
 * <p>This class is a holder of HTTP configuration for use by the {@link HttpChannel} class.
 * Typically a HTTPConfiguration instance is instantiated and passed to a {@link ConnectionFactory}
 * that can create HTTP channels (eg HTTP, AJP or SPDY).
 *
 * <p>The configuration held by this class is not for the wire protocol, but for the interpretation
 * and handling of HTTP requests that could be transported by a variety of protocols.
 */
@ManagedObject("HTTP Configuration")
public class HttpConfiguration {
  private List<Customizer> _customizers = new CopyOnWriteArrayList<>();
  private int _outputBufferSize = 32 * 1024;
  private int _requestHeaderSize = 8 * 1024;
  private int _responseHeaderSize = 8 * 1024;
  private int _headerCacheSize = 512;
  private int _securePort;
  private String _secureScheme = HttpScheme.HTTPS.asString();
  private boolean _sendServerVersion = true; // send Server: header
  private boolean _sendXPoweredBy = false; // send X-Powered-By: header
  private boolean _sendDateHeader = false; // send Date: header

  public interface Customizer {
    public void customize(Connector connector, HttpConfiguration channelConfig, Request request);
  }

  public interface ConnectionFactory {
    HttpConfiguration getHttpConfiguration();
  }

  public HttpConfiguration() {}

  /* ------------------------------------------------------------ */
  /**
   * Create a configuration from another.
   *
   * @param config The configuration to copy.
   */
  public HttpConfiguration(HttpConfiguration config) {
    _customizers.addAll(config._customizers);
    _outputBufferSize = config._outputBufferSize;
    _requestHeaderSize = config._requestHeaderSize;
    _responseHeaderSize = config._responseHeaderSize;
    _securePort = config._securePort;
    _secureScheme = config._secureScheme;
    _sendDateHeader = config._sendDateHeader;
    _sendServerVersion = config._sendServerVersion;
    _headerCacheSize = config._headerCacheSize;
  }

  /* ------------------------------------------------------------ */
  /**
   * Add a {@link Customizer} that is invoked for every request received.
   *
   * <p>Customiser are often used to interpret optional headers (eg {@link
   * ForwardedRequestCustomizer}) or optional protocol semantics (eg {@link
   * SecureRequestCustomizer}).
   *
   * @param customizer A request customizer
   */
  public void addCustomizer(Customizer customizer) {
    _customizers.add(customizer);
  }

  /* ------------------------------------------------------------ */
  public List<Customizer> getCustomizers() {
    return _customizers;
  }

  public <T> T getCustomizer(Class<T> type) {
    for (Customizer c : _customizers) if (type.isAssignableFrom(c.getClass())) return (T) c;
    return null;
  }

  @ManagedAttribute("The size in bytes of the output buffer used to aggregate HTTP output")
  public int getOutputBufferSize() {
    return _outputBufferSize;
  }

  @ManagedAttribute("The maximum allowed size in bytes for a HTTP request header")
  public int getRequestHeaderSize() {
    return _requestHeaderSize;
  }

  @ManagedAttribute("The maximum allowed size in bytes for a HTTP response header")
  public int getResponseHeaderSize() {
    return _responseHeaderSize;
  }

  @ManagedAttribute("The maximum allowed size in bytes for a HTTP header field cache")
  public int getHeaderCacheSize() {
    return _headerCacheSize;
  }

  @ManagedAttribute(
      "The port to which Integral or Confidential security constraints are redirected")
  public int getSecurePort() {
    return _securePort;
  }

  @ManagedAttribute(
      "The scheme with which Integral or Confidential security constraints are redirected")
  public String getSecureScheme() {
    return _secureScheme;
  }

  public void setSendServerVersion(boolean sendServerVersion) {
    _sendServerVersion = sendServerVersion;
  }

  @ManagedAttribute("if true, send the Server header in responses")
  public boolean getSendServerVersion() {
    return _sendServerVersion;
  }

  public void setSendXPoweredBy(boolean sendXPoweredBy) {
    _sendXPoweredBy = sendXPoweredBy;
  }

  @ManagedAttribute("if true, send the X-Powered-By header in responses")
  public boolean getSendXPoweredBy() {
    return _sendXPoweredBy;
  }

  public void setSendDateHeader(boolean sendDateHeader) {
    _sendDateHeader = sendDateHeader;
  }

  @ManagedAttribute("if true, include the date in HTTP headers")
  public boolean getSendDateHeader() {
    return _sendDateHeader;
  }

  /* ------------------------------------------------------------ */
  /**
   * Set the {@link Customizer}s that are invoked for every request received.
   *
   * <p>Customisers are often used to interpret optional headers (eg {@link
   * ForwardedRequestCustomizer}) or optional protocol semantics (eg {@link
   * SecureRequestCustomizer}).
   *
   * @param customizers
   */
  public void setCustomizers(List<Customizer> customizers) {
    _customizers.clear();
    _customizers.addAll(customizers);
  }

  /* ------------------------------------------------------------ */
  /**
   * Set the size of the buffer into which response content is aggregated before being sent to the
   * client. A larger buffer can improve performance by allowing a content producer to run without
   * blocking, however larger buffers consume more memory and may induce some latency before a
   * client starts processing the content.
   *
   * @param responseBufferSize buffer size in bytes.
   */
  public void setOutputBufferSize(int responseBufferSize) {
    _outputBufferSize = responseBufferSize;
  }

  /* ------------------------------------------------------------ */
  /**
   * Set the maximum size of a request header.
   *
   * <p>Larger headers will allow for more and/or larger cookies plus larger form content encoded in
   * a URL. However, larger headers consume more memory and can make a server more vulnerable to
   * denial of service attacks.
   *
   * @param requestHeaderSize Max header size in bytes
   */
  public void setRequestHeaderSize(int requestHeaderSize) {
    _requestHeaderSize = requestHeaderSize;
  }

  /* ------------------------------------------------------------ */
  /**
   * Set the maximum size of a response header.
   *
   * <p>Larger headers will allow for more and/or larger cookies and longer HTTP headers (eg for
   * redirection). However, larger headers will also consume more memory.
   *
   * @param responseHeaderSize Response header size in bytes.
   */
  public void setResponseHeaderSize(int responseHeaderSize) {
    _responseHeaderSize = responseHeaderSize;
  }

  /* ------------------------------------------------------------ */
  /**
   * Set the header field cache size.
   *
   * @param headerCacheSize The size in bytes of the header field cache.
   */
  public void setHeaderCacheSize(int headerCacheSize) {
    _headerCacheSize = headerCacheSize;
  }

  /* ------------------------------------------------------------ */
  /**
   * Set the TCP/IP port used for CONFIDENTIAL and INTEGRAL redirections.
   *
   * @param confidentialPort
   */
  public void setSecurePort(int confidentialPort) {
    _securePort = confidentialPort;
  }

  /* ------------------------------------------------------------ */
  /**
   * Set the URI scheme used for CONFIDENTIAL and INTEGRAL redirections.
   *
   * @param confidentialScheme A string like"https"
   */
  public void setSecureScheme(String confidentialScheme) {
    _secureScheme = confidentialScheme;
  }

  @Override
  public String toString() {
    return String.format(
        "%s@%x{%d,%d/%d,%s://:%d,%s}",
        this.getClass().getSimpleName(),
        hashCode(),
        _outputBufferSize,
        _requestHeaderSize,
        _responseHeaderSize,
        _secureScheme,
        _securePort,
        _customizers);
  }
}
예제 #5
0
 @Override
 public URI getURI() {
   String scheme = isSecure() ? HttpScheme.HTTPS.asString() : HttpScheme.HTTP.asString();
   return URI.create(new Origin(scheme, getAddress()).asString());
 }
예제 #6
0
  @Override
  public String encodeURL(String url) {
    final Request request = _channel.getRequest();
    SessionManager sessionManager = request.getSessionManager();
    if (sessionManager == null) return url;

    HttpURI uri = null;
    if (sessionManager.isCheckingRemoteSessionIdEncoding() && URIUtil.hasScheme(url)) {
      uri = new HttpURI(url);
      String path = uri.getPath();
      path = (path == null ? "" : path);
      int port = uri.getPort();
      if (port < 0) port = HttpScheme.HTTPS.asString().equalsIgnoreCase(uri.getScheme()) ? 443 : 80;
      if (!request.getServerName().equalsIgnoreCase(uri.getHost())
          || request.getServerPort() != port
          || !path.startsWith(
              request
                  .getContextPath())) // TODO the root context path is "", with which every non null
                                      // string starts
      return url;
    }

    String sessionURLPrefix = sessionManager.getSessionIdPathParameterNamePrefix();
    if (sessionURLPrefix == null) return url;

    if (url == null) return null;

    // should not encode if cookies in evidence
    if (request.isRequestedSessionIdFromCookie()) {
      int prefix = url.indexOf(sessionURLPrefix);
      if (prefix != -1) {
        int suffix = url.indexOf("?", prefix);
        if (suffix < 0) suffix = url.indexOf("#", prefix);

        if (suffix <= prefix) return url.substring(0, prefix);
        return url.substring(0, prefix) + url.substring(suffix);
      }
      return url;
    }

    // get session;
    HttpSession session = request.getSession(false);

    // no session
    if (session == null) return url;

    // invalid session
    if (!sessionManager.isValid(session)) return url;

    String id = sessionManager.getNodeId(session);

    if (uri == null) uri = new HttpURI(url);

    // Already encoded
    int prefix = url.indexOf(sessionURLPrefix);
    if (prefix != -1) {
      int suffix = url.indexOf("?", prefix);
      if (suffix < 0) suffix = url.indexOf("#", prefix);

      if (suffix <= prefix) return url.substring(0, prefix + sessionURLPrefix.length()) + id;
      return url.substring(0, prefix + sessionURLPrefix.length()) + id + url.substring(suffix);
    }

    // edit the session
    int suffix = url.indexOf('?');
    if (suffix < 0) suffix = url.indexOf('#');
    if (suffix < 0) {
      return url
          + ((HttpScheme.HTTPS.is(uri.getScheme()) || HttpScheme.HTTP.is(uri.getScheme()))
                  && uri.getPath() == null
              ? "/"
              : "")
          + // if no path, insert the root path
          sessionURLPrefix
          + id;
    }

    return url.substring(0, suffix)
        + ((HttpScheme.HTTPS.is(uri.getScheme()) || HttpScheme.HTTP.is(uri.getScheme()))
                && uri.getPath() == null
            ? "/"
            : "")
        + // if no path so insert the root path
        sessionURLPrefix
        + id
        + url.substring(suffix);
  }