#51 Re: mORMot 1 » Websockets client - how to detect the closing of the socket? » 2019-05-27 09:39:28

In the code that I showed in the example, there are two events:

procedure TLogClientWebsockets.OnClientDisconnected(sender: TObject);
begin
  //   disconnect event handling is never called!!
end;

procedure TLogClientWebsockets.OnWebSocketsClosed(sender: TObject);
begin
  //   disconnect event handling is never called!!
end;


None of these events is called, so I ask what I am doing wrong or how to do it correctly?

#52 Re: mORMot 1 » Websockets client - how to detect the closing of the socket? » 2019-05-27 06:30:20

So there is no way to know from the client side (callback implementation side) that the connection has died?

My problem is protection against network errors and the possibility of resuming the connection. How to do it?

#53 mORMot 1 » Websockets client - how to detect the closing of the socket? » 2019-05-26 10:45:46

jaclas
Replies: 22

Based on example 31, I wrote a simple service for uploading logs using websockets.
However, I would like the client side (which implements the callback class) to receive an event in the event of a lost connection so that it can re-connect to the server and pass the callback interface.

I made this code for client:

procedure TLogClientWebsockets.OnClientDisconnected(sender: TObject);
begin
  //   disconnect event handling is never called!!
end;

procedure TLogClientWebsockets.OnWebSocketsClosed(sender: TObject);
begin
  //   disconnect event handling is never called!!
end;

procedure TLogClientWebsockets.Start();
begin
  fModel := TSQLModel.Create([], cRemoteLogRootName);

  fRestClient := TSQLHttpClientWebsockets.Create('127.0.0.1', cRemoteLogHTTPPort.ToString, fModel);
  fRestClient.Model.Owner := fRestClient;

  fRestClient.OnWebSocketsClosed := OnWebSocketsClosed;
  fRestClient.WebSockets.OnWebSocketsClosed := OnWebSocketsClosed;
  fRestClient.WebSockets.Settings.OnClientDisconnected := OnClientDisconnected;
  fRestClient.WebSockets.Settings.HeartbeatDelay := 3000;
  fRestClient.WebSockets.Settings.DisconnectAfterInvalidHeartbeatCount := 3;
  fRestClient.WebSocketLoopDelay := 100;
  fRestClient.WebSocketsUpgrade(cWebSocketEncryptionKey);
  fRestClient.ServiceDefine([ILogService], sicShared);

  if not fRestClient.Services.Resolve(ILogService, fService) then
    raise EServiceException.Create('Service ILogService unavailable');

  fLogManager := TLogManager.Create(TPanel(fLogPanel), 0, nil);
  fCallback := TRemoteLogCallback.Create(fLogManager, fRestClient, IRemoteLogCallback, fLogPanel.Handle);
  fService.StartLogService(fCallback);
end;

Then I run the application and during transmission using TCPView (from Sysinternals) I close the socket that supports the websockets connection. On the server side, the onClientDisconnect event fires. But nothing is happening on the client's side!
How to detect connection loss from the client side?

#54 Re: mORMot 1 » Does gzip response work properly? » 2019-01-25 15:56:38

I use Fiddler this time. It seems, however, that large files are also not compressed, see:

78mFK6XMsYHauGK2Ctz4SEE8qQqDjx9hwlnBIFo30w3T6GPAZJ6nOCm0t5d5UCEL.png

#55 mORMot 1 » Does gzip response work properly? » 2019-01-25 15:03:33

jaclas
Replies: 3

Maybe I'm wrong, but the server's answer is probably not gzipped. Please look at the headings:

rBUXRwbDCyk1TpagvlzFqmEKSCqrSYvE1l6Mc9Qfx2ALKARbmmh5YLimOy8csuGN.png

What needs to be set that mORMot used gzip compression?

See on MDN documentation:

https://developer.mozilla.org/en-US/doc … _with_gzip

#56 Re: mORMot 1 » Get available webapi from server » 2018-10-08 12:02:11

