【DELPHI】一個TIdHTTPServer元件可以同時處理http和https請求嗎?

2020-12-16 DELPHI

我使用的是tidhttpserver元件,到目前為止執行良好,但是當我使用以下程式碼新增ssl支援時

  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;

伺服器只處理https請求,如果我傳送http請求,則引發此異常
Error accepting connection with SSL. error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request
問題是:我可以使用單個tidhttpserver元件來處理http和https請求?如果答案是肯定的,怎麼做?如果答案是否定的,我必須建立兩個tidhttpserver例項,一個用於http,另一個用於https?

解決辦法

是的,http和https都可以使用一個TIdHTTPServer
如果您使用的是indy 9,那麼它有一個bug,當所有客戶端連線連線到伺服器時,預設情況下都會啟用ssl。要解決此問題,請使用伺服器的OnConnect事件手動關閉SSL(如果連線不在埠443上),例如:

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

如果您使用的是indy 10,則該錯誤已修復,因此預設情況下,所有客戶端連線都將禁用ssl,因此您可以:
如果連線在埠443上,則使用OnConnect事件開啟SSL,例如:
procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext);
begin
  if AContext.Connection.Socket.Binding.Port = 443 then
    TIdSSLIOHandlerSocketBase(AContext.Connection.Socket).PassThrough := False;
end;

(首選)使用newTIdHTTPServer.OnQuerySSLPort事件告訴伺服器哪個埠應使用ssl,例如:
procedure TForm1.IdHTTPServer1QuerySSLPort(APort: TIdPort; var VUseSSL: Boolean);
begin
  VUseSSL := (APort = 443);
end;

出處

Have any Question?

Let us answer it!