Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a single TIdHTTPServer component handle http and https request in the same time?

Tags:

http

delphi

indy

I'm using a TIdHTTPServer component, so far is working fine, but when I added SSL support using this code

  SSLHandler:= TIdServerIOHandlerSSLOpenSSL.Create(nil);
  SSLHandler.SSLOptions.CertFile := 'foo.pem';
  SSLHandler.SSLOptions.KeyFile := 'foo.pem';
  SSLHandler.SSLOptions.RootCertFile := 'foo.pem';
  SSLHandler.SSLOptions.Method := sslvSSLv23;
  SSLHandler.SSLOptions.Mode := sslmServer;

  SSLHandler.SSLOptions.VerifyDepth := 1;
  SSLHandler.SSLOptions.VerifyMode := [sslvrfPeer,sslvrfFailIfNoPeerCert,sslvrfClientOnce];

  idHttpServer1.IOHandler := SSLHandler;
  IdHTTPServer1.Bindings.Add.Port := 80;  
  IdHTTPServer1.Bindings.Add.Port := 443;       
  IdHTTPServer1.Active := True;

The server only process https requests and if I send a http request this exception is thrown

Error accepting connection with SSL. error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request

The question is : I can use a single TIdHTTPServer component to process the http and https requests? if the answer is Yes how this can be done? If the answer is No, I must create two TIdHTTPServer instances one for http and another for https?

like image 460
Salvador Avatar asked Jul 22 '13 19:07

Salvador


1 Answers

Yes, you can use a single TIdHTTPServer for both HTTP and HTTPS.

If you are using Indy 9, then it has a bug where all client connections will have SSL enabled by default when they connect to the server. To work around that, use the server's OnConnect event to manually turn off SSL if the connection is not on port 443, eg:

procedure TForm1.IdHTTPServer1Connect(AThread: TIdPeerThread);
begin
  if AThread.Connection.Socket.Binding.Port <> 443 then
    TIdSSLIOHandlerSocket(AThread.Connection.Socket).PassThrough := True;
end;

If you are using Indy 10, then that bug was fixed, so all client connections will have SSL disabled by default, so you can either:

  1. use the OnConnect event to turn on SSL if the connection is on port 443, eg:

    procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext);
    begin
      if AContext.Connection.Socket.Binding.Port = 443 then
        TIdSSLIOHandlerSocketBase(AContext.Connection.Socket).PassThrough := False;
    end;
    
  2. (preferred) use the new TIdHTTPServer.OnQuerySSLPort event to tell the server which port should use SSL or not, eg:

    procedure TForm1.IdHTTPServer1QuerySSLPort(APort: TIdPort; var VUseSSL: Boolean);
    begin
      VUseSSL := (APort = 443);
    end;
    
like image 140
Remy Lebeau Avatar answered Nov 14 '22 23:11

Remy Lebeau