Maybe we do not understand a bit.
I'm doing an HTTP server with several REST servers that have dozens of methods.
Now a colleague who is going to write a JS or PHP client asks me for an API.
What should I give him? Pascal files with data types and interface definitions?

#57 Re: mORMot 1 » Get available webapi from server » 2018-10-08 10:03:02

No, no, I need this for own convenience, only for internal use. For easier testing of clients written on other platforms.
Now I have to fold these addresses manually and I'm often wrong, I'm wasting many time.

#58 mORMot 1 » Get available webapi from server » 2018-10-08 07:47:58

jaclas
Replies: 7

I have an example server:

  TMyService = class(TInterfacedObject, IMyService)
  public
    procedure GetSomeData(const ID: integer; out Data: TSomeData);
    procedure GetOtherData(const ID: integer; out Data: TOtherData);
  end;

  aModel := TSQLModel.Create([]);
  try
    // create a fast in-memory ORM server
    aRest := TSQLRestServerFullMemory.Create(aModel,'',false,false);
    try
      aRest.ServiceRegister(TMyService,[TypeInfo(IMyService)],sicShared);
      aServer := TSQLHttpServer.Create('8090', [aRest], '+', useHttpApiRegisteringURI);
      try
        writeln('Background server is running'#10);
        write('Press [Enter] to close the server.');
        ReadLn;
      finally
        aServer.Free;
      end;
    finally
      aDB.Free;
    end;

Is there a method/function to get from the server information about the available API in the form of a list of simple links for a specific service?

Something like that:

var
 list : TStringList;
 
list := server.GetAvailableAPI('MyService');

//or maybe

list := aRest.GetAvailableAPI('https://server.adrress.com', 'MyService');

in list:

 https://server.adrress.com:8090/root/MyService/GetSomeData
 https://server.adrress.com:8090/root/MyService/GetOtherData

I particularly care about combining the http address (with port if <> 80 or 443), root address, service name and method name.

#59 Re: Other components » SynMustache and RenderJSON and Args param » 2018-08-18 09:07:29

Look closely. See that in the RenderJSON() function the Params parameter is next to the Args parameter:

const Args,Params: array of const;

And Params parameter contains values as in FormatUTF8(). But for what is Args?

#60 Other components » SynMustache and RenderJSON and Args param » 2018-08-17 12:52:13

jaclas
Replies: 3

I try use method:

    /// renders the {{mustache}} template from JSON defined context
    // - the context is given via a JSON object, defined with parameters
    // - you can specify a list of partials via TSynMustachePartials.CreateOwned,
    // a list of Expression Helpers, or a custom {{"English text}} callback
    // - is just a wrapper around Render(_JsonFastFmt())
    // - you can write e.g. with the extended JSON syntax:
    // !   html := mustache.RenderJSON('{name:?,value:?}',[],['Chris',10000]);
    // - set EscapeInvert = true to force {{value}} NOT to escape HTML chars
    // and {{{value}} escaping chars (may be useful e.g. for code generation)
    function RenderJSON(const JSON: RawUTF8; const Args,Params: array of const;
      Partials: TSynMustachePartials=nil; Helpers: TSynMustacheHelpers=nil;
      OnTranslate: TOnStringTranslate=nil;
      EscapeInvert: boolean=false): RawUTF8; overload;

but what is Args parameter? In the above example Args is passed as empty array.

#61 Re: mORMot 1 » How to pass xml to interface based service » 2018-07-28 07:02:27

Ok, I read this article http://blog.synopse.info/post/2011/07/0 … te-binding and now I know that mORMot has own late binding, and fast :-)

#62 Re: mORMot 1 » How to pass xml to interface based service » 2018-07-27 08:47:20

Variant is a magic, but without compile time checked and code insight. And it is quite slow.

#63 Re: mORMot 1 » Intreface based service and JS client » 2018-07-27 08:43:13

You are right, after change param type to RawUTF8 values are corrected. Thx Arnaud!

#64 mORMot 1 » Potential bug? » 2018-07-26 18:09:18

jaclas
Replies: 1

Enter/Leave critical section without try..finally.

In mORMot.pas, procedure ComputeResult:

    if ForceServiceResultAsXMLObjectNameSpace='' then
      ForceServiceResultAsXMLObjectNameSpace := Service.ResultAsXMLObjectNameSpace;
    with Server.fStats do begin
      EnterCriticalSection(fLock);  <-- is there no lack of try finally?
      inc(fServiceInterface);
      Changed;
      LeaveCriticalSection(fLock); <--
    end;

#65 mORMot 1 » Intreface based service and JS client » 2018-07-26 17:58:11

jaclas
Replies: 2

I have service with method:

function TServiceBase.LogOn(const aEmail, aPassHash, aAPIKey, aResourceIdentifier: RawByteString; aClientSalt: UInt32): RawUTF8;

I call this from Delphi client and method is called properly, in log I see:

[MainEventLog] 2018-07-26 19:51:27.13 call  	ss.Rest.ServicesAccessAdministration.TAccessAdministrationRest(7E94AF60)
 IAccessAdministrationService.LogOn["ZWdveWFAb25ldC5wbA==",
"Y2MyNTBmNTAzMzIyNmVhYjk4Y2ExODliMzBhZmMzYjAwODQ0OGVkMTg0YzFhYWQ0NmQ4NzIwMTQyZTJjMDk2ZA==","QVBJS0VZLUFCQ0RFLUZHSElK",
"WFlaLUFCQy0xMjM=",8493]

but when I call from JS client (based on jquery) then request in log looks:

[MainEventLog] 2018-07-26 19:51:27.13 call  	ss.Rest.ServicesAccessAdministration.TAccessAdministrationRest(7E94AF60)
 IAccessAdministrationService.LogOn{"aEmail":"test@test.pl","aPassHash":"2676afb19748e6fc5ed1320df9f8d4a7c9fb41b6ef997e2cb4998ff10dd1007c",
"aAPIKey":"KEY_FOR_TEST","aResourceIdentifier":"SomeResourceId","aClientSalt":693}

and method LogOn is called with empty parameters (except aClientSalt, this param has value) :-(

I don't JS developer, where I should search problem?

#66 mORMot 1 » GetTickCount64() - returned value type » 2018-07-23 11:49:20

jaclas
Replies: 0

In SynCommons GetTickCount64 is declared as function that return Int64 value:

var
  /// the number of milliseconds that have elapsed since the system was started
  // - compatibility function, to be implemented according to the running OS
  // - will use the corresponding native API function under Vista+, or
  // will emulate it for older Windows versions

  GetTickCount64: function: Int64; stdcall;

procedure RetrieveSystemInfo;
var
[...]
begin
  [...]
  GetTickCount64 := GetProcAddress(Kernel,'GetTickCount64');
  if not Assigned(GetTickCount64) then
    GetTickCount64 := @GetSystemTimeMillisecondsForXP;

but WinAPI function return UInt64:

https://msdn.microsoft.com/pl-pl/librar … s.85).aspx

Does the declaration from Int64 do not interfere with UInt64 from WinAPI?

#67 Re: mORMot 1 » Help needed with TAESECB » 2018-06-28 12:08:17

1. EncryptPKCS7() generate random IV (initialization vector), the result will be different each time for the same input data
try this method:

    /// perform the AES cypher in the corresponding mode
    // - when used in block chaining mode, you should have set the IV property
    procedure Encrypt(BufIn, BufOut: pointer; Count: cardinal); virtual; abstract;

but you must known and pass IV

2. You use encoding to Base64, but you expected result in hex?

#68 Other components » AES encrypt and IV question » 2018-06-28 09:14:43

jaclas
Replies: 1

AES and other block cipher algorithms uses a initialization vector as first block to encode input data.

But when I call method (or other with IVAtBeginning param):

TAESxxx.EncryptPKCS7(const Input: TBytes;  IVAtBeginning: boolean): TBytes; 

with IVAtBeginnig = False, then as IV is used an empty array?

#69 Re: mORMot 1 » TAESWriteStream - chaining mode » 2018-05-12 07:29:47

array of byte :-)
I need to encrypt stream (with chaining mode), how to do it best?

Like this?

procedure AESstreamCrypt(const aInStream, aOutStream: TStream; const aKey: TBytes; const aIV: TAESBlock);
var
  lInput : TBytes;
  lOutput : RawByteString;
begin
  lAES := TAESCBC.Create(aKey[0], lKeySize);
  try
    lAES.IV := aIV;
    aInStream.Position := 0;

    // copy aInStream to TBytes local variable
    SetLength(lInput, aInStream.Size);
    aInStream.ReadBuffer(lInput[0], aInStream.Size);

    //encypt TBytes
    lOutput := lAES.EncryptPKCS7(lInput, False);

    //copy encrypted data do output stream
    aOutStream.Write(lOutput[1], Length(lOut));
  finally
    lAES.Free;
  end;
end;

#70 Re: mORMot 1 » TAESWriteStream - chaining mode » 2018-05-11 18:53:26

So how to encrypt streams? By copying them to the array?

#71 mORMot 1 » TAESWriteStream - chaining mode » 2018-05-11 12:25:56

jaclas
Replies: 5

What chaining mode does TAESWriteStream use?

#74 Re: mORMot 1 » Proposal for a new behavior for TObjectDynArrayWrapper/IObjectDynArray » 2018-02-15 16:44:24

I am voting for the extension of the TObjectDynArrayWrapper class by the OwnsObjects parameter.
This change don't break the existing interface (default OwnsObjects is True) and extends class functionality significantly.

Who else supports this idea? :-)

