org.eclipse.jetty.server.OptionalSslConnectionFactory Maven / Gradle / Ivy
Show all versions of jetty-server Show documentation
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.server;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A ConnectionFactory whose connections detect whether the first bytes are
* TLS bytes and upgrades to either a TLS connection or to another configurable
* connection.
*
* @deprecated Use {@link DetectorConnectionFactory} with a {@link SslConnectionFactory} instead.
*/
@Deprecated
public class OptionalSslConnectionFactory extends DetectorConnectionFactory
{
private static final Logger LOG = LoggerFactory.getLogger(OptionalSslConnectionFactory.class);
private final String _nextProtocol;
/**
* Creates a new ConnectionFactory whose connections can upgrade to TLS or another protocol.
*
* @param sslConnectionFactory The {@link SslConnectionFactory} to use if the first bytes are TLS
* @param nextProtocol the protocol of the {@link ConnectionFactory} to use if the first bytes are not TLS,
* or null to explicitly handle the non-TLS case
*/
public OptionalSslConnectionFactory(SslConnectionFactory sslConnectionFactory, String nextProtocol)
{
super(sslConnectionFactory);
_nextProtocol = nextProtocol;
}
/**
* Callback method invoked when the detected bytes are not TLS.
* This typically happens when a client is trying to connect to a TLS
* port using the {@code http} scheme (and not the {@code https} scheme).
*
* @param connector The connector object
* @param endPoint The connection EndPoint object
* @param buffer The buffer with the first bytes of the connection
*/
protected void nextProtocol(Connector connector, EndPoint endPoint, ByteBuffer buffer)
{
if (LOG.isDebugEnabled())
LOG.debug("OptionalSSL TLS detection unsuccessful, attempting to upgrade to {}", _nextProtocol);
if (_nextProtocol != null)
{
ConnectionFactory connectionFactory = connector.getConnectionFactory(_nextProtocol);
if (connectionFactory == null)
throw new IllegalStateException("Cannot find protocol '" + _nextProtocol + "' in connector's protocol list " + connector.getProtocols() + " for " + endPoint);
upgradeToConnectionFactory(connectionFactory, connector, endPoint);
}
else
{
otherProtocol(buffer, endPoint);
}
}
/**
* Legacy callback method invoked when {@code nextProtocol} is {@code null}
* and the first bytes are not TLS.
* This typically happens when a client is trying to connect to a TLS
* port using the {@code http} scheme (and not the {@code https} scheme).
* This method is kept around for backward compatibility.
*
* @param buffer The buffer with the first bytes of the connection
* @param endPoint The connection EndPoint object
* @deprecated Override {@link #nextProtocol(Connector, EndPoint, ByteBuffer)} instead.
*/
@Deprecated
protected void otherProtocol(ByteBuffer buffer, EndPoint endPoint)
{
LOG.warn("Detected non-TLS bytes, but no other protocol to upgrade to for {}", endPoint);
// There are always at least 2 bytes.
int byte1 = buffer.get(0) & 0xFF;
int byte2 = buffer.get(1) & 0xFF;
if (byte1 == 'G' && byte2 == 'E')
{
// Plain text HTTP to an HTTPS port,
// write a minimal response.
String body =
"\r\n" +
"\r\n" +
"Bad Request \r\n" +
"" +
"Bad Request
" +
"HTTP request to HTTPS port
" +
"\r\n" +
"";
String response =
"HTTP/1.1 400 Bad Request\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: " + body.length() + "\r\n" +
"Connection: close\r\n" +
"\r\n" +
body;
Callback.Completable completable = new Callback.Completable();
endPoint.write(completable, ByteBuffer.wrap(response.getBytes(StandardCharsets.US_ASCII)));
completable.whenComplete((r, x) -> endPoint.close());
}
else
{
endPoint.close();
}
}
}