A TLS server (TsgcWebSocketServer, TsgcWebSocketHTTPServer and TsgcHTTPServer with the default Indy, IOCP or EPOLL IOHandler) can also accept plain HTTP and WebSocket connections on the same port it uses for TLS. When this option is enabled, the server peeks at the first byte of every new connection. A $16 byte (TLS handshake record) means the client starts a TLS handshake, any other byte means the connection is served as plain text. If no byte arrives within PlainTextTimeout, the connection is treated as TLS, which is the previous behaviour. With the IOCP and EPOLL IOHandlers the decision is made on the first data received, without blocking, and PlainTextTimeout is not used.
The typical use is migrating an existing published plain HTTP port to HTTPS without changing the port configured on the clients. Enable AllowPlainText while the clients are updated, and switch it off again once all of them use TLS.
Boolean, default False. When True, the TLS listener also accepts plain connections on the same port.ptpServe (default): the plain request is served normally.ptpRedirect: the server answers 308 Permanent Redirect to https://<Host><path>, so the client keeps the method and the body. If the request has no Host header, the server answers 400 Bad Request.ptpReject: the server answers 400 Bad Request and closes the connection.Integer, milliseconds, default 5000. Time to wait for the first byte of the client before the connection is treated as TLS. It only applies to the default Indy IOHandler.Boolean of the server connection (TsgcWSConnectionServer), True when the connection uses TLS. The server method IsTLS(AContext) returns the same value from the TIdContext of a request.The enumeration TsgcSSLPlainTextPolicy is declared in the unit sgcWebSocket_Types.
Start a server on port 443 that accepts TLS and plain connections and serves both.
oServer := TsgcWebSocketHTTPServer.Create(nil);
oServer.SSL := True;
oServer.Port := 443;
oServer.SSLOptions.Port := 443;
oServer.SSLOptions.CertFile := 'c:\certificates\mycert.pem';
oServer.SSLOptions.KeyFile := 'c:\certificates\mycert.pem';
oServer.SSLOptions.RootCertFile := 'c:\certificates\mycert.pem';
oServer.SSLOptions.AllowPlainText := True;
oServer.SSLOptions.PlainTextPolicy := ptpServe;
oServer.Active := True;
To know whether a request uses TLS, call the server method IsTLS(AContext), for example in the OnCommandGet or OnCommandOther events. The TLS property of the connection (TsgcWSConnectionServer) is also available.
procedure OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
if TsgcWebSocketHTTPServer1.IsTLS(AContext) then
AResponseInfo.ContentText := 'Secure connection'
else
AResponseInfo.ContentText := 'Plain connection, please use https://';
end;
TLS value read inside OnConnect is not yet reliable. From the first request on, it is correct.SecurityOptions) are only sent on TLS connections, never on plain ones.