#77 Re: mORMot 1 » Send binary data in interface-based service - without encoding! » 2018-02-13 09:31:01

F3oDCU6q.png

is not exactly like you wrote:

"if you use default TSQLRestRoutingREST routing, and defined a single RawByteString or TSQLRawBlob input parameter, it will be processed as a raw POST with binary body defined with mime-type 'application/octet-stream'"

Can you correct it?

#78 Re: mORMot 1 » Send binary data in interface-based service - without encoding! » 2018-02-12 21:06:33

But how to set it? For now I don't set the Content-Type header.

#79 Re: mORMot 1 » Send binary data in interface-based service - without encoding! » 2018-02-12 14:28:15

For send PDF file header is:

POST /server/SomeService.SendFilePart HTTP/1.1
Accept: */*
FILEID: 84317faa3d2516d189da1e356e12e4fe5f55eeea8970a09d26739ec690e0c4fb
Content-Type: application/pdf
User-Agent: Mozilla/5.0 (Windows; mORMot 1.18 TWinINet)
Host: localhost:8090
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Content-Length: 1048576

%PDF-1.4
%ŕáâă
2 0 obj
<</Filter /FlateDecode
/Length 11656951
>>
stream
xśĚÝÁŽćHš¬ç}_ĹÜŔNŇé$·
[...]­

for XML:

POST /server/SomeService.SendFilePart HTTP/1.1
Accept: */*
FILEID: 8472f3d762a2f42ebde6a9bf9fba0806d9c8e59221fc0dafd3fe05dd1a94050c
Content-Type: application/octet-stream
User-Agent: Mozilla/5.0 (Windows; mORMot 1.18 TWinINet)
Host: localhost:8090
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Content-Length: 1048576

