4

I am trying to create https server in lazarus using synapse but I am failing. I want to mys server receive data from other https clients. I am sending requests with my browser using https://localhost:1500 and mys server is receiving signals. But when I try to read sent data I receive nothing. When I tested simple http server all worked fine. But now in case of https it is not working. I am using ubuntu 15.04 as my OS

s := ASocket.RecvString(timeout); //returns noething

My sample code:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

uses
  blcksock, sockets, Synautil, ssl_openssl, ssl_openssl_lib;

procedure AttendConnection(ASocket: TTCPBlockSocket);
var
  timeout: integer;
  s: string;
  method, uri, protocol: string;
  OutputDataString: string;
  ResultCode: integer;
begin
  timeout := 1000;

  WriteLn('Received headers+document from browser:');

  //read request line
  s := ASocket.RecvString(timeout);
  WriteLn(s);
  method := fetch(s, ' ');
  uri := fetch(s, ' ');
  protocol := fetch(s, ' ');

  //read request headers
  repeat
    s := ASocket.RecvString(Timeout);
    WriteLn(s);
  until s = '';

  // Now write the document to the output stream

  if uri = '/' then
  begin
    // Write the output document to the stream
    OutputDataString :=
      '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
      + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + CRLF
      + '<html><h1>Teste</h1></html>' + CRLF;

    // Write the headers back to the client
    ASocket.SendString('HTTP/1.0 200' + CRLF);
    ASocket.SendString('Content-type: Text/Html' + CRLF);
    ASocket.SendString('Content-length: ' + IntTostr(Length(OutputDataString)) + CRLF);
    ASocket.SendString('Connection: close' + CRLF);
    ASocket.SendString('Date: ' + Rfc822DateTime(now) + CRLF);
    ASocket.SendString('Server: Servidor do Felipe usando Synapse' + CRLF);
    ASocket.SendString('' + CRLF);

  //  if ASocket.lasterror <> 0 then HandleError;

    // Write the document back to the browser
    ASocket.SendString(OutputDataString);
  end
  else
    ASocket.SendString('HTTP/1.0 404' + CRLF);
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  ListenerSocket, ConnectionSocket: TTCPBlockSocket;
begin
  ListenerSocket := TTCPBlockSocket.Create;
  ConnectionSocket := TTCPBlockSocket.Create;

  ListenerSocket.CreateSocket;
  ListenerSocket.SSL.CertificateFile := '/home/imants/projects/apps/medieval/bin/40669199_localhost_8080.cert';
  ListenerSocket.SSL.PrivateKeyFile := '/home/imants/projects/apps/medieval/bin/40669199_localhost_8080.key';
  ListenerSocket.SSLDoConnect;
  ListenerSocket.setLinger(true,10);
  ListenerSocket.bind('localhost','1500');
  ListenerSocket.listen;

  repeat
    if ListenerSocket.canread(1000) then
    begin
      ConnectionSocket.Socket := ListenerSocket.accept;
      WriteLn('Attending Connection. Error code (0=Success): ', ConnectionSocket.lasterror);
      AttendConnection(ConnectionSocket);
      ConnectionSocket.CloseSocket;
    end;
  until false;

  ListenerSocket.Free;
  ConnectionSocket.Free;
end;

end.
Imants Gulbis
  • 87
  • 1
  • 8
  • Did you follow (or find) the instructions at http://www.ararat.cz/synapse/doku.php/public:howto:httpsserver ? – Rik Oct 05 '15 at 12:22
  • No I found that example else where I will try to check HTTP Server Demo (which is I guess comes with synapse) and will try to change it accordingly. – Imants Gulbis Oct 05 '15 at 12:54
  • unfortunately http server example witch comes with synapse is windows specifics because it uses winsock unit witch Lazarus do not support at least in Linux – Imants Gulbis Oct 08 '15 at 12:07
  • As far as I can remember you can just substitute all winsock occurrences with synsock and it should work in Lazarus on Linux. (I could be wrong but try it) – Rik Oct 08 '15 at 13:42
  • Although I would advise using the latest svn version of synapse, the stable version 40 includes the httpsserv (https server) example. Try changing the winsock in synsock and removing any windows-clause. If that doesn't work you might want to try adjusting this example: https://www.mail-archive.com/synalist-public@lists.sourceforge.net/msg02225.html – Rik Oct 08 '15 at 13:58
  • Thanks that actually work. I created https server with synapse. Maybe you want to put it as answer so I can accept it? – Imants Gulbis Oct 09 '15 at 05:35

2 Answers2

3

There are two sources, that I know of, with an example for a HTTP(s) server in Synapse.

The first example is in the Synapse stable package (release 40). Although I would recommend you use the SVN version (you can use the Download Snapshot button on that page) you can still use the examples in the "release 40 package".

The example in synapse40\source\demo\httpsserv should be usable as HTTPS-server. If it's not you could take the httpserv (HTTP) example and change it as shown here. (But I think the httpsserv is just the same with those modifications)

If you're on Linux (Lazarus) you'll need to change every occurrence of winsock to synsock and remove any windows-clause.

Another example can be found here. (Direct download of SynHttp.zip) As far as I could see it also has HTTPS-server functionality.

Rik
  • 1,982
  • 1
  • 17
  • 30
2

I know that you want to use Synapse, but you may want to take a look at Indy. I have been developing server/client apps with indy for some years and I like it. It's working fine with windows and linux (32bit, 64bit, arm...) and has some nice features. You could use the TIdHTTPServer component. Moreover get an IOHandlerSSLOpenSSL. The event OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo) is the most important one. It allows access to the Request (like A ARequestInfo.Document) and to your HTTP response (AResponseInfo).

MBDev
  • 442
  • 1
  • 4
  • 14
  • I used indy and it worked grate. But it has some bad issues with Lazarus like my automated build server cannot compile it 100% because of some bugs in Lazarus or they're package. When compiling it throws cannot find IdStreamVCL :(. So I now try to use some other methods. But if I will not find something then yes Indy it is. – Imants Gulbis Oct 05 '15 at 08:20
  • 1
    Installing Indy for Lazarus is a mess, but you don't need to :) You could just copy the indy folder into your project folder. In Lazarus press Shift + Ctrl + F11 and select Compiler Options -> Paths. Add your Indy source folder (Indy\source) to other unit files and your done :) Just add your needed units and create the components at runtime. – MBDev Oct 05 '15 at 09:34
  • Your advice helped me to sort out problems with indy. It is not the best solution which I would wanted bet it is better than that it was. But as this did not answer my original question I will not accept this as answer. – Imants Gulbis Oct 05 '15 at 10:37