<?xml version="1.0" encoding="UTF-8"?>
<Migration>
<Session Type="Online">
	<Platform Type="Source">
[...]

Content-Type is different for PDF and for XML, how to force properly value of Content-Type?

#80 Re: mORMot 1 » Send binary data in interface-based service - without encoding! » 2018-02-12 13:13:05

Not supported?

Then why you wrote above:

"As an alternative, if you use default TSQLRestRoutingREST routing, and defined a single RawByteString or TSQLRawBlob input parameter, it will be processed as a raw POST with binary body defined with mime-type 'application/octet-stream'. This may be more optimized for remote access over the Internet.
See https://synopse.info/fossil/info/4cfc722c69"
?

And what changes has this commit? https://synopse.info/fossil/info/4cfc722c69


btw on other (text) files this way acts properly (send without json and base64 encoding)

#81 Re: mORMot 1 » Send binary data in interface-based service - without encoding! » 2018-02-12 12:30:55

I found problem on this topic.
I get exception:

TSQLRestRoutingREST.Error: 
{"errorCode":406,  "errorText":"sicShared execution failed (probably due to bad input parameters) for TMyService.SendFilePart"}

See for reason:

EenCksJv.png

#83 Re: mORMot 1 » Client-server contract incompatibilty » 2018-02-08 14:04:14

Ok, I remove this line, but I have a doubt and a question!

When I create TServiceFactoryServer object and specify the contract in the constructor:

  sf := ServiceRegister(fMyService as TInterfacedObject, [TypeInfo(IMyService)], '2');

then in ContractExpected property I have value: "2" (with quote chars)

sf.ContractExpected is equal "2"

But (!) when I use setter:

  sf.ContractExpected := '2';

then property is set to a different value! ContractExpected property has a: 2 (without quote chars!)

sf.ContractExpected is equal 2

This is IMHO a incorrect behavior, the value set by the constructor should be the same as set by property.

#84 Re: mORMot 1 » Client-server contract incompatibilty » 2018-02-07 12:29:29

I found on server side:

NSZp6rv8.png


But I have it in the code for a very long time! And maybe the last versions of the mORMot have changed something here...

#85 Re: mORMot 1 » Client-server contract incompatibilty » 2018-02-07 10:06:57

BtdPrwv5.png

And I found problematic place, in constructor:

constructor TServiceFactory.Create(aRest: TSQLRest; aInterface: PTypeInfo; 
                                aInstanceCreation: TServiceInstanceImplementation; const aContractExpected: RawUTF8);

See:

SfiMe1yl.png

#86 Re: mORMot 1 » Client-server contract incompatibilty » 2018-02-07 09:51:16

Client side:

    fServiceFactory := fClient.ServiceRegister(TypeInfo(IMyInterface), sicShared, '2') as TServiceFactoryClient;

server side:

  sf := ServiceRegister(fMyService as TInterfacedObject, [TypeInfo(IMyService)], '2');
  sf.ContractExpected := '2';

and I still get exception:

{"Message":"TServiceFactoryClient.Create(): server's IMyService 
contract differs from client's: expected [\"2\"], received [2] - you may need to upgrade your 1.0.0.221 client to match  server expectations"}

Why? Where I make mistake?

#87 Re: mORMot 1 » Client-server contract incompatibilty » 2018-02-06 21:50:22

I always recompile server and client.

But why ContractExpected value has quoted chars around "1"? See Watch List and values of compared variables.

#88 mORMot 1 » Client-server contract incompatibilty » 2018-02-06 12:43:19

jaclas
Replies: 12

I get exception:

TServiceFactoryClient.Create(): server''s IMyService contract differs from 
client''s: expected ["1"], received [1] - 
you may need to upgrade your 1.0.0.219 client to match  server expectations'

But see screen from debug session (mORMot.pas)

uR5XXilJ.png

This is my mistake or mORMot has problem? :-)


ps. latest mORMot, Delphi Tokyo

#89 mORMot 1 » SynLZ vs other LZ algorithm » 2017-12-13 11:36:21

jaclas
Replies: 1

Is SynLZ binary compatible with other LZ algorithm? I want to compress files on client and sent to the server (and on server decompress then), but clients will be created not only in Delphi (eg in Java). Is the use of the SynLZ algorithm limited only to Delphi?

#90 Re: mORMot 1 » Problem with WinHTTP client - error 87 » 2017-12-12 15:11:08

After commented this line TWinHTTP client connect properly. And what now?

#91 Re: mORMot 1 » Problem with WinHTTP client - error 87 » 2017-12-12 15:05:51

Yes, you are right, I add more logs and problem occurs in line:

    if not WinHttpAPI.SetOption(fSession, WINHTTP_OPTION_SECURE_PROTOCOLS,
       @WINHTTP_FLAG_SECURE_PROTOCOL_MODERN, SizeOf(WINHTTP_FLAG_SECURE_PROTOCOL_MODERN)) then
      RaiseLastModuleError(winhttpdll,EWinHTTP);

How resolve this issue?

#92 Re: mORMot 1 » Problem with WinHTTP client - error 87 » 2017-12-12 14:28:31

I don't have Vista, problem occurs on our customer station (I have access only to his log file).
Yes, I use SSL connection. I don't use proxy.

#93 Re: mORMot 1 » Problem with WinHTTP client - error 87 » 2017-12-11 13:36:31

First report from customer:

14:20:44.20: System: Windows Vista SP2 (6.0.6002)
14:20:50.20: mORMot [ver.1.18.4061] client TSQLHttpClientWinHTTP test....
14:20:51.20: Trying connect to REST server ...
14:20:51.20: 20171211 13205102  +    mORMotHttpClient.TSQLHttpClientWinHTTP(03A54630).CallBackGet Companies/Timestamp
14:20:51.20: 20171211 13205112 + mORMotHttpClient.TSQLHttpClientWinHTTP(03A54630).007F7FBC 
                                                       mORMotHttpClient.TSQLHttpClientGeneric.InternalURI (525) 
14:20:51.20: 20171211 13205122 EXC EWinHTTP ("winhttp.dll error 87 (Parametr jest niepoprawny)") at 00694735 
                                                          SynCrtSock.RaiseLastModuleError (3656)  stack trace API 00694735 
                                                          SynCrtSock.RaiseLastModuleError (3656) 0069ACD5 
                                                          SynCrtSock.TWinHTTP.InternalConnect (10025) 00699631 
                                                          SynCrtSock.THttpRequest.Create (9423) 007F9CA8 
                                                          mORMotHttpClient.TSQLHttpClientRequest.InternalCheckOpen (916) 007F7FCC 
mORMotHttpClient.TSQLHttpClientGeneric.InternalURI (527) 007AB0BA mORMot.CallInternalURI (37775) 

"Parametr jest niepoprawny" in polish mean "The parameter is incorrect"

#94 Re: mORMot 1 » Problem with WinHTTP client - error 87 » 2017-12-09 11:06:15

Ok, I will collect this data on monday

#96 Re: mORMot 1 » Help for new user » 2017-12-08 20:32:47

It looks like you do not understand what a mORMot is. And maybe you do not need it.

#98 mORMot 1 » Problem with WinHTTP client - error 87 » 2017-12-08 18:48:09

jaclas
Replies: 17

I discovered that on some systems (our customers) client  on WinHTTP get error:

EWinHTTP ("winhttp.dll error 87 (The parameter is incorrect)")

but WinINet client works properly, why?

#99 Re: mORMot 1 » TSQLHttpClientCurl - how use » 2017-12-08 11:26:52

I detect that on some systems client on WinHTTP get error:

"winhttp.dll error 87, The parameter is incorrect error"

but WinINet client works properly, why?

#100 Re: mORMot 1 » TSQLHttpClientCurl - how use » 2017-12-07 19:09:21

I write diagnostic app for our clients who have a various problems with connecting to server. The app connects through TSQLHttpClientWinHTT, TSQLHttpClientWinINet and sockets by Indy TIdTCPClient and reports messages to file.
I thought I could use curl based class too. If no then sorry :-)

Board footer

Powered by FluxBB